Friday, June 22, 2012

Spring classpath*: vs classpath:

- classpath: will return first one found
- classpath: will use the first classpath from classloader?  http://blog.carbonfive.com/2007/05/17/using-classpath-vs-classpath-when-loading-spring-resources/  ,  http://tech-tauk.blogspot.hk/2010/04/difference-between-classpath-classpath.html
- classpath*: will return all resources from all classpath even they are having same name
- classpath*: + antstyle for no base directory (e.g. classpath*:**/foo.xml) can only find resources on filesystemp, not in JARs etc.

Friday, November 13, 2009

Java CLI Library

Some Java command line parsing library available.

Programmatic-style
Options structure are created programmatically, so do the parameter retrieval.

Commons CLI
Workable and can fulfill most common usage scenario.
http://commons.apache.org/cli/

Commons CLI2
Redesign from Commons CLI. Sounds promising and fixes a lot of design flaws or deficit of CLI 1.x. However it seems abandoned and progress is slow.
http://commons.apache.org/sandbox/cli2/

DPML Commons CLI2 fork
A fork of original CLI2 project
http://www.dpml.net/util/cli/index.html

JArgp
http://jargp.sourceforge.net/

jcmdline
http://jcmdline.sourceforge.net/

GNU getopt port
http://www.urbanophile.com/arenn/hacking/download.html

JArgs
http://jargs.sourceforge.net/

JCommando
http://jcommando.sourceforge.net/

JSAP
http://www.martiansoftware.com/jsap/


Auto-binded style
Options structure are done declaratively. Result are transformed and binded to result object.
Most of them are making use of Java5 Annotation.

Args4J
https://args4j.dev.java.net/

parse-cmd
http://code.google.com/p/parse-cmd/

CLI Parser
http://code.google.com/p/cli-parser/

Jewel CLI
http://jewelcli.sourceforge.net/

Tuesday, June 24, 2008

Maven: deploy 向另一 repository

如果某 POM 指明了 deployment 的 target repository, 我想 deploy 往另一個 repository (比如 download 了 third party 的 source, deploy 往自己的 repository), 可以:

mvn deploy -DaltDeploymentRepository=serverId::default::ftp://host/path

serverId 是在 settings.xml 的 server
ftp 那位置是 protocol, 比如 ftp, scp, file 等.

Friday, May 30, 2008

找出 jar 之間的 dependency

有個好工具能找出一堆 Jar 之間的相互 dependency, 當你要為一堆 third-party JAR 寫 POM deploy 上 maven 的話, 這尤其有用. 這工具叫 jarjar. 找 dependency 只是 jarjar 其中一個小功能.

最基本用法 (on windows, 在 Unix 請改動最後那段 classpath):
> java -jar jarjar.jar find jar a.jar;b.jar;c.jar
C:\tmp\a.jar -> C:\tmp\b.jar
C:\tmp\b.jar -> C:\tmp\c.jar

這樣你就很容易明白, a depends on b, 然後 b depends on c.

可以用 mustang-style 的 classpath syntax:
> java -jar jarjar.jar find jar "./*"


Wednesday, May 14, 2008

Maven 筆記 (1) - Maven 與 Ant 的分別

這裡說的 Maven 是 Maven2

1) Ant 可以說是一個 script,當中要把每個 step 寫出。Maven 是 Declarative 的,不是告訴 build tools "怎樣做",而是告訴 build tools "做什麼"。
例如在 Ant 中你要寫:建立 output directory,然後 compile 某 source directory 裡的 source 往 output directory, 再 copy 某些 resource files 到 output directory, 然後再 jar 成什麼什麼名字。
在 Maven 中則只是宣告:source directory 在哪裡,output directory 在哪,我的 project 要 build 成 jar (還是 war/ear etc),我的成品要叫什麼名字。

2) Ant 對於每樣做的事都需要逐一 Config 好。Maven 則是主張 Convention over Configuration。有些東西定好了 Convention (慣例) 後,只要你跟從該慣例,便不需額外做 configuration。
比如,如果我的 source directory 跟從了 maven 所定的慣例,我的 POM.xml (Maven 的 "build script") 只需要定義這個 project 的名稱等,連 compile 的 source directory 都不需設定,就已經能交給 maven 去了:http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Minimal_POM

Maven 與 Ant 整個設計哲學簡直是南轅北轍,孰佳孰劣很難比較。但綜觀而言,對於一般的 project, 使用 Maven 能逼使你把 project 結構想好 (一個混亂的結構與依賴關係的 project 套用 Maven 會很困難)。Maven 的 pom.xml 比起 Ant 的 build.xml 看起來更一目瞭然。但一些特別的 step, 在 Ant 中可能寫幾句就可以達到,在 Maven 中,要是沒有適當的 plugin, 做起來可能很麻煩。

