<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<body link="#355491" alink="#4262a1" vlink="#355491" style="background: #e2e2e2; margin: 0; padding: 20px;">
<div>
        <table cellpadding="0" bgcolor="#FFFFFF" border="0" cellspacing="0" style="border: 1px solid #dadada; margin-bottom: 30px; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                <tbody>
                        <tr>
                                <td>
                                        <table border="0" cellpadding="0" cellspacing="0" bgcolor="#FFFFFF" style="border: solid 2px #ccc; background: #dadada; width: 100%; -moz-border-radius: 6px; -webkit-border-radius: 6px;">
                                                <tbody>
                                                        <tr>
                                                                <td bgcolor="#000000" valign="middle" height="58px" style="border-bottom: 1px solid #ccc; padding: 20px; -moz-border-radius-topleft: 3px; -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 5px; -webkit-border-top-left-radius: 5px;">
                                                                        <h1 style="color: #333333; font: bold 22px Arial, Helvetica, sans-serif; margin: 0; display: block !important;">
                                                                        <!-- To have a header image/logo replace the name below with your img tag -->
                                                                        <!-- Email clients will render the images when the message is read so any image -->
                                                                        <!-- must be made available on a public server, so that all recipients can load the image. -->
                                                                        <a href="http://community.jboss.org/index.jspa" style="text-decoration: none; color: #E1E1E1">JBoss Community</a></h1>
                                                                </td>
                                                        </tr>
                                                        <tr>
                                                                <td bgcolor="#FFFFFF" style="font: normal 12px Arial, Helvetica, sans-serif; color:#333333; padding: 20px; -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 5px; -webkit-border-bottom-left-radius: 5px;"><h3 style="margin: 10px 0 5px; font-size: 17px; font-weight: normal;">
