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@bec2452{VFSClassLoaderPolicy@3c44899b{name=vfsfile:/D:/apps/jboss-5.1.0.GA/server/iICE/deploy/jbpm/jbpm-enterprise.jar/
domain=ClassLoaderDomain@7d858aa0{name=DefaultDomain parentPolicy=BEFORE
parent=org.jboss.bootstrap.NoAnnotationURLClassLoader@2f754ad2}
roots=[MemoryContextHandler@933641734[path=
context=vfsmemory://3ia22z-wqetcv-gdhxpu8b-1-gdhxq6z0-2a
real=vfsmemory://3ia22z-wqetcv-gdhxpu8b-1-gdhxq6z0-2a],
FileHandler(a)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
[
http://community.jboss.org/message/559670#559670]
Start a new discussion in jBPM at Community
[
http://community.jboss.org/choose-container!input.jspa?contentType=1&...]