[jboss-user] [Beginners Corner] - Re: Howto install custom classloader

Deady do-not-reply at jboss.com
Fri Nov 7 10:01:05 EST 2008


For simplicity let's load class from file.

here's a trick:

1. create classloader

  | package test.jboss;
  | 
  | import org.jboss.logging.Logger;
  | import org.jboss.mx.loading.RepositoryClassLoader;
  | 
  | import javax.management.MalformedObjectNameException;
  | import javax.management.ObjectName;
  | import java.net.URL;
  | import java.io.FileInputStream;
  | import java.io.IOException;
  | 
  | /**
  |  * User: Deady
  |  * Date: 06.11.2008
  |  * Time: 16:58:53
  |  */
  | 
  | public class DBClassLoader extends RepositoryClassLoader {
  | 
  | 
  |     protected Logger log;
  |     private String name;
  | 
  | 
  |     /**
  |      * Create a new LoaderRepositoryClassLoader
  |      *
  |      * @param parent the parent classloader
  |      */
  |     public DBClassLoader(String name, URL[] url, ClassLoader parent) {
  |         super(url, parent);
  |         this.name = name;
  |         this.log = org.jboss.logging.Logger.getLogger(getClass().getName());
  |     }
  | 
  |     public ObjectName getObjectName() throws MalformedObjectNameException {
  |         return new ObjectName("dbclassloader");
  |     }
  | 
  |     public Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
  |         log.info("loading class: "+name);
  |         return super.loadClass(name, resolve);
  |     }
  | 
  |     public URL getResourceLocally(String name) {
  |         log.info("getting resource locally: "+name);
  |         return getURL();
  |     }
  | 
  |     public Class loadClassLocally(String name, boolean resolve) throws ClassNotFoundException {
  |         log.info("loading class locally: "+name);
  |         String file = "/home/Deady/testbean/classes/"+name.replace(".","/")+".class";
  |         byte[] b = null;
  |         int readen = 0;
  |         try {
  |             FileInputStream in = new FileInputStream(file);
  |             b = new byte[in.available()];
  |             readen = in.read(b);
  |             in.close();
  |         } catch (IOException e) {
  |             e.printStackTrace();
  |         }
  |         return defineClass(name, b, 0, readen);
  |     }
  | 
  |     public Package[] getPackages() {
  |         log.info("return packages: "+getPackage(name));
  |         return new Package[]{getPackage(name)};
  |     }
  | }
  | 


2. create deployer MBean:



  | package test.jboss;
  | 
  | import org.jboss.deployment.DeploymentException;
  | import org.jboss.deployment.DeploymentInfo;
  | import org.jboss.deployment.SubDeployerSupport;
  | import org.jboss.logging.Logger;
  | 
  | import java.net.URL;
  | 
  | /**
  |  * User: Deady
  |  * Date: 06.11.2008
  |  * Time: 13:42:03
  |  */
  | public class DBDeployerMBean extends SubDeployerSupport {
  | 
  |     protected Logger log;
  | 
  |     public DBDeployerMBean() {
  |         this.log = org.jboss.logging.Logger.getLogger(getClass().getName());
  |     }
  | 
  |     public boolean accepts(DeploymentInfo di) {
  |         String urlStr = di.url.toString();
  |         String extension = getExtension();
  |         boolean res = urlStr.endsWith(extension);
  |         if (res) {
  |             log.info("accepted: "+di);            
  |         }
  |         return res;
  |     }
  | 
  | 
  |     public void init(DeploymentInfo di) throws DeploymentException {
  |         log.info("initializing: "+di);
  |         try {
  |             di.createClassLoaders();
  |             di.ucl.getLoaderRepository().addClassLoader(new DBClassLoader("foo", new URL[]{di.localUrl}, di.ucl));
  |         } catch (Exception e) {
  |             e.printStackTrace();
  |         }
  |         super.init(di);
  |     }
  | 
  |     protected void deployUrl(DeploymentInfo di, URL url, String name) throws DeploymentException {
  |         log.info("di: "+di+", url:"+url+", name: "+name);
  |         super.deployUrl(di, url, name);
  |     }
  | 
  |     public String getExtension() {
  |         return ".dbr";
  |     }
  | 
  | }
  | 

