[jboss-dev-forums] [Design of EJB 3.0] - Quartz MDB integration and classloader issues

jaikiran do-not-reply at jboss.com
Fri Jul 24 19:42:11 EDT 2009


There have been more than a couple of users now, having trouble with getting the Quartz integration with MDB running. Here are the 2 instances, for example:

http://www.jboss.org/index.html?module=bb&op=viewtopic&t=158926

http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4229808

The real issue is classloading where the quartz thread triggers a job. The QuartzJob which does this (and is triggered through quartz-ra.rar) has the base classloader which does not have access to user deployment classloader. So if you have your MDB packaged in a deployment with its own classloader (which is practical), then the QuartzJob will not have access to the EJBs in the user deployment leading to exceptions like:


  | javax.ejb.EJBTransactionRolledbackException: Unable to inject jndi dependency: env/org.jboss.tutorial.quartz.bean.AnnotatedQuartzMDBBean/calc into property org.jboss.tutorial.quartz.bean.AnnotatedQuartzMDBBean.calc: org.jboss.tutorial.quartz.bean.Calculator from BaseClassLoader at 1f172aa{VFSClassLoaderPolicy at 9f3364{name=vfszip:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar/ domain=ClassLoaderDomain at 1f5eb7f{name=DefaultDomain parentPolicy=BEFORE parent=org.jboss.bootstrap.NoAnnotationURLClassLoader at 1431340} roots=[MemoryContextHandler at 31918682[path= context=vfsmemory://3j001-a542up-fxj4w94o-1-fxj4x19a-21 real=vfsmemory://3j001-a542up-fxj4w94o-1-fxj4x19a-21], DelegatingHandler at 22593168[path=quartz-ra.rar context=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/ real=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar], DelegatingHandler at 21430906[path=quartz-ra.rar/quartz-ra.jar context=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/ real=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar/quartz-ra.jar]]  delegates=null exported=[META-INF, org.jboss.resource.adapter.quartz.inflow] <IMPORT-ALL>NON_EMPTY}}
  | 	at org.jboss.ejb3.tx.Ejb3TxPolicy.handleInCallerTx(Ejb3TxPolicy.java:115)
  | 	at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:130)
  | 	at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:194)
  | 	at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
  | 	at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42)
  | 	at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
  | 	at org.jboss.ejb3.security.Ejb3AuthenticationInterceptorv2.invoke(Ejb3AuthenticationInterceptorv2.java:80)
  | 	at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
  | 	at org.jboss.ejb3.BlockContainerShutdownInterceptor.invoke(BlockContainerShutdownInterceptor.java:67)
  | 	at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
  | 	at org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(CurrentInvocationInterceptor.java:67)
  | 	at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
  | 	at org.jboss.ejb3.mdb.MessagingContainer.localInvoke(MessagingContainer.java:282)
  | 	at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.delivery(MessageInflowLocalProxy.java:270)
  | 	at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.invoke(MessageInflowLocalProxy.java:140)
  | 	at $Proxy136.execute(Unknown Source)
  | 	at org.jboss.resource.adapter.quartz.inflow.QuartzJob.execute(QuartzJob.java:57)
  | 	at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
  | 	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)
  | Caused by: java.lang.RuntimeException: Unable to inject jndi dependency: env/org.jboss.tutorial.quartz.bean.AnnotatedQuartzMDBBean/calc into property org.jboss.tutorial.quartz.bean.AnnotatedQuartzMDBBean.calc: org.jboss.tutorial.quartz.bean.Calculator from BaseClassLoader at 1f172aa{VFSClassLoaderPolicy at 9f3364{name=vfszip:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar/ domain=ClassLoaderDomain at 1f5eb7f{name=DefaultDomain parentPolicy=BEFORE parent=org.jboss.bootstrap.NoAnnotationURLClassLoader at 1431340} roots=[MemoryContextHandler at 31918682[path= context=vfsmemory://3j001-a542up-fxj4w94o-1-fxj4x19a-21 real=vfsmemory://3j001-a542up-fxj4w94o-1-fxj4x19a-21], DelegatingHandler at 22593168[path=quartz-ra.rar context=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/ real=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar], DelegatingHandler at 21430906[path=quartz-ra.rar/quartz-ra.jar context=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/ real=file:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar/quartz-ra.jar]]  delegates=null exported=[META-INF, org.jboss.resource.adapter.quartz.inflow] <IMPORT-ALL>NON_EMPTY}}
  | 	at org.jboss.injection.JndiPropertyInjector.lookup(JndiPropertyInjector.java:82)
  | 	at org.jboss.injection.JndiPropertyInjector.inject(JndiPropertyInjector.java:99)
  | 	at org.jboss.injection.JndiPropertyInjector.inject(JndiPropertyInjector.java:89)
  | 	at org.jboss.injection.JndiPropertyInjector.inject(JndiPropertyInjector.java:61)
  | 	at org.jboss.ejb3.injection.InjectionInvocation.invokeTarget(InjectionInvocation.java:89)
  | 	at org.jboss.ejb3.injection.InjectionInvocation.invokeNext(InjectionInvocation.java:83)
  | 	at org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(CurrentInvocationInterceptor.java:67)
  | 	at org.jboss.ejb3.injection.InjectionInvocation.invokeNext(InjectionInvocation.java:74)
  | 	at org.jboss.ejb3.EJBContainer.injectBeanContext(EJBContainer.java:1097)
  | 	at org.jboss.ejb3.pool.AbstractPool.create(AbstractPool.java:83)
  | 	at org.jboss.ejb3.pool.AbstractPool.create(AbstractPool.java:73)
  | 	at org.jboss.ejb3.pool.StrictMaxPool.get(StrictMaxPool.java:146)
  | 	at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:58)
  | 	at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
  | 	at org.jboss.aspects.tx.TxPolicy.invokeInCallerTx(TxPolicy.java:126)
  | 	... 17 more
  | Caused by: javax.naming.NamingException: Could not dereference object [Root exception is javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Can not find interface declared by Proxy in our CL + BaseClassLoader at 1f172aa{vfszip:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar/}]]
  | 	at org.jnp.interfaces.NamingContext.resolveLink(NamingContext.java:1352)
  | 	at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:817)
  | 	at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686)
  | 	at org.jboss.ejb3.JndiUtil.lookup(JndiUtil.java:44)
  | 	at org.jboss.injection.JndiPropertyInjector.lookup(JndiPropertyInjector.java:75)
  | 	... 31 more
  | Caused by: javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Can not find interface declared by Proxy in our CL + BaseClassLoader at 1f172aa{vfszip:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar/}]
  | 	at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1504)
  | 	at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:822)
  | 	at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686)
  | 	at javax.naming.InitialContext.lookup(InitialContext.java:351)
  | 	at org.jnp.interfaces.NamingContext.resolveLink(NamingContext.java:1346)
  | 	... 35 more
  | Caused by: java.lang.RuntimeException: Can not find interface declared by Proxy in our CL + BaseClassLoader at 1f172aa{vfszip:/home/jpai/jboss-5.1.0.GA/server/default/deploy/quartz-ra.rar/}
  | 	at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.redefineProxyInTcl(ProxyObjectFactory.java:343)
  | 	at org.jboss.ejb3.proxy.impl.objectfactory.session.SessionProxyObjectFactory.createProxy(SessionProxyObjectFactory.java:134)
  | 	at org.jboss.ejb3.proxy.impl.objectfactory.session.stateless.StatelessSessionProxyObjectFactory.getProxy(StatelessSessionProxyObjectFactory.java:79)
  | 	at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.getObjectInstance(ProxyObjectFactory.java:158)
  | 	at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
  | 	at org.jnp.interfaces.NamingContext.getObjectInstance(NamingContext.java:1479)
  | 	at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1496)
  | 	... 39 more
  |    

Looking at the code, i think the right way to fix this is to change the   org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.delivery to deliver the message as part of the container's classloader:


  | Index: src/main/java/org/jboss/ejb3/mdb/inflow/MessageInflowLocalProxy.java
  | ===================================================================
  | --- src/main/java/org/jboss/ejb3/mdb/inflow/MessageInflowLocalProxy.java	(revision 91150)
  | +++ src/main/java/org/jboss/ejb3/mdb/inflow/MessageInflowLocalProxy.java	(working copy)
  | -         return delivery(proxy, container, method, args);
  | +      {
  | +         ClassLoader earlierClassLoader = Thread.currentThread().getContextClassLoader();
  | +         try
  | +         {
  | +            // Deliver the message through the container's classloader 
  | +            Thread.currentThread().setContextClassLoader(container.getClassloader());
  | +            return delivery(proxy, container, method, args);
  | +         }
  | +         finally
  | +         {
  | +            Thread.currentThread().setContextClassLoader(earlierClassLoader);
  | +         }
  | +
  | +      }
  |     }
  |  
  | 

Thoughts? Anything obviously wrong with this approach? 

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

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




More information about the jboss-dev-forums mailing list