Friday, March 28, 2008

Generic DAO (3)

基本的 Generic DAO 只會找對應的 named query 去 invoke. 但有些情況下這功能未必合用,所以我便加了四個特殊 annotation 來提供更廣的應用。這四個都是 method-based 的annotation。用時只要在 interface 或 implementation class 的相關 method 前面 annotate 就可以
1) @Query
基本上與原本的功能相若。可以讓developer 直接寫 HQL, 或註明某特定 named query。Example:
public interface PersonDao extends GenericDao<Person, Long> {
___ @Query(query="select p from Person p where p.name = :name")
___ List<Person> findByNameWithProvidedQueryString(@Param("name") String personName);
}


2) @SqlQuery
當初設計是利用 Hibernate 的 Native Query, 讓 developer 可以做到基本的應用,但後來發覺 named native query 做的和這個差不多。
public interface PersonDao extends GenericDao<Person, Long> {
___ @SqlQuery(
_______ query = "select p.* from PERSON p where p.name = :name",
_______ entity = { @SqlEntity(alias = "p", entityClass = Person.class) }
___ )
___ List<Person> findBySqlNamedParam(@Param("name") String personName);
}

3) @QueryByCriteria
Hibernate 提供了一個動態生成 query 的機制,叫 Query By Criteria (QBC),QBC 還有一個特別應用叫 Query By Example (QBE)。這裡我希望有一個簡單的方法讓 developer 能寫到基本的 QBC 應用。(由於 Annotation 不能 Recursive, 所以比較複雜的 QBC, 比如 nested Criteria 暫時還是沒法用 annotation 表達)
public interface PersonDao extends GenericDao<Person, Long> {

___ @QueryByCriteria(
_______ criteria = @QbcCriteria (
___________ alias={@QbcAlias(aliasName = "n", field = "names")},
___________ restriction = {
_______________ @QbcRestriction(field = "n.name", operator = LIKE, param = "name", matchStyle = MatchStyle.START)
___________ }
_______ ),
_______ resultTransformer = QueryResultTransformer.DISTINCT_ROOT_ENTITY
___ )
___ public List<Person> findDistinctPersonByQbc(@Param("name")String name);
}


4) @Implemented
上面的 annotation-based query builder 如果都不能達到想要的效果,就利用這 annotation 讓 user 自己弄個 implementation class, 再在裡面自己 implement 這個 method 好了。

大致上,是 interceptor 攔截 find* 的 method call, 便 invoke GenericDao Impl 的 executeFinder() method。而 executeFinder 則會嘗試找尋究竟這次 invoke 的 method 有什麼annotation (先找 implementation class, 沒有上述四個 annotation 再找 interface), 然後根據不同的 annotation 執行不同的 logic。比如是 @Query 或 @SqlQuery, 便嘗試解拆 annotation 並執行對應的 Query/SqlQuery;@QueryByCriteria 的話,便建立並執行 Criteria;@Implemented 的話便什麼都不做,直接 invoke implementation class 的 method。

除了上面四個 finder method annotation,還有 parameter level 的 annotation 來配合:
1) @Param
用來為 method parameter 命名,用以 bind 到 query 的 named parameters, 又或者用來於 @QueryByCriteria 裡面指明某 parameter 時用到。

2) @MaxResults
用於 annotate int 的 parameter。代表 return 多少筆 result。

3) @FirstResult
用於 annotate int 的 parameter。代表 return 的第一筆 result 是整體的第幾筆。@MaxResults 和 @FirstResult 通常是兩者配合,用來作 pagination。Generic DAO 的 execute finder 處理時其實只是把值塞到 Query/SQLQuery/Criteria 的 setFirstResult() 和 setMaxResults()。

另外如果有 parameter 的 type 是 EnquiryParam 的話會有特別處理。EnquiryParam 當中可以為 enquiry 定義很多不同的東西,包括
1) Sorting fields 及其 sorting 方向
2) 同樣可以定義 first result 和 max results
3) like 比對時用什麼方法比對(QBC 時有效),是整個字段 match, 還是 match anywhere, 還是 match 開始位置。
4) 字串比對時 match case 還是 ignore case(QBC 時有效)。

至於怎樣達成這些功能,因為 code 實在太長,就不貼出來了,反正 idea 比較重要(遲些有機會才整理出來吧)。

Thursday, February 14, 2008

Spring Batch 記錄

1) SimpleJobLauncher default 用 SyncExecutor. 所以 jobLauncher.run(job, jobParam) 會等 job 跑完才 return. 可以在 app context config inject Async Task Executor (or Thread Pool Executor etc). 這樣 SimpleJobLauncher#run() 便會立刻 return JobExecution.

2) 暫無 completion event 之類. 要自己做 aop wrap around Job.execute() or Step.execute()