1 Reply Latest reply on Aug 21, 2013 7:16 AM by tellisnz

    FAB not merging manual Import-Package entries with its own generated entries.

      Hi Everyone,

       

      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.

       

      Cheers,

       

      Tom

        • 1. Re: FAB dependencies and Class Loaders in Karaf/Fuse

          So after a bit of googling/debugging/trying stuff etc I'm thinking it seems that FAB can't determine that it needs to add the javax.jms to the Import-Package header. According to http://fusesource.com/docs/esbent/7.0/esb_deploy_osgi/BuildFab-Configure.html I can add specific imports as an extra header as described in my previous post and FAB should merge my additions with the ones it automatically generates. However, I've found this isn't the case.

           

          With no Import-Package specified as a manifestEntries element in my maven pom as above, the following is what appears for the Import-Package header when I install the fab:

           

          Import-Package =
                  com.sonicsw.blackbird.http.impl.server;resolution:=optional,
                  com.sonicsw.blackbird.http.server;resolution:=optional,
                  com.sonicsw.mf.framework;resolution:=optional,
                  com.sonicsw.mf.framework.agent;resolution:=optional,
                  com.sonicsw.mf.framework.agent.ci;resolution:=optional,
                  com.sonicsw.mf.framework.directory;resolution:=optional,
                  com.sonicsw.mx.config;resolution:=optional,
                  com.sonicsw.mx.config.impl;resolution:=optional,
                  com.sonicsw.mx.config.util;resolution:=optional,
                  com.sonicsw.net.http;resolution:=optional,
                  com.sonicsw.security.pass.broker;resolution:=optional,
                  com.sonicsw.security.ssl;resolution:=optional,
                  javax.activation;resolution:=optional,
                  javax.crypto;resolution:=optional,
                  javax.crypto.spec;resolution:=optional,
                  javax.management;resolution:=optional,
                  javax.management.openmbean;resolution:=optional,
                  javax.management.remote;resolution:=optional,
                  javax.naming;resolution:=optional,
                  javax.naming.spi;resolution:=optional,
                  javax.security.auth;resolution:=optional,
                  javax.transaction.xa;resolution:=optional,
                  javax.xml.namespace;resolution:=optional,
                  javax.xml.parsers;resolution:=optional,
                  javax.xml.soap;resolution:=optional,
                  javax.xml.transform;resolution:=optional,
                  javax.xml.transform.dom;resolution:=optional,
                  javax.xml.transform.stream;resolution:=optional,
                  org.apache.axis;resolution:=optional,
                  org.apache.axis.client;resolution:=optional,
                  org.apache.axis.components.jms;resolution:=optional,
                  org.apache.axis.components.uuid;resolution:=optional,
                  org.apache.axis.handlers;resolution:=optional,
                  org.apache.axis.message;resolution:=optional,
                  org.apache.axis.message.addressing;resolution:=optional,
                  org.apache.axis.message.addressing.handler;resolution:=optional,
                  org.apache.axis.message.addressing.util;resolution:=optional,
                  org.apache.axis.soap;resolution:=optional,
                  org.apache.axis.transport.jms;resolution:=optional,
                  org.apache.axis.types;resolution:=optional,
                  org.apache.axis.utils;resolution:=optional,
                  org.osgi.service.blueprint;resolution:=optional;version="[1.0.0,2.0.0)",
                  org.slf4j;resolution:=optional,
                  org.springframework.jms.connection;resolution:=optional,
                  org.w3c.dom;resolution:=optional,
                  org.xml.sax;resolution:=optional,
                  org.xml.sax.ext;resolution:=optional,
                  org.xml.sax.helpers;resolution:=optional,
                  progress.message.broker;resolution:=optional,
                  progress.message.broker.durable;resolution:=optional,
                  progress.message.jclient.xa;resolution:=optional,
                  progress.message.jimpl.xmessage;resolution:=optional,
                  progress.message.msg.v24;resolution:=optional,
                  progress.message.net.http.server;resolution:=optional,
                  progress.message.net.ssl;resolution:=optional,
                  progress.message.xa;resolution:=optional,
                  sun.misc;resolution:=optional
          

           

          With <Import-Package>jms.javax</Import-Package> specified as a manifestEntries element in my maven pom as above, the following is what appears for the Import-Package header when I install the fab:

           

          Import-Package =
                  javax.jms
          

           

          Which obviously causes dependency issues. However, if I manually join the two above lists as one big manifestEntries element in my POM there are no dependency issues and the class loader issue goes away and the test works. I'm happy with the solution of manually adding imports that FAB can't see, so is there a bug in the FAB bundler that it's not joining the Import-Package I specify in the POM with the one it automatically generates?

           

          I've tried to step through the code, but I can't find when the automatic Import-Package list is generated and why it isn't being generated when I specify the Import-Package in the POM.

           

          Cheers,

           

          Tom