10 Replies Latest reply on Mar 16, 2016 2:49 PM by dahm

    Wildfly 10: Problems with contextual proxy and JMS

    dahm

      Hi,

       

      I'm working with the new contextual proxy service in order to create bach jobs that run under certain privileges. I create a little

      sandbox to play with.

      Now I'm facing problems when submitting a batch job proxy to JMS. I'll attach the complete source code.

       

      The situation in short consists a batch job class:

       

      public class BatchJobImpl implements BatchJob {
          private static final long serialVersionUID = 1L;
          private static final Logger LOGGER = Logger.getLogger(BatchJobImpl.class.getName());
          private final String name;
          private final SecurityService securityService;
      
          public BatchJobImpl(final String name, final SecurityService securityService) {
              this.name = name;
              this.securityService = securityService;
           }
           ...
      }sss
      

       

      The SecurityService is an EJB that just prints out the current security context:

      @Stateless
      @RolesAllowed({"user", "admin"})
      @SecurityDomain("jumble-domain")
      public class SecurityService {
         @Resource
          private SessionContext ctx;
      
         public String getPrincipal() {
              final Principal principal = ctx.getCallerPrincipal()
              return principal.getName();
          }
      ...
      

       

      Now I have an MDB to run the batch job:

       

      @MessageDriven(activationConfig = {@ActivationConfigProperty(propertyName = "destinationLookup",
          propertyValue = Resources.Queue), @ActivationConfigProperty(propertyName = "destinationType",
          propertyValue = "javax.jms.Queue"),})
      public class BatchProcessor implements MessageListener {
          @Override
          public void onMessage(final Message message) {
                  final ObjectMessage omsg = (ObjectMessage) message;
                  final BatchJob batchJob = (BatchJob) omsg.getObject();
      ...
      

       

      I submit the job like this:

       

      public void submitBatchToJms(final String name) {
         final Map<String, String> execProps = new HashMap<>();
         execProps.put(ManagedTask.TRANSACTION, ManagedTask.USE_TRANSACTION_OF_EXECUTION_THREAD);
      
      
        final BatchJob proxy = contextService.createContextualProxy(new BatchJobImpl(name, securityService),
         execProps,BatchJob.class);
      
      
         Message message = jmsContext.createObjectMessage(proxy);
         JMSProducer jmsProducer = jmsContext.createProducer();
         jmsProducer.send(queue, message);
      }
      

       

      The problem is that when a run the example an JmsException is raised when calling getObject() on the message.

      My interpretation is that there is a class loader/resolution issue: The class EJBContextHandleFactory is found as it appears in the stack trace.

      However, there is obviously a problem with the inner class EJBContextHandleFactory$EJBContextHandle.

       

      Now whats going wrong here? Is there some conceptual error in my approach or is this just a bug in wildfly/JMS?

      I tried to fiddle around with a jboss-deployment-structure.xml but with no success.


      Cheers

           Markus

       

      P.S. the stack trace is

       

      2:08:19,982 SEVERE [de.akquinet.jbosscc.examples.eap.jms.BatchProcessor] (Thread-286 (ActiveMQ-client-global-threads-76563851)) batch job: javax.jms.JMSException: org.jboss.as.ejb3.component.concurrent.EJBContextHandleFactory$EJBContextHandle from [Module "org.apache.activemq.artemis:main" from local module loader @de3a06f (finder: local module finder @76b10754 (roots: /Servers/wildfly-10.0.0.Final/modules,/Servers/wildfly-10.0.0.Final/modules/system/layers/base))]
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:198)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:626)
        at org.apache.activemq.artemis.utils.ObjectInputStreamWithClassLoader.resolveClass0(ObjectInputStreamWithClassLoader.java:107)
        at org.apache.activemq.artemis.utils.ObjectInputStreamWithClassLoader.resolveClass(ObjectInputStreamWithClassLoader.java:52)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
        at org.jboss.as.ejb3.component.concurrent.EJBContextHandleFactory.readSetupContextHandle(EJBContextHandleFactory.java:72)
        at org.jboss.as.ee.concurrent.ConcurrentContext$ChainedSetupContextHandle.readObject(ConcurrentContext.java:250)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1058)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1900)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
        at org.apache.activemq.artemis.jms.client.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:139)
        at de.akquinet.jbosscc.examples.eap.jms.BatchProcessor.onMessage(BatchProcessor.java:29)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
        at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doMethodInterception(Jsr299BindingsInterceptor.java:82)
        at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:93)
        at org.jboss.as.ee.component.interceptors.UserInterceptorFactory$1.processInvocation(UserInterceptorFactory.java:63)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.invocationmetrics.ExecutionTimeInterceptor.processInvocation(ExecutionTimeInterceptor.java:43)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:437)
        at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:73)
        at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ee.concurrent.ConcurrentContextInterceptor.processInvocation(ConcurrentContextInterceptor.java:45)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InitialInterceptor.processInvocation(InitialInterceptor.java:21)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
        at org.jboss.as.ee.component.interceptors.ComponentDispatcherInterceptor.processInvocation(ComponentDispatcherInterceptor.java:52)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.pool.PooledInstanceInterceptor.processInvocation(PooledInstanceInterceptor.java:51)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:254)
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:329)
        at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:239)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.deployment.processors.EjbSuspendInterceptor.processInvocation(EjbSuspendInterceptor.java:53)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:66)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.as.ejb3.component.messagedriven.MessageDrivenComponentDescription$5$1.processInvocation(MessageDrivenComponentDescription.java:239)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
        at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:636)
        at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
        at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
        at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:195)
        at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:185)
        at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
        at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
        at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:73)
        at de.akquinet.jbosscc.examples.eap.jms.BatchProcessor$$$view4.onMessage(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.jboss.as.ejb3.inflow.MessageEndpointInvocationHandler.doInvoke(MessageEndpointInvocationHandler.java:139)
        at org.jboss.as.ejb3.inflow.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:73)
        at de.akquinet.jbosscc.examples.eap.jms.BatchProcessor$$$endpoint2.onMessage(Unknown Source)
        at org.apache.activemq.artemis.ra.inflow.ActiveMQMessageHandler.onMessage(ActiveMQMessageHandler.java:310)
        at org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.callOnMessage(ClientConsumerImpl.java:932)
        at org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.access$400(ClientConsumerImpl.java:47)
        at org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run(ClientConsumerImpl.java:1045)
        at org.apache.activemq.artemis.utils.OrderedExecutorFactory$OrderedExecutor$ExecutorTask.run(OrderedExecutorFactory.java:100)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
      
      
        • 1. Re: Wildfly 10: Problems with contextual proxy and JMS
          mnovak

          Could you try to modify your MANIFEST.MF for MDB and add there:

          Dependencies: org.jboss.as.ejb3
          

           

          It seems that MDB is missing those classes in its classloader and cannot read message which contains them.

          • 2. Re: Wildfly 10: Problems with contextual proxy and JMS
            dahm
            
            

            Miroslav Novak schrieb:

             

            Could you try to modify your MANIFEST.MF for MDB and add there:

            1. Dependencies: org.jboss.as.ejb3 

             

            It seems that MDB is missing those classes in its classloader and cannot read message which contains them.

            Hi.

             

            Thanks for your suggestion. It did not work however, the error remains.

            As I mentioned in the original post I try to use the deployment-structure file, which to my knowledge should have basically the same effect:

             

            <?xml version='1.0' encoding='UTF-8'?>
            
            <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
              <deployment>
              <dependencies>
               <module name="org.jboss.as.ejb3" export="true" />
              </dependencies>
              </deployment>
            </jboss-deployment-structure>
            



            • 3. Re: Wildfly 10: Problems with contextual proxy and JMS
              jbertram

              I'm not really familiar with javax.enterprise.concurrent.ContextService, but my hunch is that what you're trying to do simply isn't supported.

              • 4. Re: Wildfly 10: Problems with contextual proxy and JMS
                mnovak

                Thanks Markus for giving it a try.

                 

                I have 3 tips how to proceed. As you could send a message, I believe that all classes are serializable and in classloader when message is sent. Could you try to receive the message in the same code as you send it? If it succeeds then could you check which classes are in the classloader when you send a message and compare it with classloader for MDB. It could help to see if specifying dependencies in your deployment-structure file had effect.

                 

                Other quick try would be to add "org.jboss.as.ejb3" to:

                <subsystem xmlns="urn:jboss:domain:ee:3.0">
                            <global-modules>
                ...
                                <module name="org.jboss.as.ejb3" slot="main"/>
                            </global-modules>
                ...
                
                

                 

                in standalone...xml. It should load all classes from org.jboss.as.ejb3 module to classloader for all deployments.

                 

                Last thing what comes to my mind is to add "org.jboss.as.ejb3" dependency to "org.apache.activemq.artemis.ra" module.xml ($JBOSS_HOME/modules/system/layers/base/org/apache/activemq/artemis/ra/main/module.xml) like :

                ...
                <dependencies>
                        <module name="org.jboss.as.ejb3"/>
                ...
                
                

                 

                org.apache.activemq.artemis.ra is Artemis resouce adapter which is actually doing the receive of the message for you MDB. This could help as well.

                • 5. Re: Wildfly 10: Problems with contextual proxy and JMS
                  dahm

                  Hi.

                   

                  Well I got the example from the WebLogic example suite and adapted it a bit. So I guess it should work.

                  The main difference is that my object is holding a reference to an EJB when being serialized/deserialized.

                  This works fine if no JMS is involved.

                   

                  My guess is rather that the object cannot be properly deserialized, because it uses private constructors:

                   

                  public class EJBContextHandleFactory implements ContextHandleFactory {
                      public static final String NAME = "EJB";
                  
                      public static final EJBContextHandleFactory INSTANCE = new EJBContextHandleFactory();
                  
                      private EJBContextHandleFactory() {
                      }
                      ...    
                      private static class EJBContextHandle implements SetupContextHandle, ResetContextHandle {
                          private final transient InterceptorContext interceptorContext;
                          private EJBContextHandle() {
                          ...
                      ...
                  
                  • 6. Re: Wildfly 10: Problems with contextual proxy and JMS
                    dahm

                    Hi.

                     

                    I did all sorts of experiments with class loaders and modules, but nothing solved the problem. I now print out the class loader(s) in use when receiving the

                    message:

                     

                    11:19:41,795 INFO  [de.akquinet.jbosscc.examples.eap.jms.BatchProcessor] (Thread-288 (ActiveMQ-client-global-threads-857492803)) MDB: ModuleClassLoader for Module "deployment.eap-jumble.war:main" from Service Module Loader:vfs:/content/eap-jumble.war/WEB-INF/classes/de/akquinet/jbosscc/examples/eap/jms/BatchProcessor.class
                    11:19:41,797 INFO  [de.akquinet.jbosscc.examples.eap.jms.BatchProcessor] (Thread-288 (ActiveMQ-client-global-threads-857492803)) Message: ModuleClassLoader for Module "org.apache.activemq.artemis:main" from local module loader @de3a06f (finder: local module finder @76b10754 (roots: /Servers/wildfly-10.0.0.Final/modules,/Servers/wildfly-10.0.0.Final/modules/system/layers/base)):jar:file:/Servers/wildfly-10.0.0.Final/modules/system/layers/base/org/apache/activemq/artemis/main/artemis-jms-client-1.1.0.wildfly-011.jar!/org/apache/activemq/artemis/jms/client/ActiveMQObjectMessage.class
                    

                     

                    I stripped down the sent object so it only contains a String. Even that did not work.

                     

                    So my conclusion is the Wildfly in general cannot handle contextual proxies in JMS/MDBs.

                    I do not know whether this feature is spec-compliant, yet WebLogic is obviously capable (unless they ship examples that do not work :-)

                     

                    Maybe I should file a bug report...?

                     

                    Cheers

                         Markus

                    • 7. Re: Wildfly 10: Problems with contextual proxy and JMS
                      mnovak

                      if you can receive message in submitBatchToJms() method and call:

                      final ObjectMessage omsg = (ObjectMessage) message;  
                                  final BatchJob batchJob = (BatchJob) omsg.getObject();  
                      
                      

                       

                      then it should be possible to do that in MDB as well and it's classloading problem.

                      • 8. Re: Wildfly 10: Problems with contextual proxy and JMS
                        dahm

                        Miroslav Novak schrieb:

                         

                        if you can receive message in submitBatchToJms() method and call:

                        1. final ObjectMessage omsg = (ObjectMessage) message;   
                        2.             final BatchJob batchJob = (BatchJob) omsg.getObject();   

                         

                        then it should be possible to do that in MDB as well and it's classloading problem.

                        I forgot to mention that I tried that, too. Same problem... Thus I concluded it's a general problem ....

                        • 9. Re: Wildfly 10: Problems with contextual proxy and JMS
                          emmartins

                          When you create the contextual proxy the invocation context is saved, my guess is that some of that context is not saved, and it's needed later when invoking such object. Please open a JIRA, link it to this post, and assign it to me, I will have a look when possible.

                          • 10. Re: Wildfly 10: Problems with contextual proxy and JMS
                            dahm

                            I opened an issue under

                             

                            https://issues.jboss.org/browse/WFLY-6385

                             

                            but I cannot change the assignee.

                             

                            Cheers

                              Markus