[jboss-user] [jBPM] - Classloading of JNDI objects in ExternalActivityBehaviour impl

Justin Couch do-not-reply at jboss.com
Tue Aug 31 00:52:06 EDT 2010

Justin Couch [http://community.jboss.org/people/jcouch] created the discussion

"Classloading of JNDI objects in ExternalActivityBehaviour impl"

To view the discussion, visit: http://community.jboss.org/message/559670#559670

Classloading seems to be the eternal bane of JBPM and I've run in to another fun problem  :( 

Platform: JBPM 4.4, JBoss 5.1.0GA with JBPM as a process, JDK 1.6 u21, Win7 64bit

I have a custom ExternalActivityBehaviour where we reference several remote beans through JNDI. We have JBoss set up for strict classloading so that each EAR file has it's own class loader. My code for the deployment registers all the necessary classes with the JBPM deployment instance as needed:

        ByteArrayInputStream bis = new ByteArrayInputStream(jbpm_config.getBytes());        try        {            ProcessEngine jbpm_engine = getProcessEngine();            ExecutionService exec_service = jbpm_engine.getExecutionService();            RepositoryService repo_service = jbpm_engine.getRepositoryService();            NewDeployment deployment = repo_service.createDeployment();            String workflow_name = workflow.getWorkflowName();            String jpdl_name = workflow_name + ".jpdl.xml";            deployment.addResourceFromInputStream(jpdl_name, bis);            InputStream[] is = new InputStream[RUNTIME_CLASSES.length];            ClassLoader cl = Thread.currentThread().getContextClassLoader();            for(int i = 0; i < RUNTIME_CLASSES.length; i++)            {                String cls = convertClassName(RUNTIME_CLASSES[i]);                InputStream class_input = cl.getResourceAsStream(cls);                if(class_input == null)                {                    log(...)                }                else                {                    is[i] = class_input;                    deployment.addResourceFromInputStream(cls, class_input);                }            }            deployment.setName(workflow_name);            String deployment_id = deployment.deploy();            ProcessInstance process_instance =                exec_service.startProcessInstanceByKey(workflow_name, vars);            close(is);        }        catch(JbpmException jbe)        {        }

where getProcessEngine() uses a JNDI lookup.

That's fine - everything registers and puts the right sets of classes in to the DB - confirmed by manual inspection of the JBPM4_LOB table.

My custom behaviour looks like this:

public class JMSActivityBehaviour implements ExternalActivityBehaviour{    private JobProcessorManagerRemote jobProcessor;    public JMSActivityBehaviour()
        ....    }    @Override    public void signal(ActivityExecution exec,                       String signal,                       Map<String, ?> extVars)        throws Exception    {        exec.setVariables(extVars);        exec.take(signal);    }    /**     * @inheritDoc     */    @Override    public void execute(ActivityExecution exec)    {        // Locate the message queue first, to make sure we can send the        // message.        String jms_queue = null;        QueueSession session = null;        Queue message_queue = null;        Context ctx = null;        try        {            ctx = new InitialContext();            QueueConnectionFactory fac =                (QueueConnectionFactory)ctx.lookup("ConnectionFactory");            QueueConnection conn = fac.createQueueConnection();            session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);            conn.start();            if(jobProcessor == null)            {                Object obj = ctx.lookup("ejb/mycompany/JobProcessorManager");                if(obj != null)                    jobProcessor = (JobProcessorManagerRemote)PortableRemoteObject.narrow(obj,JobProcessorManagerRemote.class );            }....        }        catch (NamingException ne)

in the line where I look up the custom EJB (EJB3 SLSB), I get a ClassNotFoundException on the remote interface class. Note that the variable in the top of the class doesn't throw the CNFE on <init>, it is only during the JNDI lookup, from somewhere in the guts of JNDI. I've confirmed w test that that specific EJB end point can be located in JNDI in other EJBs, MBeans, and even external Junit tests, so I have narrowed it down to the way that JBPM does it's classloading specifically. Here's the important part of the stack trace:

Caused by: java.lang.ClassNotFoundException: com.mycompany.server.ejb3.scheduler.JobProcessorManagerRemote from BaseClassLoader at bec2452{VFSClassLoaderPolicy at 3c44899b{name=vfsfile:/D:/apps/jboss-5.1.0.GA/server/iICE/deploy/jbpm/jbpm-enterprise.jar/ domain=ClassLoaderDomain at 7d858aa0{name=DefaultDomain parentPolicy=BEFORE parent=org.jboss.bootstrap.NoAnnotationURLClassLoader at 2f754ad2} roots=[MemoryContextHandler at 933641734[path= context=vfsmemory://3ia22z-wqetcv-gdhxpu8b-1-gdhxq6z0-2a real=vfsmemory://3ia22z-wqetcv-gdhxpu8b-1-gdhxq6z0-2a], FileHandler at 53614709[path=jbpm/jbpm-enterprise.jar context=file:/D:/apps/jboss-5.1.0.GA/server/iICE/deploy/ real=file:/D:/apps/jboss-5.1.0.GA/server/iICE/deploy/jbpm/jbpm-enterprise.jar/]]  delegates=null exported=[META-INF] <IMPORT-ALL>NON_EMPTY}}    at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:448)    at java.lang.ClassLoader.loadClass(Unknown Source)    at org.jboss.classloading.spi.DelegatingClassLoader.loadClass(DelegatingClassLoader.java:87)    at java.lang.ClassLoader.loadClass(Unknown Source)    at org.jboss.util.loading.DelegatingClassLoader.loadClass(DelegatingClassLoader.java:97)    at java.lang.ClassLoader.loadClass(Unknown Source)    at java.lang.Class.forName0(Native Method)    at java.lang.Class.forName(Unknown Source)    at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.redefineProxyInTcl(ProxyObjectFactory.java:406)    ... 175 more

In reading through past documentation and forum threads, I've noticed that there used to be an option in JBPM to turn off it's internal classloader and delegate to JBoss's  classloader. With JBPM 4.3 and 4.4 that option no longer seems to exist. Anyone have ideas on places to look and other options to try. I've tried everything in the wiki, previous forum posts and such, just completely out of ideas.


Reply to this message by going to Community

Start a new discussion in jBPM at Community

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jboss-user/attachments/20100831/b82ae216/attachment-0001.html 

More information about the jboss-user mailing list