3. create sar descriptor:


  | <?xml version="1.0" encoding="UTF-8"?>
  | <!--
  |   The JBoss service configuration file for the EJB deployer service.
  |   
  |   $Id: ejb-deployer.xml 62317 2007-04-13 10:39:22Z dimitris at jboss.org $
  | -->
  | <server>
  | 
  | 
  |     <!-- ==================================================================== -->
  |     <!-- DB Deployer                                                         -->
  |     <!-- ==================================================================== -->
  | 
  |     <!-- EJB deployer, remove to disable EJB behavior-->
  |     <mbean code="test.jboss.DBDeployerMBean" name="jboss.ejb:service=DBDeployer" xmbean-dd="">
  | 
  |         <!-- Inline XMBean Descriptor BEGIN -->
  |         <xmbean>
  |             <description>The DBDeployer responsible for dbr jar deployment</description>
  |             <class>test.jboss.DBDeployerMBean</class>
  | 
  |             <!-- ServiceMBean operations -->
  |             <operation>
  |                 <description>Standard MBean lifecycle method</description>
  |                 <name>create</name>
  |             </operation>
  | 
  |             <operation>
  |                 <description>The start lifecycle operation</description>
  |                 <name>start</name>
  |             </operation>
  | 
  |             <operation>
  |                 <description>The stop lifecycle operation</description>
  |                 <name>stop</name>
  |             </operation>
  | 
  |             <operation>
  |                 <description>The destroy lifecycle operation</description>
  |                 <name>destroy</name>
  |             </operation>
  | 
  |             <operation>
  |                 <description>The detyped lifecycle operation (for internal use only)</description>
  |                 <name>jbossInternalLifecycle</name>
  |                 <parameter>
  |                     <description>The lifecycle operation</description>
  |                     <name>method</name>
  |                     <type>java.lang.String</type>
  |                 </parameter>
  |                 <return-type>void</return-type>
  |             </operation>
  | 
  | 
  |             <!-- SubDeployerMBean operations -->
  |             <operation>
  |                 <description>Accept a module for deployment</description>
  |                 <name>accepts</name>
  |                 <parameter>
  |                     <name>info</name>
  |                     <type>org.jboss.deployment.DeploymentInfo</type>
  |                 </parameter>
  |                 <return-type>boolean</return-type>
  |             </operation>
  | 
  |             <operation>
  |                 <description>Initialize deployment step</description>
  |                 <name>init</name>
  |                 <parameter>
  |                     <name>info</name>
  |                     <type>org.jboss.deployment.DeploymentInfo</type>
  |                 </parameter>
  |             </operation>
  | 
  |             <operation>
  |                 <description>Create deployment step</description>
  |                 <name>create</name>
  |                 <parameter>
  |                     <name>info</name>
  |                     <type>org.jboss.deployment.DeploymentInfo</type>
  |                 </parameter>
  |             </operation>
  | 
  |             <operation>
  |                 <description>Start deployment step</description>
  |                 <name>start</name>
  |                 <parameter>
  |                     <name>info</name>
  |                     <type>org.jboss.deployment.DeploymentInfo</type>
  |                 </parameter>
  |             </operation>
  | 
  | 
  |             <operation>
  |                 <description>Stop deployment step</description>
  |                 <name>stop</name>
  |                 <parameter>
  |                     <name>info</name>
  |                     <type>org.jboss.deployment.DeploymentInfo</type>
  |                 </parameter>
  |             </operation>
  | 
  |             <operation>
  |                 <description>Destroy deployment step</description>
  |                 <name>destroy</name>
  |                 <parameter>
  |                     <name>info</name>
  |                     <type>org.jboss.deployment.DeploymentInfo</type>
  |                 </parameter>
  |             </operation>
  | 
  | 
  |         </xmbean>
  | 
  | 
  |     </mbean>
  | 
  | </server>
  | 


4. pack sar and copy it to server:
/jboss/server/deploy/dbdeployer.sar
+METAINF
++jboss-service.xml
+dbdeployer.jar


5. create and deploy test.ddr - this is simple jar file:
test.dbr
+META-INF
++INDEX.LIST

content of INDEX.LIST:

  | ddd
  | 
  | db.jar
  | foo
  | 

6. create test bean:

  | package test;
  | 
  | import javax.ejb.Remote;
  | 
  | /**
  |  * User: Deady
  |  * Date: 06.11.2008
  |  * Time: 17:08:24
  |  */
  | @Remote
  | public interface TestClassLoader {
  | 
  |     public Object loadClass(String className);
  | 
  | }
  | 


  | package test;
  | 
  | import org.jboss.annotation.ejb.RemoteBinding;
  | 
  | import javax.ejb.Stateless;
  | 
  | /**
  |  * User: Deady
  |  * Date: 06.11.2008
  |  * Time: 17:09:06
  |  */
  | @Stateless(name="DBClassLoader")
  | @RemoteBinding(jndiBinding="test/DBClassLoader/remote")
  | public class TestClassLoaderImpl implements TestClassLoader{
  | 
  |     public Object loadClass(String className) {
  |         try {
  |             Class cl = Thread.currentThread().getContextClassLoader().loadClass(className);
  |             System.out.println("loaded = " + cl);
  |             Object o = cl.newInstance();
  |             return o;
  |         } catch (Exception e) {
  |             e.printStackTrace();
  |         }
  |         return null;
  |     }
  | }
  | 
  | 


7. create test class:


  | package foo;
  | 
  | import java.io.Serializable;
  | 
  | /**
  |  * User: Deady
  |  * Date: 07.11.2008
  |  * Time: 17:19:00
  |  */
  | public class Test implements Serializable {
  | 
  |     public String hello() {
  |         return "hello world3";
  |     }
  | 
  | }
  | 
  | 

compile it and copy to path, from which DBClassLoader will read it ("/home/Deady/testbean/classes/" in my case)


8. test it works:


  | package test;
  | 
  | import foo.Test;
  | 
  | import javax.naming.InitialContext;
  | import javax.naming.Context;
  | import java.util.Properties;
  | 
  | /**
  |  * User: Deady
  |  * Date: 06.11.2008
  |  * Time: 17:16:26
  |  */
  | public class Client {
  | 
  |     public static void main(String[] args) throws Exception {
  |         Properties p = new Properties();
  | 
  | 
  |         p.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
  |         p.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
  |         p.put(Context.PROVIDER_URL, "jnp://192.168.0.87:1099");
  |         InitialContext ctx = new InitialContext(p);
  |         TestClassLoader l = (TestClassLoader) ctx.lookup("test/DBClassLoader/remote");
  |         Object c = l.loadClass("foo.Test");
  |         if (c==null) {
  |             System.out.println("null");
  |         }
  |         else {
  |             if (c instanceof Test) {
  |                 System.out.println(((Test)c).hello());
  |             }
  |             else {
  |                 System.out.println(c.getClass());
  |             }
  |         }
  |         
  | 
  |     }
  | 
  | }
  | 
  | 
  | 

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4187739#4187739

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4187739



More information about the jboss-user mailing list