假設(shè)你是一個J2EE程序員,你正在使用struts2+spring2+hibernate3的時尚標(biāo)準(zhǔn)組合來開發(fā)一個項(xiàng)目。某天,你的項(xiàng)目經(jīng)理告訴你,當(dāng)前項(xiàng)目需要開發(fā)一個新功能,需要系統(tǒng)來定時來執(zhí)行一段代碼,比如每天大半夜定時進(jìn)行前一天的數(shù)據(jù)統(tǒng)計(jì)并且插入數(shù)據(jù)庫。如果你部署的系統(tǒng)是Linux并且你熟悉crontab而且你打算那么麻煩地去干,我當(dāng)然沒話可說。否則在你google和baidu了一會兒之后,你必然會想到可以使用的quartz來和spring集成起來做這件事。
比如,先把需要干的活兒寫在一個類的一個方法里面:
public class ScheduleWorker {
public void doDailyWork() {
System.out.println("今日統(tǒng)計(jì)完畢!");
}
}
然后,配置spring的applicationContext.xml如下:
0 0 * * * ?
然后編譯上傳(別忘了上傳更新的applicationContext.xml還有quartz.jar,一般都在spring解開的包的lib/quartz目錄下面)。你重新啟動你的tomcat(也可能是resin或者其他什么東西),然后,不出意外地,發(fā)現(xiàn)如下錯誤:
ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’jobDetail’ defined in ServletContext resourc
e [/WEB-INF/classes/applicationContext-service.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodErr
or: org.apache.commons.collections.SetUtils.orderedSet(Ljava/util/Set;)Ljava/util/Set;
如果你經(jīng)驗(yàn)比較豐富,你會去找你部署的服務(wù)器的WEB-INF/lib下面是不是存在commons-collections的jar包,然后你很驚奇地發(fā)現(xiàn)它的確在那里,你會很困惑。
如果你經(jīng)驗(yàn)十分豐富,你知道了commons-collections.jar的確存在于classpath里面,你知道引起NoSuchMethodErr的原因很可能是部署服務(wù)器上的commons-collections.jar的版本過低,在quartz調(diào)用的時候不存在而導(dǎo)致的,于是你會去檢查WEB-INF/lib下面的commons-collections.jar的版本,然后你還是會很驚奇地發(fā)現(xiàn)它的版本是3.2,并且在這個jar包里面的確存在org.apache.commons.collections.SetUtils這個類,并且方法orderedSet也存在,你還是會很困惑。
如果你經(jīng)驗(yàn)非常豐富,你知道了引起上面這種情況的原因是系統(tǒng)的classloader先加載了其他地方低版本的commons-collections里面的org.apache.commons.collections.SetUtils類,導(dǎo)致WEB-INF/lib下面的commons-collections.jar里面的同名類沒有被加載所導(dǎo)致的。于是你就到處去找另外的commons-collections.jar,在WEB-INF/lib你可能會找到一個,包括common/lib等等地方,如果你是jdk6,考試,大提示還有可能在jdk的ext目錄下找到。刪掉老版本的commons-collections.jar,重啟tomcat,發(fā)現(xiàn)問題依舊,你繼續(xù)找。但是皇天不負(fù)有心人,你啥都沒找到,整個jdk和整個tomcat下面,你整個搜索了一番,只有這么一個commons-collections.jar。你依然會很困惑。
不賣關(guān)子了。解決問題的辦法:刪除WEB-INF/lib/checkstyle-all.jar,重新啟動tomcat,問題解決。
在hibernate3的lib目錄下,存在commons-collections-2.1.1.jar和checkstyle-all.jar,一般我們都是直接上傳到WEB-INF/lib,前者不必說,版本太老而被classloader先加載了,按說刪了問題應(yīng)該解決了,但是為什么必須刪掉checkstyle-all.jar問題才能正式解決呢。拿WinRAR打開checkstyle-all.jar一看你就知道了,里面赫然有org.apache.commons.collections.SetUtils這個類,并且,它是老版本的!
這也太可惡了,明明叫checkstyle-all.jar,里面為啥還包含commons-collections的東西……而且還是老調(diào)牙的版本。另外,如果你覺得checkstyle-all.jar或許還有點(diǎn)什么用處,可以用WinRAR解開之后把commons-collections的包和類去掉,然后重新打包上傳。
其實(shí)問題的根源在于:hibernate3使用老版本(2.1.1)的commons-collections及包含它的checkstyle-all.jar,而spring2.5使用新版本(3.2)的commons-collections以及需要3.2版本commons-collections的quartz。
比如,先把需要干的活兒寫在一個類的一個方法里面:
public class ScheduleWorker {
public void doDailyWork() {
System.out.println("今日統(tǒng)計(jì)完畢!");
}
}
然后,配置spring的applicationContext.xml如下:
然后編譯上傳(別忘了上傳更新的applicationContext.xml還有quartz.jar,一般都在spring解開的包的lib/quartz目錄下面)。你重新啟動你的tomcat(也可能是resin或者其他什么東西),然后,不出意外地,發(fā)現(xiàn)如下錯誤:
ERROR [org.springframework.web.context.ContextLoader] - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’jobDetail’ defined in ServletContext resourc
e [/WEB-INF/classes/applicationContext-service.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodErr
or: org.apache.commons.collections.SetUtils.orderedSet(Ljava/util/Set;)Ljava/util/Set;
如果你經(jīng)驗(yàn)比較豐富,你會去找你部署的服務(wù)器的WEB-INF/lib下面是不是存在commons-collections的jar包,然后你很驚奇地發(fā)現(xiàn)它的確在那里,你會很困惑。
如果你經(jīng)驗(yàn)十分豐富,你知道了commons-collections.jar的確存在于classpath里面,你知道引起NoSuchMethodErr的原因很可能是部署服務(wù)器上的commons-collections.jar的版本過低,在quartz調(diào)用的時候不存在而導(dǎo)致的,于是你會去檢查WEB-INF/lib下面的commons-collections.jar的版本,然后你還是會很驚奇地發(fā)現(xiàn)它的版本是3.2,并且在這個jar包里面的確存在org.apache.commons.collections.SetUtils這個類,并且方法orderedSet也存在,你還是會很困惑。
如果你經(jīng)驗(yàn)非常豐富,你知道了引起上面這種情況的原因是系統(tǒng)的classloader先加載了其他地方低版本的commons-collections里面的org.apache.commons.collections.SetUtils類,導(dǎo)致WEB-INF/lib下面的commons-collections.jar里面的同名類沒有被加載所導(dǎo)致的。于是你就到處去找另外的commons-collections.jar,在WEB-INF/lib你可能會找到一個,包括common/lib等等地方,如果你是jdk6,考試,大提示還有可能在jdk的ext目錄下找到。刪掉老版本的commons-collections.jar,重啟tomcat,發(fā)現(xiàn)問題依舊,你繼續(xù)找。但是皇天不負(fù)有心人,你啥都沒找到,整個jdk和整個tomcat下面,你整個搜索了一番,只有這么一個commons-collections.jar。你依然會很困惑。
不賣關(guān)子了。解決問題的辦法:刪除WEB-INF/lib/checkstyle-all.jar,重新啟動tomcat,問題解決。
在hibernate3的lib目錄下,存在commons-collections-2.1.1.jar和checkstyle-all.jar,一般我們都是直接上傳到WEB-INF/lib,前者不必說,版本太老而被classloader先加載了,按說刪了問題應(yīng)該解決了,但是為什么必須刪掉checkstyle-all.jar問題才能正式解決呢。拿WinRAR打開checkstyle-all.jar一看你就知道了,里面赫然有org.apache.commons.collections.SetUtils這個類,并且,它是老版本的!
這也太可惡了,明明叫checkstyle-all.jar,里面為啥還包含commons-collections的東西……而且還是老調(diào)牙的版本。另外,如果你覺得checkstyle-all.jar或許還有點(diǎn)什么用處,可以用WinRAR解開之后把commons-collections的包和類去掉,然后重新打包上傳。
其實(shí)問題的根源在于:hibernate3使用老版本(2.1.1)的commons-collections及包含它的checkstyle-all.jar,而spring2.5使用新版本(3.2)的commons-collections以及需要3.2版本commons-collections的quartz。

