Bundle Classloader初探
问题
SMB Blueprint后,又有另一个项目需要, 但SMB文件不是放到服务器上,而需要SCP到另一台Linux机器上。 于是直接使用Camel的SCP组件:jsch, (http://camel.apache.org/jsch.html) 于是直接改上Router
<!-- Basic Bean Definitions--> <bean id="fileStore" class="org.apache.camel.processor.idempotent.FileIdempotentRepository"> <!-- the filename for the store --> <property name="fileStore" value="/tmp/smb/.igsIdempotent.dat"/> <!-- the max filesize in bytes for the file. Camel will trunk and flush the cache if the file gets bigger --> <property name="maxFileStoreSize" value="512000"/> <!-- the number of elements in our store --> <property name="cacheSize" value="250"/> </bean> <bean id="smb" class="org.apacheextras.camel.component.jcifs.SmbComponent"/> <!-- <bean id="foo" class="foo.bar.Baz"> <property name="simpleProperty" value="Hello World" /> <property </bean> --> <!-- Osgi Service Related --> <!-- Exposing Services : ... References to Services : <reference id="referenceId" availability="optional" interface="foo.bar.IBaz"/> --> <camelContext trace="false" xmlns="http://camel.apache.org/schema/blueprint"> <camel:route> <camel:from uri="smb://domain;username@ip/850/?password=password&useFixedDelay=true&delay=10000&runLoggingLevel=debug&noop=true&idempotentRepository=#fileStore&antInclude=*.CMS"/> <camel:log message="file: ${header.CamelFileName}"/> <camel:to uri="scp://10.10.5.13/mnt/edi/${header.CamelFileName}?username=igsuser"/> </camel:route> </camelContext>
直接放到Karaf容器跑,因为SMB组件 Camel-extra 版本为2.15.0, 与Camel的版本2.17.3不一致辞, 使用idempotentRepository 的Bean就直接出错了,
解决方案
第一时间,当然是想保持Camel-extra/Camel 的版本一致, Talend默认的运行环境使用的是2.17.3, 只要将Camel-extra版本升到2.17.3就可以了。 不过经过多方努力,在Maven repo上始终找不到, 查找github上的Source code, https://github.com/camel-extra/camel-extra, 最新版本为2.18.0-SNAPSHOT, 依赖于Camel的2.18.0, 并且是没有2.17.x分支,多次折腾后放弃。
以Bundle/Jar方式运行
那只能将Camel版本降至2.15.0, 对Bundle的Classloader不熟,似乎也只能这条路可以走,参考了Camel Sample里面关于Osgi 例子,以及参考了 https://www.ibm.com/developerworks/cn/java/j-lo-osgi/ 关键在于Import-Package以及DynamicImport-Package的设置。
于是在这个Blueprint文件,改为使用Bundle形式运行。 新建工程,POM.xml 文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel</groupId> <artifactId>camel-parent</artifactId> <version>2.15.0</version> </parent> <groupId>com.esq.grm.igs</groupId> <artifactId>igs-file-transformer</artifactId> <!--<version>1.0.0</version>--> <packaging>bundle</packaging> <properties> <camel-version>2.15.0</camel-version> <camel-extra-version>2.15.0</camel-extra-version> </properties> <dependencies> <!-- camel --> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>${camel-version}</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-blueprint</artifactId> <version>${camel-version}</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jsch</artifactId> <version>${camel-version}</version> </dependency> <dependency> <groupId>org.apache-extras.camel-extra</groupId> <artifactId>camel-jcifs</artifactId> <version>${camel-extra-version}</version> </dependency> </dependencies> <build> <finalName>${project.artifactId}-${project.version}</finalName> <plugins> <!-- to generate the MANIFEST-FILE of the bundle --> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <manifestLocation>target/META-INF</manifestLocation> <instructions> <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName> <Export-Package>${project.groupId}*</Export-Package> <Import-Package> org.apache.camel.component.scp;version="[2.15,2.16)", org.apache.camel.blueprint;version="[2.15,2.16)", org.apacheextras.camel.component.jcifs;version="[2.15,2.16)", * </Import-Package> </instructions> </configuration> </plugin> <!--camel run--> </plugins> </build> </project>
改用Camel 2.15.0 版本,重点在于:
<Import-Package> org.apache.camel.component.scp;version="[2.15,2.16)", org.apache.camel.blueprint;version="[2.15,2.16)", org.apacheextras.camel.component.jcifs;version="[2.15,2.16)", * </Import-Package>
再将Blueprint的xml的文件放入src\main\resources\OSGI-INF\blueprint 目录下,直接使用mvn:package生成Jar文件, 可以看到生成的MANIFEST.MF文件如下
Manifest-Version: 1.0 Bnd-LastModified: 1486709707601 Build-Jdk: 1.8.0_45 Built-By: PanArm Bundle-Description: Camel Parent POM Bundle-DocURL: http://www.apache.org/ Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-ManifestVersion: 2 Bundle-Name: igs-file-transformer Bundle-SymbolicName: com.esq.grm.igs.igs-file-transformer Bundle-Vendor: The Apache Software Foundation Bundle-Version: 2.15.0 Created-By: Apache Maven Bundle Plugin Export-Package: com.esq.grm.igs.fileTransformer;uses:="org.apache.camel. builder";version="2.15.0" Implementation-Title: Apache Camel Implementation-Version: 2.15.0 Import-Package: org.apache.camel.blueprint;version="[2.15,2.16)",org.apa che.camel.builder;version="[2.15,3)",org.apache.camel.component.scp;ver sion="[2.15,2.16)",org.apache.camel.processor.idempotent;version="[2.15 ,3)",org.apacheextras.camel.component.jcifs;version="[2.15,2.16)",org.o sgi.service.blueprint;version="[1.0.0,2.0.0)" Karaf-Info: Camel;igs-file-transformer=2.15.0 Tool: Bnd-1.50.0
将jar文件直接丢到Karaf容器, 又发现SCP的配置有误,修改一些配置后(camel-jsch配置待续)Smb to SCP就跑起来了。
继续以Blueprint运行
查Karaf文档,Blueprint/XML也可以设置类依赖, 详情:http://karaf.apache.org/manual/latest/#_blueprint_deployer
原理与MANIFES.MF一样, 只需要XML内加入
<manifest xmlns="http://karaf.apache.org/xmlns/deployer/blueprint/v1.0.0"> Bundle-Name=TrialHttpProxyByCamel Bundle-Version=1.0.0 Import-Package=org.apache.camel.blueprint;version="[2.15,2.16)".... </manifest>