I'm trying to utilise Fuse Application Bundles for my project and am coming up against the following problem:
I have a simple test utilising the Spring JMS CachingConnectionFactory with a 3rd party (SonicMQ) JMS client that sends a receives a message from a Sonic MQ JMS queue.
In my POM I have the spring-jms and the sonic jms client dependencies.
If I install this as a fab on fuse, at the point when the fab bundle starts and attempts to execute the following:
CachingConnectionFactory cachingfactory = new CachingConnectionFactory(); ConnectionFactory factory = new progress.message.jclient.ConnectionFactory(url, user, password); cachingfactory.setTargetConnectionFactory(factory);
I get the following exception:
Caused by: java.lang.LinkageError: loader constraint violation: when resolving method "org.springframework.jms.connection.CachingConnectionFactory.setTargetConnectionFactory(Ljavax/jms/ConnectionFactory;)V" the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) of the current class, com/xtrakter/xbus/fabsonictest/FabSonicTest, and the class loader (instance of org/apache/felix/framework/BundleWiringImpl$BundleClassLoaderJava5) for resolved class, org/springframework/jms/connection/CachingConnectionFactory, have different Class objects for the type tionFactory.setTargetConnectionFactory(Ljavax/jms/ConnectionFactory;)V used in the signature
If I debug I can see the class loader for the CachingConnectionFactory is actually a class loader for a Spring JMS bundle:
[ 284] [Active ] [ ] [ ] [ 60] Spring JMS (3.1.3.RELEASE)
Whereas the classloader for the Sonic MQ Connection Factory is the fab bundle.
I figured I needed these to be in the same class loader for the error to go away and set about doing it by adding the FAB Manifest headers as described at http://fusesource.com/docs/esbent/7.0/esb_deploy_osgi/BuildFab-Configure.html by doing the following:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <index>true</index> <manifestEntries> <FAB-Skip-Matching-Feature-Detection>org.springframework</FAB-Skip-Matching-Feature-Detection> <FAB-Install-Provided-Bundle-Dependencies>true</FAB-Install-Provided-Bundle-Dependencies> <!-- hack required to get passed dependency issues --> <FAB-Exclude-Dependency>javax.el javax.inject</FAB-Exclude-Dependency> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build>
This made it so the fab installed the spring-jms dependency in the same classloader and when it started the test then ran correctly.
However, this can't be right, and there must be a better way? What am I doing wrong? I tried using the provided scope on the spring-jms dependency but that didn't work either.
Any help would be much appreciated.