2015年7月8日 星期三

Git

Git : 分散式的版本控管系統。

Git 保留了所有的 history, commits, branches 記錄在本地端,所以跟傳統中央控管的方式不同,不需透過連到主機的方式,即可使用和查詢。

Git 的創造者是 Linus Torvalds , 同時也是 linux 核心的發起者。



了解 Git

Git 可分為 local 本地端和 remote 遠端。
像 CVS 或是 SVN 的相關記錄和程式碼都是放在中央主機上。但是 Git 是分散式的架構。所以可以有很多的分身。
每個分身都是獨立的個體。而獨立的個體會活在 local 本地端的資料夾中。

一般程式碼寫完之後,接著會做 add , commit , update , merge 等動作,讓程式碼進到版本控管中。
CVS or SVN 都是要跟中央主機打交道。但是 Git 是跟自己本地端的分身打交道。
所以 Git commit 完,只有自己看的到。如果要跟別人協同合作,還須多做 push , pull 的指令,讓相關程式碼合併到 Git 遠端的分身。
(在 Git 的世界裡,每個人都可以是老大)。







Git local 指令

1. 開始第一個 git repository  :  git init XXXXX  (在目前位置下建立一個 Git 專案 XXXXX)
2. 新增檔案到 git index file  :  git add XXXX.java  (將資料送到 index 資料庫中)
3. 送交檔案到 git repository  :  git commit --message '註解'  (送交檔案到 Git 專案)
   第一次的檔案一定要先  add , 接著  commit
4. 更新 git repository 檔案  :  沒有指令。 (在本地端開發,除了被惡搞外,程式碼應該是最新的吧)
5. 從不同 branches 或是版本取檔案 : git checkout
6. 產生 branches(分支)  : git branch
7. 合併分支 : git merge

git 強調註解。最好註解寫的像一封 mail。用 gitx 的介面看,註解展開的像 mail。
所以不同於傳統用人名當帳號的方式,git 用 email 帳號當帳號。


Git remote 指令


1. 送交到遠端位置 :  git push
2. 將遠端的程式碼 merge  回來 :  git fetch , git pull
3. 將遠端資料 copy 回來(產生分身) : git clone
4. 讓本地端資料在遠端產生目錄(產生分身)  : git remote



2014年9月23日 星期二

WebService using JAX-RPC style with Spring & Axis 1

Web Service 使用 RPC-style 的方式,只剩很古早的 Axis 1 (最後版本為 1.4) 還支援。
如果需要產生此種 style 的 Web Service , 可參考以下方法 (參考 Pro Spring 作法)。

1. 建立 maven project

2. 加上 dependency

         <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-discovery</groupId>
            <artifactId>commons-discovery</artifactId>
            <version>0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis-jaxrpc</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis-saaj</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>2.2</version>
        </dependency>




3. 產生 interface

package org.ws;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface RemoteHelloWorld extends Remote {
 String getMessage() throws RemoteException;
}
4. 產生 implement class

package org.ws.impl;

import java.rmi.RemoteException;

import org.springframework.remoting.jaxrpc.ServletEndpointSupport;
import org.ws.RemoteHelloWorld;


public class JaxRpcHelloWorld extends ServletEndpointSupport implements RemoteHelloWorld {
    
 public String getMessage() throws RemoteException {
  
  return "Hello World";
 }

} 
5. 在 WEB-INF 下新增 server-config.wsdd 檔案 (Axis 使用)

<deployment xmlns="http://xml.apache.org/axis/wsdd/"
 xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 <handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper" />
 <service name="HelloWorld" provider="java:RPC">
  <parameter name="className" value="org.ws.impl.JaxRpcHelloWorld" />
  <parameter name="allowedMethods" value="*" />
 </service>
 <transport name="http">
  <requestFlow>
   <handler type="URLMapper" />
  </requestFlow>
 </transport>