Re: Dynamic classloading issue
</h3>
<span style="margin-bottom: 10px;">
created by <a href="http://community.jboss.org/people/ron.sigal%40jboss.com">Ron Sigal</a> in <i>JBoss Remoting</i> - <a href="http://community.jboss.org/message/563767#563767">View the full discussion</a>
</span>
<hr style="margin: 20px 0; border: none; background-color: #dadada; height: 1px;">
<div class="jive-rendered-content"><blockquote class="jive-quote"><p>v a wrote:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p> But when I tried to load something through InitialContext.lookup the weird exception (see above) occurred.</p></blockquote><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>The JBoss JNDI implementation is completely separate from Remoting.  It is based on RMI and can support remote classloading to some extent.  The MBean "jboss:service=WebService" in $JBOSS_HOME/server/$CONFIG/conf/jboss-service.xml is the special purpose web server that returns classes from the server.  Note, however, that it can't process jars inside of ears.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><blockquote class="jive-quote"><p>v a wrote:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>However, I still have no idea how to deal with the isolated classloader because the example from the documentation does not work.</p></blockquote><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>I have recently learned that it's not so easy to access classloaders by name in AS 5.  I have a partial solution which involves adding an object that collects references to all classloaders used in the AS and which can be used to inject classloaders into a Remoting connector.  The class is called ClassloaderCatcher:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>/*<br/> * JBoss, Home of Professional Open Source.<br/> * Copyright 2010, Red Hat Middleware LLC, and individual contributors<br/> * as indicated by the @author tags. See the copyright.txt file in the<br/> * distribution for a full listing of individual contributors.<br/>  *<br/> * This is free software; you can redistribute it and/or modify it<br/> * under the terms of the GNU Lesser General Public License as<br/> * published by the Free Software Foundation; either version 2.1 of<br/> * the License, or (at your option) any later version.<br/> *<br/> * This software is distributed in the hope that it will be useful,<br/> * but WITHOUT ANY WARRANTY; without even the implied warranty of<br/> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU<br/> * Lesser General Public License for more details.<br/> *<br/> * You should have received a copy of the GNU Lesser General Public<br/> * License along with this software; if not, write to the Free<br/> * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA<br/><span> * 02110-1301 USA, or see the FSF site: </span><a class="jive-link-external-small" href="http://www.fsf.org" target="_blank">http://www.fsf.org</a><span>.</span><br/> */<br/>package org.jboss.deployers.classloadercatcher;</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>import java.io.IOException;<br/>import java.io.InputStream;<br/>import java.net.URL;<br/>import java.util.ArrayList;<br/>import java.util.Collections;<br/>import java.util.Enumeration;<br/>import java.util.Map;<br/>import java.util.concurrent.ConcurrentHashMap;</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>import org.jboss.deployers.spi.DeploymentException;<br/>import org.jboss.deployers.spi.deployer.helpers.AbstractDeployer;<br/>import org.jboss.deployers.structure.spi.DeploymentUnit;<br/>import org.jboss.logging.Logger;<br/>import org.jboss.metadata.ejb.jboss.JBossMetaData;</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>/**<br/> * A ClassLoaderCatcher.<br/> * <br/><span> * @author <a href="</span><a class="jive-link-email-small" href="mailto:ron.sigal@jboss.com" target="_blank">ron.sigal@jboss.com</a><span>">Ron Sigal</a></span><br/> * @version $Revision: 1.1 $<br/> *<br/> * Copyright Aug 9, 2010<br/> */<br/>public class ClassLoaderCatcher extends AbstractDeployer<br/>{</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   // ------------------------------------------------------------------------------||<br/>   // Class Members ----------------------------------------------------------------||<br/>   // ------------------------------------------------------------------------------||</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   public ClassLoader getClassLoader(String deploymentUnitName) {<br/>      return new ClassLoaderWrapper(deploymentUnitName);<br/>   }<br/>   <br/>   private static ClassLoader getActualClassLoader(String deploymentUnitName) {<br/>      return map.get(deploymentUnitName);<br/>   }<br/>       <br/>//   public static <br/>   private static final Logger log = Logger.getLogger(ClassLoaderCatcher.class);<br/>   private static final Map<String, ClassLoader> map = new ConcurrentHashMap<String, ClassLoader>();<br/>   <br/>   // ------------------------------------------------------------------------------||<br/>   // Instance Members -------------------------------------------------------------||,<br/>   // ------------------------------------------------------------------------------||</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   // ------------------------------------------------------------------------------||<br/>   // Constructor ------------------------------------------------------------------||<br/>   // ------------------------------------------------------------------------------||</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   public ClassLoaderCatcher() {<br/>      log.debug(this + " created");<br/>   }</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   // ------------------------------------------------------------------------------||<br/>   // Required Implementations -----------------------------------------------------||<br/>   // ------------------------------------------------------------------------------||</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   /**<br/>    * {@inheritDoc}<br/>    * @see org.jboss.deployers.spi.deployer.Deployer#deploy(org.jboss.deployers.structure.spi.DeploymentUnit)<br/>    */<br/>   public void deploy(final DeploymentUnit unit) throws DeploymentException<br/>   {<br/>      log.trace(this + " gets DeploymentUnit: " + unit);<br/>//      if (!isEjb3Deployment(unit)) {<br/>//          log.trace(this + " not an EJB3");<br/>////          return;<br/>//      }<br/>      <br/>      log.trace(this + " name: " + unit.getName());<br/>       log.trace(this + " topLevel name: " + unit.getTopLevel().getName());<br/>       log.trace(this + " topLevel simple name: " + unit.getTopLevel().getSimpleName());<br/>      log.trace(this + " classloader: " + unit.getTopLevel().getClassLoader());<br/>      <br/>       DeploymentUnit topLevel = unit.getTopLevel();<br/>      map.put(topLevel.getSimpleName(), topLevel.getClassLoader());<br/>      log.trace(this + " map: " + map);<br/>   }</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   // ------------------------------------------------------------------------------||<br/>   // Helper Methods ---------------------------------------------------------------||<br/>   // ------------------------------------------------------------------------------||</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   /*<br/>    * These may be overridden for testing purposes<br/>    */</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   /**<br/>    * Returns whether this is an EJB3 Deployment, determining if we should take action<br/>    * @param unit<br/>    * @return<br/>    */<br/>   boolean isEjb3Deployment(final DeploymentUnit unit)<br/>   {<br/>      // Obtain the Merged Metadata<br/>      final JBossMetaData md = unit.getAttachment(JBossMetaData.class);</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>      // If metadata's not present as an attachment, return<br/>      if (md == null)<br/>      {<br/>         return false;<br/>      }</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>      // If this is not an EJB3 Deployment, return<br/>      if (!md.isEJB3x())<br/>      {<br/>         return false;<br/>      }</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>      // Meets conditions<br/>      return true;<br/>   }<br/>   <br/>   static class ClassLoaderWrapper extends ClassLoader {<br/>      private static Enumeration<URL> emptyEnumeration = Collections.enumeration(new ArrayList<URL>());<br/>      private String topLevelName;<br/>      private ClassLoader delegate;</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>      public ClassLoaderWrapper(String topLevelName) {<br/>         this.topLevelName = topLevelName;<br/>      }</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>      public Class<?> loadClass(String name) throws ClassNotFoundException {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            throw new ClassNotFoundException("top level name not found: " + topLevelName);<br/>         }<br/>         return delegate.loadClass(name);<br/>      }<br/>      <br/>      public URL getResource(String name) {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            return null;<br/>         }<br/>         return delegate.getResource(name);<br/>      }<br/>      <br/>      public Enumeration<URL> getResources(String name) throws IOException {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            return emptyEnumeration;<br/>         }<br/>         return delegate.getResources(name);<br/>      }<br/>      <br/>      public InputStream getResourceAsStream(String name) {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            return null;<br/>         }<br/>         return delegate.getResourceAsStream(name);<br/>      }<br/>      <br/>      public synchronized void setDefaultAssertionStatus(boolean enabled) {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            return;<br/>         }<br/>         delegate.setDefaultAssertionStatus(enabled);<br/>      }<br/>      <br/>      public synchronized void setPackageAssertionStatus(String packageName, boolean enabled) {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            return;<br/>         }<br/>         delegate.setPackageAssertionStatus(packageName, enabled);<br/>      }<br/>      <br/>      public synchronized void setClassAssertionStatus(String className, boolean enabled) {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            return;<br/>         }<br/>         delegate.setClassAssertionStatus(className, enabled);<br/>      }<br/>      <br/>      public synchronized void clearAssertionStatus() {<br/>         checkClassLoader();<br/>         if (delegate == null) {<br/>            return;<br/>         }<br/>         delegate.clearAssertionStatus();<br/>         <br/>      }<br/>   <br/>      private void checkClassLoader() {<br/>//         if (delegate == null) {<br/>//            delegate = TestDeployer.getActualClassLoader(topLevelName);<br/>//         }<br/>         delegate = ClassLoaderCatcher.getActualClassLoader(topLevelName);<br/>      }<br/>   }</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>}</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>It is added to the AS by putting it in a jar and adding the following directory to $JBOSS_HOME/server/$CONFIG/deployers:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>classloader-catcher.deployer</p><p>  classloader-catcher.jar</p><p>  META-INF</p><p>    classloader-catcher-jboss-beans.xml</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>where classloader-catcher-jboss-beans.xml is</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p><?xml version="1.0" encoding="UTF-8"?><br/><deployment xmlns="urn:jboss:bean-deployer:2.0"></p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>   <bean name="classloaderCatcher" class="org.jboss.deployers.classloadercatcher.ClassLoaderCatcher"><br/>   </bean><br/>      <br/></deployment></p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>You then can add the following to $JBOSS_HOME/server/$CONFIG/deploy/ejb3-connectors-jboss-beans.xml:</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p><property name="serverParameters"><br/>      <map keyClass="java.lang.String" valueClass="java.lang.Object"><br/>        <entry><br/>          <key>remoteClassLoaders</key><br/>          <value><br/>            <list elementClass="java.lang.ClassLoader"><br/>              <value-factory bean="classloaderCatcher" method="getClassLoader"><br/>                 <parameter>Simple21EJB.ear</parameter><br/>              </value-factory><br/>            </list><br/>          </value><br/>        </entry><br/>      </map><br/>    </property></p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>where, in this case, Simple21EJB.ear is the ear with the classes I want to load.</p><p style="min-height: 8pt; height: 8pt; padding: 0px;"> </p><p>It's not a foolproof solution, since there's no way to distinguish two distinct classes with the same name, but it's a step in the right direction.</p></div>
<div style="background-color: #f4f4f4; padding: 10px; margin-top: 20px;">
<p style="margin: 0;">Reply to this message by <a href="http://community.jboss.org/message/563767#563767">going to Community</a></p>
        <p style="margin: 0;">Start a new discussion in JBoss Remoting at <a href="http://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2050">Community</a></p>
</div></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>