JBoss Deployer 3.0 Snapshot classloading issues
-----------------------------------------------

                 Key: SM-758
                 URL: https://issues.apache.org/activemq/browse/SM-758
             Project: ServiceMix
          Issue Type: Bug
          Components: tooling
    Affects Versions: 3.0.1, 3.0
         Environment: JBoss 4.02 , any System (tested on Windows XP)
            Reporter: Alexis Kinsella
             Fix For: 3.0.1, 3.0


Message From Forum: 

Hello, I have noticed some problems related to classloading with jboss-deployer.
Due to the JBoss classloading mechanism (cf: UCL and loader-repositories), if 
you install the sar, you can't anymore deploy any web application with spring 
jar even if you use the default isolated Tomcat classloader mechanisms. To 
resolve definitively the problem, the best  bugfix is to create a 
loader-repository for the servicemix jbi deployer sar and its JBI components  
by affecting this newly defined loader-repository to it.
The loader-repository has to be defined in the jboss-service.xml from 
servicemix-jboss-deployer and set the default java2ClassDelegation to true:


<server>
 <loader-repository>
 org.jboss:loader-repository=servicemix
 <loader-repository-config>java2ParentDelegation=true</loader-repository-config>
 </loader-repository>
...

(Jboss wiki: http://www.jboss.org/wiki/Wiki.jsp?page=ClassLoadingConfiguration 
and related pages)
 
java2ParentDelegation=true <= to inherit from jboss server classloader et jboss 
profile classloader and base service classloaders.


After it you have to modify the JBIDeployer to affect this loader-repository to 
loader JBIComponents!
Examples can be found in EARDeployer.java (affect loader to DeployementInfo).

After thos modifications, servicemix jbi service is now really safely isolated, 
and the global service loader-repository, is not pollued by servicemix jars 
(like spring).

The reason of that problem is the Tomcat-service and so Webapps classloaders in 
jboss inherit from the jboss profile classloader which is related to the 
default laoder-repository in jboss. So, there is a problem if servicemix jbi 
service or jbi components jar are deployed in the same loader-repository, 
because, for example spring jar will be in the scope of the webapp 
classloaders, but has not been loader directly by those classloader, the direct 
consequency is that spring verify if some classes have been loader by the same 
classloader and crash if it is not the case! (cf: example of namespace 
handlers, when loading applicationContexts).


Sorry, for my bad explanations in english, if you want better explanations, I 
can explain it in french eventually.

The main thing is that it is very impotant to isolate correctly servicemix 
related classloaders in jboss, to avoid strange classloader issues in other 
J2EE app deployed in JBoss by using correctly Jboss classloading mechanisms.

I have tested a working patch, and all works like a charm. If you prefer to 
have a directly a patch(maybe some dirty code, due to some jboss and 
servmicemix underknowledges), I can send it.


--------------------------------------------------------------------------------------------------

Bug Fixes: 

1 - In POM.xml from jboss-deployer, add this to avoid many problems with class 
no found exceptions when deploying  "-sm.xml" files in JBoss  : 

    <!-- Added as dependency, needed by lw components, example: filebindings -->
    <dependency>
      <groupId>org.apache.servicemix</groupId>
      <artifactId>servicemix-components</artifactId>
      <version>3.0-incubating</version>
    </dependency>

2 - In Jboss-service.xml, add loader-repository like this: 

<?xml version="1.0" encoding="UTF-8"?>

<!-- The J2EE application client deployer service -->
<server>
  <loader-repository>
          org.servicemix:loader-repository=JBIContainer
         
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
  </loader-repository>
  <mbean code="org.servicemix.jboss.deployment.JBIDeployer" 
name="org.servicemix:service=Deployer">
    <depends 
optional-attribute-name="JBIContainer">org.servicemix:service=JBIService</depends>
  </mbean>

  <mbean code="org.servicemix.jboss.deployment.JBIService" 
name="org.servicemix:service=JBIService">
    <depends>jboss:service=TransactionManager</depends>
    <attribute name="TransactionManager">java:/TransactionManager</attribute>
  </mbean>
  
</server>


In trunk there is a fault in actual jboss-service.xml : there is a token "-->" 
that should not be here!


3 -  In JBIDeployer.java you should correct source like this: 



        /**
         * Describe <code>init</code> method here.
         * 
         * @param di
         *            a <code>DeploymentInfo</code> value
         * @exception DeploymentException
         *                if an error occurs
         * @jmx.managed-operation
         */
        public void init(DeploymentInfo di) throws DeploymentException {
              try
              {
                 log.info("Init ServiceMix JBI Component: " + di.url);

                 log.info("Init Watcher");
                 initWatcher(di);
                 log.info("Init LoaderRepository");
                 initLoaderRepository(di);
              }
              catch (DeploymentException e)
              {
                 throw e;
              }
              catch (Exception e)
              {
                  log.error(e.getMessage());
                  e.printStackTrace();
                 throw new DeploymentException("Error in accessing application 
metadata: ", e);
              }

              super.init(di);
        }

        private void initWatcher(DeploymentInfo di) throws 
MalformedURLException {

        // resolve the watch
        if (di.url.getProtocol().equals("file")) {
           File file = new File(di.url.getFile());
           
           // If not directory we watch the package
           if (!file.isDirectory()) {
              di.watch = di.url;
           }
           // If directory we watch the xml files
           else {
              di.watch = new URL(di.url, "META-INF/jbi.xml");
           }
        }
        else {
           // We watch the top only, no directory support
           di.watch = di.url;
        }

        }

        /**
         * Add the jbi scoped repository
         * 
         * @param di
         *            the deployment info passed to deploy
         * @throws Exception
         */
        protected void initLoaderRepository(DeploymentInfo di) throws Exception 
{
                LoaderRepositoryConfig lrConfig = new 
LoaderRepositoryFactory.LoaderRepositoryConfig();
                lrConfig.repositoryName = new 
ObjectName("org.servicemix:loader-repository=JBIContainer");
                di.setRepositoryInfo(lrConfig);
        }


I don't know how to affect automaticaly loader-repository from the deployer 
one, maybe, this code is a little crap, because affectation of loader 
repository is hard code, it needs to be the same than in jboss-service.xml. One 
possible thing to do, is to add the laoder-repository in META-INF or in another 
file, and get it on "initLoaderRepository" step.

4 - Problem related to Bug SM-584:
I have not tested if it can resolve it, But I think eventually, if it is not 
the case, a README file should be added to explain how to install correctly the 
jboss-deployer.

I think, that-s all about classloading issues I met!








-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
https://issues.apache.org/activemq/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to