</deployment>
6. 修改 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath*:ApplicationContext.xml</param-value>
 </context-param>
 
 <servlet>
  <servlet-name>context</servlet-name>
                <servlet-class>
                     org.springframework.web.context.ContextLoaderServlet
                </servlet-class>
                <load-on-startup>1</load-on-startup>
 </servlet>
 
 <servlet>
                <servlet-name>axis</servlet-name>
                <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
                <load-on-startup>2</load-on-startup>
        </servlet>

        <servlet-mapping>
         <servlet-name>axis</servlet-name>
                <url-pattern>/services/*</url-pattern>
        </servlet-mapping>

</web-app>
7. 開 server 看 wsdl
http://localhost:8080/xxxxxx/services/HelloWorld?wsdl

2013年2月9日 星期六

Java Code Quality Tools

From http://www.javacodegeeks.com/2012/10/java-code-quality-tools-overview.html

open source 的好優點也是缺點就是,一個問題可以找到很多解法。
但是因為也因為太多解法,所以要挑合適的 solution 必須花很多時間。

光光一個 Test 工具,就可以列出這麼多個。

要看完大概要花上一兩年吧。

這篇列出的Test Tool 大概比較著名的就是前幾個。

PMD , CheckStyle ,

2013年1月15日 星期二

Java 日期 Parse. DateFormat.setLenient

一般使用 Java 從字串轉成日期,通常會使用 SimpleDataFormat 做轉換。

例如:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


public class DataSample {
 
   public static void main(String[] args) {
      SimpleDateFormat sdf = new SimpleDateFormat();
      sdf.applyPattern("MM/dd/yyyy") ;
      try {
         Date d = sdf.parse("01/17/2013") ;
         System.out.println(d) ;
      } catch (ParseException e) {
        e.printStackTrace();
      }
   }
}

會得到
Thu Jan 17 00:00:00 CST 2013

這是再自然不過了。
但是如果你不小心給錯格式,那會怎樣? 例如 MM/dd/yyyy 給成了 yyyy/MM/dd , 你猜會怎樣?

答案會 beyond imagination 。直覺應該會出錯,但不會,而且會有一個日期跑出來!!!

Tue Sep 01 00:00:00 CST 184

哪怎麼辦?
在 DateFormat 有一個 method , 可以解決此問題。 setLenient
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


public class DataSample {
 
   public static void main(String[] args) {
      SimpleDateFormat sdf = new SimpleDateFormat();
      sdf.applyPattern("MM/dd/yyyy") ;
      sdf.setLenient(false);
      try {
         Date d = sdf.parse("2013/01/17") ;
         System.out.println(d) ;
      } catch (ParseException e) {
         e.printStackTrace();
      }
   }
}

會得到
java.text.ParseException: Unparseable date: "2013/01/17"
 at java.text.DateFormat.parse(DateFormat.java:357)
 at DataSample.main(DataSample.java:13)


2013年1月12日 星期六

Portal

什麼是 Portal。

簡單的說就是集合各類的網站的入口網站,行話叫做 web application(called "portlets") 的集合。
最著名的就是 igoogle , 或是 windows 8 都是這樣的概念。


進入 Portal 後,就可以透過這樣的介面,進入到不同的網站去,通常都是我們感興趣的內容。
而且這些內容會隨著時間而更新,所以不完全是被動的網頁。


每個獨立的網站,活在 Portal 下的,就稱為 Porlet。
而這些各自的 Porlet 內容,又會因為個人又有差異。例如天氣,Mail 等各自獨立的資訊都不同。
而為了達到傳遞各自不同的資訊,所以一些資訊的控制,如登入就顯得重要了。


為了達到這麼複雜的功能,需透過特別的 Portal Sever 來做控制,而每個個別的內容,又需要Porlet Container 來轉成特定的內容。Portal Server有幾個著名的例如 Liferay 分為 Community 和 Enterprise 版本。Jboss 的 GateIn


在 Java 的標準裡,是有定義 Portal 的。JSR 168 定義 Portal 1.0 , JSR 268 定義 Portal 2.0


題外話:
iGoogle 一度是我的首頁,今天再去看的時候突然發現此好用的功能要 sunset 了,猜想因為要推銷自家的 Chrome, 才出此下策吧。



2013年1月2日 星期三

Grails 2.2









Grails 又升級了!
最近的升版都很快,才剛適應 2.1 , 2.2 又來了。

根據官網的說法,升級重點如下
http://grails.org/doc/2.2.x/guide/introduction.html#whatsNew22

1.Namespace support


Bean names for Service artifacts provided by a plugin are now prefixed with the plugin name

grails 有一個很討厭的東西,就是 groovy 的 class name 不能重複,即使 package name 不一樣也不行。不然 runtime 時常常會給你驚喜!!
因此 Grails 決定如果名稱衝突的話,將會加上 plugin name 成為預設的 Serivce or Bean name,  讓 DI 找到對的 class。

Domain Class 的 Bean name 有了 plugin name , 將會影響建 DB 的 table name。當然也是可以設定的。

2.Forked Tomcat Execution


Grails 2.2 supports forked JVM execution of the Tomcat container in development mode.

嗯,我想最大的好處就是減少 memory 使用量,跟減少 Jar 檔衝突的可能。

3.SQL Projections In Criteria Queries

 

4.Groovy 2

最大的進展就是從 Groovy 1.8 跳到 Groovy 2 。除了對JDK 7  的 Support 外(Project coin),一些 enhancement 都有針對 Groovy 太動態,而產生無法管教的問題做一些修正。
像是static type checking @TypeChecked ,  或是 Static compilation @CompileStatic

 

 

2012年12月21日 星期五

User Thread and Daemon Thread

Java 的 Thread 分兩種:
User Thread(Defalut) 和 Daemon Thread.

User Thread 被停止時,JVM 會看是否還有其他 User Thread 在執行,如果有其他 User Thread 在執行,則該 Thread 不會被停止。

Daemon Thread 是一個背景執行緒,並且會跟著創造他的 Thread (father Thread) 的生命週期。

程式裡的差別就是 Thread 內的 setDaemon(boolean) 方法。(此 method 要在 Thread.start() 之前就要決定了)

以下的程式碼可以試著把 setDaemon 打開測試。 也可以把 interrupt 打開測試。

public class TryThread extends Thread{
 private String lastname;
 private long delay;
 
 public TryThread(String lastname, long delay) {
  
  this.lastname = lastname;
  this.delay = delay;
  //this.setDaemon(true);
 }
 
 public static void main(String[] args){
  Thread t1 = new TryThread("cristo", 2000L);
  Thread t2 = new TryThread("eric", 3000L);
  Thread t3 = new TryThread("john", 5000L);
  System.out.println("Press Enter...");
  t1.start();
  t2.start();
  //t3.setDaemon(false);
  t3.start();

  try{  
   System.in.read();
   System.out.println("Enter pressed...");
   //t1.interrupt();
   //t2.interrupt();
   //t3.interrupt();
  }catch(Exception e){
   System.out.println(e);
  }
  System.out.println("Enter main()");
  return;
 }

 @Override
 public void run() {
  try{
   while(true){
    System.out.println(lastname);
    sleep(delay);
   }
  }catch(Exception e){
   System.out.println(e);
  }
 }
}
以上參考 Ivor.Hortons.Beginning.Java.Java.7.Edition. CH16 Understanding Threads