You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@servicemix.apache.org by "Alexis Kinsella (JIRA)" <ji...@apache.org> on 2006/11/24 11:42:02 UTC

[jira] Created: (SM-758) JBoss Deployer 3.0 Snapshot classloading issues

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

        

[jira] Resolved: (SM-758) JBoss Deployer 3.0 Snapshot classloading issues

Posted by "Guillaume Nodet (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/activemq/browse/SM-758?page=all ]

Guillaume Nodet resolved SM-758.
--------------------------------

    Fix Version/s: 3.1
                       (was: 3.0.1)
                       (was: 3.0)
       Resolution: Fixed
         Assignee: Guillaume Nodet

Note that I have not included the servicemix-components jar, as all its dependencies are not included.

See http://fisheye.codehaus.org/changelog/servicemix/?cs=1083

> 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
>         Assigned To: Guillaume Nodet
>             Fix For: 3.1
>
>
> 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