之前的Opendoc中沒(méi)有涉及過(guò)此部分的內(nèi)容,maven又是現(xiàn)在非常流行的java的工具,再加上到目前為止搭建OSGi Maven開(kāi)發(fā)和部署的環(huán)境還是比較的麻煩,覺(jué)得有必要寫(xiě)篇這樣的blog,:),在這篇blog中來(lái)看下如何搭建一個(gè)比較好用的OSGi Maven開(kāi)發(fā)和部署環(huán)境,看看我在搭建一個(gè)這樣的環(huán)境中的痛苦歷程。
首先說(shuō)下我期望的OSGi Maven開(kāi)發(fā)/部署的環(huán)境:
1、META-INF中的manifest.mf文件可以自己控制;
Eclipse對(duì)插件工程的開(kāi)發(fā)支持的很好了,在IDE中可以很方便的去修改這個(gè)manifest.mf,所以還是自己控制更爽,當(dāng)然,打包的時(shí)候需要打入自己控制的這個(gè)manifest.mf。
2、在mvn eclipse:eclipse生成的.classpath中,能夠不把所依賴(lài)的bundle的jar包放進(jìn)去;
因?yàn)樵贠SGi環(huán)境中,已經(jīng)不再通過(guò)直接在project的classpath中依賴(lài)其他bundle的jar了來(lái)調(diào)用其他bundle中的package,而是通過(guò)在manifest.mf中增加import-package這樣的方式,所以不能再把依賴(lài)的bundle的jar打到classpath里了,否則會(huì)很奇怪,當(dāng)然,這也源于eclipse有個(gè)很好的插件開(kāi)發(fā)環(huán)境,讓你可以在不依賴(lài)bundle jar的情況下直接寫(xiě)依賴(lài)其他bundle的package的代碼。
3、在mvn clean package的時(shí)候能夠把需要依賴(lài)的jar打到bundle jar中,并和META-INF/Manifest.mf文件中的Bundle-Classpath是匹配的;
在某些bundle中可能會(huì)依賴(lài)一些jar,在META-INF中通常會(huì)去指定依賴(lài)的這些jar,放入bundle-classpath中,因此要求在打包的時(shí)候能夠把這些依賴(lài)的jar打入相應(yīng)的路徑下。
說(shuō)完想法后,首先想到的是在OSGi界中支持maven環(huán)境的大名鼎鼎的maven-bundle-plugin(
http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html),maven-bundle-plugin基于Peter寫(xiě)的bnd實(shí)現(xiàn),不說(shuō)廢話(huà)了,按照自己期望的環(huán)境來(lái)使用maven-bundle-plugin進(jìn)行搭建:
步驟一
按照上面頁(yè)面的指導(dǎo),在pom.xml中增加maven-bundle-plugin先,接著按照自己的想法,要自己控制manifest.mf,于是在plugin的configuration中增加:
<_include>META-INF/MANIFEST.MF</_include>
滿(mǎn)心歡喜的等待著完美的結(jié)果,可惜....不如人意呀,打包出來(lái)的jar里面的MANIFEST.MF已經(jīng)物是人非了,完全不是自己控制的那個(gè),插件給你自動(dòng)的加上了一堆的import-package、private-package、export-package,我知道這個(gè)插件是基于bnd來(lái)寫(xiě)的,但沒(méi)想到竟然連自己控制的權(quán)力都不給我了,完全仍然是通過(guò)bnd來(lái)計(jì)算出import-package、private-package什么的;
步驟二
好,在傷心過(guò)后接著仔細(xì)看,還好,在plugin的configuration中可以自己指定export-package、private-package這些,于是繼續(xù)欣喜的使用,這兩個(gè)倒是控制住了,但....import-package自己是不能控制的,這個(gè)是不行的,這樣就導(dǎo)致了必須同時(shí)自己維護(hù)pom.xml以及project中的META-INF/MANIFEST.MF,讓它們保持一致,否則可能導(dǎo)致打出來(lái)的包和你在project中運(yùn)行的表現(xiàn)不一致,并且bnd計(jì)算出來(lái)的import-package并不是我想要的,有點(diǎn)太復(fù)雜了,還是自己控制比較好;
步驟三
傷心到極點(diǎn)了,其實(shí)到目前為止,已經(jīng)可以確定maven-bundle-plugin,也是OSGi maven中唯一的插件,不能滿(mǎn)足我的需求,不過(guò)還是繼續(xù)看看這個(gè)插件其他方面的表現(xiàn),驚喜的發(fā)現(xiàn)有一點(diǎn)倒是做的不錯(cuò)的,它支持一個(gè)
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>,有了這個(gè)標(biāo)簽后,它可以直接把依賴(lài)的jar打入bundle jar包中,并且相應(yīng)的自動(dòng)在bundle-classpath中加上了,這點(diǎn)倒是不錯(cuò)的,看起來(lái)與我期望的環(huán)境的第3點(diǎn)是比較匹配的,可惜了。
還有就是,很當(dāng)然的,它沒(méi)法做到控制mvn eclipse:eclipse時(shí)生成的.classpath不包含bundle jar的引用。
按照上面的三個(gè)步驟,總結(jié)下,有些時(shí)候智能是好事,但maven-bundle-plugin就是過(guò)于智能了,為什么不給點(diǎn)權(quán)力給使用者呢,因此這個(gè)插件要提升到完全可用的情況的話(huà),還需要提供下讓使用者自己控制MANIFEST.MF的權(quán)力,相信這點(diǎn)要做到并不困難,而且做到這點(diǎn)后基本也就可以使用了。
繼續(xù)尋找,于是靜心分析了下自己的需求,貌似可以自己通過(guò)maven現(xiàn)有的幾個(gè)插件來(lái)達(dá)成自己的愿望,于是開(kāi)始了組合拳:
1、MANIFEST.MF文件自己控制
不就是要自己控制這個(gè)文件嘛,OK,干脆,就只用maven-jar-plugin,這個(gè)插件允許指定所使用的MANIFEST.MF文件,于是,嘗試著在這個(gè)plugin的configuration中增加:
<archive>
<manifestFile>META-INF/MANIFEST.MF</manifestFile>
</archive>
恩,很順利,開(kāi)門(mén)紅呀,打出來(lái)的jar包中的MANIFEST.MF文件就是自己的那個(gè)。
2、mvn eclipse:eclipse生成的.classpath中要去掉bundle jar的依賴(lài)
對(duì)于我這么一個(gè)對(duì)maven不是那么熟悉的人來(lái)講,這個(gè)有點(diǎn)復(fù)雜,于是不斷的google,甚至是翻看了maven-eclipse-plugin的源碼...
最終終于功夫不負(fù)有心人,找到一個(gè)簡(jiǎn)單的辦法:
首先將工程方式指定為pde,也就是eclipse插件工程,在maven-eclipse-plugin的configuration配置中增加<pde>true</pde>;
然后在pom.xml中將不希望生成到.classpath中依賴(lài)的scope指定為provided;
心驚膽戰(zhàn)的開(kāi)始運(yùn)行mvn eclipse:eclipse,OH YEAH!,成功!
ps: 另外也可以通過(guò)在maven-eclipse-plugin的configuration中增加exclude配置,來(lái)將某些依賴(lài)從.classpath中去掉,當(dāng)然,這方法沒(méi)有上面的易用。
3、在mvn clean package的時(shí)候能夠把需要依賴(lài)的jar打到bundle jar中,并和META-INF/Manifest.mf文件中的Bundle-Classpath是匹配的;
恩,這點(diǎn),印象中貌似maven是有支持的,于是繼續(xù)開(kāi)始找,終于找到了maven-dependency-plugin(之前還找到了一個(gè)maven-shade-plugin,也很帥,不過(guò)不滿(mǎn)足需求),通過(guò)這個(gè)插件可以把需要的依賴(lài)的jar都復(fù)制到某個(gè)指定的目錄中去,但記得把這個(gè)指定的目錄加入到maven-jar-plugin的resources目錄里面去,否則這些jar文件是不會(huì)出現(xiàn)在你的bundle jar里的。
OK,通過(guò)上面這套組合拳,終于達(dá)成了目的,看來(lái)有必要找個(gè)時(shí)間寫(xiě)個(gè)好用點(diǎn)的maven的OSGi插件,否則真的忒折騰了,上面這個(gè)方法仍然有幾個(gè)痛苦的地方:
1、如果你的bundle中需要export其中依賴(lài)的lib的package的話(huà);
mvn eclipse:eclipse之后你會(huì)發(fā)現(xiàn)其他bundle即使import了這個(gè)package,也會(huì)調(diào)用不到,這里的原因在于生成的.classpath中所依賴(lài)的那個(gè)lib的exported屬性沒(méi)有設(shè)置為true,google了maven eclipse插件,貌似這是它的一個(gè)缺失的功能,因此在目前只能是mvn eclipse:eclipse后,再到build path里把這些lib exported出去。
2、還是得在插件的pom.xml中配置所依賴(lài)的其他的bundle;
這是為了讓你在mvn clean package的時(shí)候能通過(guò),這點(diǎn)還是挺郁悶的,如果能自己去找到的話(huà)就好了(Felix構(gòu)建bundle repo是有潛質(zhì)做到這點(diǎn)的),:),這樣導(dǎo)致了在每次在import package后,還得記得去修改了pom,否則的話(huà)在eclipse compile什么都正常,到了maven里就掛了。
因此,如果能解決上面兩點(diǎn)的話(huà),那將更加完美。