1 2 Previous Next 18 Replies Latest reply on Feb 24, 2015 1:05 AM by Amit Dey

    JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage

    Alexander Lengson Newbie

      Hello All,

       

      Please help me to recognize my trouble with messaging in JBoss 5.1.0:

       

      My message's consumer class extends MessageListener.

      The single object of consumer is created in servlet's init() method.

       

      Servlet is part of WAR which is packaged inside EAR module.

      There is jar module which share common classes for WAR and other EJBs in EAR.

       

      One of EJB sends JMS message ObjectMessage to some topic which is monitored by the servlet's consumer.

      Payload of ObjectMessage is one of common shared classes.

       

      The servlet's consumer can not resolve the class of the object passed in ObjectMessage and fails at line:

       

      public void onMessage(Message recvmsg) {

          ObjectMessage om = (ObjectMessage) recvmsg;


          Class classOrder = Class.forName("com.name.shared.Order"); // ok!

          om.getObject(); // here fails!

       

      I've noticed that classloaders of the recvmsg and classOrder are different:

      INFO  [EventListenerServlet] BaseClassLoader@1a7249f{vfsfile:/C:/jboss/jboss-5.1.0.GA/server/standard/deploy/ecom.ear/}

      INFO  [EventListenerServlet] BaseClassLoader@fb111c{vfsfile:/C:/jboss/jboss-5.1.0.GA/server/standard/conf/jboss-service.xml}

      Is that exception due to the difference between class loaders actually?

       

      The strange point is that the code works from time to time (in the case of rare messages, for example). When messages go quickly, it starts throwing exceptions.

       

      Stack trace:

       

      ERROR [ClientConsumer] RuntimeException was thrown from onMessage, 20669661515808833 will be redelivered

      java.lang.RuntimeException: com.name.shared.Order

      at java.net.URLClassLoader$1.run(URLClassLoader.java:200)

      at java.security.AccessController.doPrivileged(Native Method)

      at java.net.URLClassLoader.findClass(URLClassLoader.java:188)

      at java.lang.ClassLoader.loadClass(ClassLoader.java:307)

      at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

      at java.lang.ClassLoader.loadClass(ClassLoader.java:252)

      at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)

      at java.lang.Class.forName0(Native Method)

      at java.lang.Class.forName(Class.java:247)

      at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:292)

      at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1119)

      at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:798)

      at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:441)

      at java.lang.ClassLoader.loadClass(ClassLoader.java:252)

      at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)

      at java.lang.Class.forName0(Native Method)

      at java.lang.Class.forName(Class.java:247)

      at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)

      at org.jboss.messaging.util.ObjectInputStreamWithClassLoader.resolveClass(ObjectInputStreamWithClassLoader.java:78)

      at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)

      at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)

      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)

      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)

      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)

      at org.jboss.messaging.util.StreamUtils.readObject(StreamUtils.java:154)

      at org.jboss.messaging.core.impl.message.MessageSupport.readPayload(MessageSupport.java:392)

      at org.jboss.jms.message.JBossObjectMessage.getObject(JBossObjectMessage.java:126)

      at org.jboss.jms.message.ObjectMessageProxy.getObject(ObjectMessageProxy.java:68)

      at com.name.servlet.EventListenerServlet$EventListener.onMessage(EventListenerServlet.java:201)

      at org.jboss.jms.client.container.ClientConsumer.callOnMessage(ClientConsumer.java:229)

      at org.jboss.jms.client.container.ClientConsumer$ListenerRunner.run(ClientConsumer.java:1043)

      at org.jboss.messaging.util.OrderedExecutorFactory$ChildExecutor.run(OrderedExecutorFactory.java:120)

      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

      at java.lang.Thread.run(Thread.java:619)

        • 1. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
          Yong Hao Gao Master

          Hi,

           

          Do you have a test for this? Also the latest release for AS5 is 1.4.6.GA, can you try it?

          It hasn't been updated into AS 5 distribution so you need to build yourself from tag.

           

          Also please post this question to AS forum also and if they can catch any known issues about this.

           

          Howard

          1 of 1 people found this helpful
          • 2. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
            Alexander Lengson Newbie

            Hello,

             

            Thanks for your attention.

            Currently there is no test - I discovered that behavior when was testing the whole server.

            My JBossAS 5.1.0 has default version of jboss-messaging.jar "1.4.3.GA"

             

            I tried the same scenario on JBossAS 5.0.1 with messaging "1.4.1.GA"

            There is no such problem on that configuration.

             

            I will try it again on AS 5.1.0 with 1.4.6.GA as you suggested.

             

            Alex.

            • 3. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
              Alexander Lengson Newbie

              Yong,

               

              Could you tell me please is there a description of the process for updating messaging in JBoss AS?

               

              Just simple copying files from jboss-messaging-1.4.5.GA as followed by 'jboss-messaging-1.4.5.GA\README.html' caused many startup errors in jboss AS 5.1.0 .

              • 4. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                Yong Hao Gao Master

                Hi Alex,

                 

                1.4.5.GA is for AS 4.x, please not to use it.

                 

                The latest version for AS 5 is 1.4.6.GA. Unfortunately it hasn't been updated into community AS 5.x releases. So you need to do manually as described in the following:

                 

                1. download the source from http://anonsvn.jboss.org/repos/messaging/tags/JBossMessaging_1_4_6_GA/

                2. build it.

                <source_root>/ant release-bundle

                the binary will be under <source_root>/output/lib/, it's a zip file named like jboss-messaging-1.4.6.GA.zip. Unzip it to a folder.


                3. Updating JBM jars. Simply replacing every occurence of the elements listed below with the same element in the 1.4.6.GA folder

                 

                jboss-messaging-client.jar

                jboss-messaging.jar

                4. Updating JBM configuration files. You need to replace each configuration files under deploy/messaging/ with those in 1.4.6.GA folder. They are mostly under examples/config.

                 

                5. Updating JBoss Remoting. JBM 1.4.6.GA requires remoting 2.5.2 to work. Download it from jboss.org.

                 

                That's all. You can run examples to verify the update is ok. The examples can be downloaded here:

                 

                http://www.jboss.org/downloading/?projectId=jbossmessaging&url=/jbossmessaging/downloads/jbm-examples-1.4.6.zip

                • 5. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                  Alexander Lengson Newbie

                  Hello Yong,

                   

                  Thank you for this guide.

                   

                  I tried 1.4.5.GA earlier as it was nearest to 1.4.6.GA release available right away. I had no idea that it is for AS4, sorry.

                   

                  jboss-messaging-1.4.6.GA installed well.

                  Ant build was ok, jars replacement too. The only different config file located in "jboss-messaging-1.4.6.GA" was remoting-bisocket-service.xml, I replaced it. jboss-remoting-2_5_2.zip updated well.

                   

                  Server started ok, but the erroneous behavior persisted.

                  MessageListener again accepts few first messages, and then starts throwing exceptions:

                   

                  Stack trace:

                  2009-12-25 13:22:10,687 ERROR [org.jboss.jms.client.container.ClientConsumer] (Thread-45) RuntimeException was thrown from onMessage, 5168072829600301 will be redelivered

                  java.lang.RuntimeException: com.name.sphere.messages.generic.Order

                  at java.net.URLClassLoader$1.run(URLClassLoader.java:200)

                  at java.security.AccessController.doPrivileged(Native Method)

                  at java.net.URLClassLoader.findClass(URLClassLoader.java:188)

                  at java.lang.ClassLoader.loadClass(ClassLoader.java:307)

                  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

                  at java.lang.ClassLoader.loadClass(ClassLoader.java:252)

                  at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)

                  at java.lang.Class.forName0(Native Method)

                  at java.lang.Class.forName(Class.java:247)

                  at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:292)

                  at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1119)

                  at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:798)

                  at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:441)

                  at java.lang.ClassLoader.loadClass(ClassLoader.java:252)

                  at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)

                  at java.lang.Class.forName0(Native Method)

                  at java.lang.Class.forName(Class.java:247)

                  at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)

                  at org.jboss.messaging.util.ObjectInputStreamWithClassLoader.resolveClass(ObjectInputStreamWithClassLoader.java:78)

                  at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)

                  at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)

                  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)

                  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)

                  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)

                  at org.jboss.messaging.util.StreamUtils.readObject(StreamUtils.java:154)

                  at org.jboss.messaging.core.impl.message.MessageSupport.readPayload(MessageSupport.java:405)

                  at org.jboss.jms.message.JBossObjectMessage.getObject(JBossObjectMessage.java:126)

                  at org.jboss.jms.message.ObjectMessageProxy.getObject(ObjectMessageProxy.java:68)

                  at com.name.controller.EventListenerServlet$EventListener.onMessage(EventListenerServlet.java:194)

                  at org.jboss.jms.client.container.ClientConsumer.callOnMessage(ClientConsumer.java:229)

                  at org.jboss.jms.client.container.ClientConsumer$ListenerRunner.run(ClientConsumer.java:1043)

                  at org.jboss.messaging.util.OrderedExecutorFactory$ChildExecutor.run(OrderedExecutorFactory.java:120)

                  at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)

                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)

                  at java.lang.Thread.run(Thread.java:619)

                  • 6. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                    jaikiran pai Master

                    sanches wrote:

                     


                    at java.lang.Class.forName(Class.java:247)

                    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)

                    at org.jboss.messaging.util.ObjectInputStreamWithClassLoader.resolveClass(ObjectInputStreamWithClassLoader.java:78)

                    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)

                    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)

                    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)

                    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)

                    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)

                    at org.jboss.messaging.util.StreamUtils.readObject(StreamUtils.java:154)

                    at org.jboss.messaging.core.impl.message.MessageSupport.readPayload(MessageSupport.java:392)

                    at org.jboss.jms.message.JBossObjectMessage.getObject(JBossObjectMessage.java:126)

                    at org.jboss.jms.message.ObjectMessageProxy.getObject(ObjectMessageProxy.java:68)

                    at com.name.servlet.EventListenerServlet$EventListener.onMessage(EventListenerServlet.java:201)

                    at org.jboss.jms.client.container.ClientConsumer.callOnMessage(ClientConsumer.java:229)


                     

                     

                    Looking at that stacktrace and the code in StreamUtils and ObjectInputStreamWithClassLoader http://anonsvn.jboss.org/repos/messaging/tags/JBossMessaging_1_4_3_GA/src/main/org/jboss/messaging/util/ it appears that JBM uses the TCCL to read the object in the ObjectMessage.The problem arises because when the message is being delivered (is it happening during server/application startup?), the TCCL is the BaseClassLoader of the server and may *not* have access to the classes within a deployment which contain the class required by the ObjectMessage contents. This is because the deployment might have its own classloader configured - do you have a jboss-app.xml in the .ear with the classloader configurations? The real fix to this is probably to make sure that the delivery happens within the classloader of the deployment - but i don't know much about JBM, so not sure if that's feasible.

                    • 7. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                      Alexander Lengson Newbie

                      Hi jaikiran,

                       

                      (is it happening during server/application startup?),

                      Not really. I run the test which causes the message to be sent after server started fully.

                       

                      the TCCL is the BaseClassLoader of the server and may *not* have access to the classes within a deployment which contain the class required by the ObjectMessage contents. This is because the deployment might have its own classloader configured - do you have a jboss-app.xml in the .ear with the classloader configurations? The real fix to this is probably to make sure that the delivery happens within the classloader of the deployment - but i don't know much about JBM, so not sure if that's feasible.

                      No, there is no jboss-app.xml within EAR in the case of Eclipse JBossAS Tools usage.

                      And yes, there is empty META-INF\jboss-app.xml when the EAR is built by Maven. But it does not contain anything beside DTD and <jboss-app/>

                       

                      The same code works well being deployed on JBoss 5.0.1. (output shows that classloaders names are the same as they are on 5.1.0, so my initial guess may not be valuable)

                       

                      Thanks,

                      Alex

                      • 8. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                        jaikiran pai Master

                        sanches wrote:

                         

                        Servlet is part of WAR which is packaged inside EAR module.

                        There is jar module which share common classes for WAR and other EJBs in EAR.

                         

                        Where exactly is that jar placed in the ear? Can you post the output of

                         

                        jar -tf ecom.ear
                        
                        • 9. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                          Alexander Lengson Newbie
                          META-INF/
                          META-INF/MANIFEST.MF
                          lib/
                          cp-1.0-SNAPSHOT.jar
                          da-1.0-SNAPSHOT.jar
                          disp-1.0-SNAPSHOT.jar
                          env-1.0-SNAPSHOT.jar     //  <== shared classes
                          htc-1.0-SNAPSHOT.war     // <== WAR, servlet and MessageListener here
                          lib/annotations-0.1.jar
                          lib/commons-codec-1.3.jar
                          lib/commons-logging-1.1.0.jboss.jar
                          lib/httpclient-4.0.jar
                          lib/httpcore-4.0.1.jar
                          lib/janino-2.5.15.jar
                          lib/mvel2-2.0.10.jar
                          lib/qdox-1.9.1.jar
                          lib/stax-api-1.0.1.jar
                          lib/xstream-1.3.1.jar
                          META-INF/application.xml
                          META-INF/jboss-app.xml
                          META-INF/maven/
                          META-INF/maven/com.name.prj
                          • 10. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                            jaikiran pai Master

                            I still believe that it's a case of the wrong classloader (the server level BaseClassLoader) being used during delivery of the message. From what i see in your posts, it appears that the shared class (com.name.shared.Order) gets loaded by the isolated war classloader (yes, by default .war has a separate isolated classloader). Then the EJB sends a message and JBM delivers this message to the listener in the .war using the TCCL which happens to be the server level classloader and not the deployment classloader.

                             

                            Try either of these 2 things, just to be sure that this is exactly what's happening:

                             

                            1) Follow the point#1 mentioned in this wiki http://community.jboss.org/wiki/useJBossWebClassLoaderinJBoss5

                             

                            OR

                             

                            2) Edit your com.name.servlet.EventListenerServlet$EventListener.onMessage to temporarily change the TCCL:

                             

                             

                            public void onMessage(Message recvMsg)
                            {
                            
                             ObjectMessage om = (ObjectMessage) recvMsg;
                            
                            
                            ClassLoader originalTCCL = Thread.currentThread().getContextClassLoader();
                            try
                            {
                              // temporarily change TCCL, just for testing
                              Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
                               // now get the message from ObjectMessage
                             Object obj =   om.getObject();
                             // print out the message for testing
                             System.out.println("Obtained message " + obj);
                            }
                            finally
                            {
                              // set back the original TCCL
                             Thread.currentThread().setContextClassLoader(originalTCCL);
                            }
                            ...
                            

                             

                            Note that, neither of these changes are the actual fix to the problem. This change is just to make sure that we have a clear understanding of what's going on.

                            1 of 1 people found this helpful
                            • 11. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                              Alexander Lengson Newbie

                              I've tried both:

                               

                              1)  c:\jboss\jboss-5.1.0.GA\server\standard\deployers\jbossweb.deployer\META-INF\war-deployers-jboss-beans.xml

                              WarClassLoaderDeployer commented out:

                                 <!-- Allow for war local class loaders: in testing -->

                                 <!--

                                 <bean name="WarClassLoaderDeployer" class="org.jboss.web.tomcat.service.deployers.WarClassLoaderDeployer">

                                    <property name="relativeOrder">-1</property>

                                    <property name="filteredPackages">javax.servlet,org.apache.commons.logging</property>     

                                 </bean>

                                      -->

                               

                              Result:

                              21:12:26,687 INFO  [EventListenerServlet] BaseClassLoader@17cb2f7{vfsfile:/C:/jboss/jboss-5.1.0.GA/server/standard/conf/jboss-service.xml} //for incoming JMS Message

                              21:12:26,687 INFO  [EventListenerServlet] BaseClassLoader@175626d{vfsfile:/C:/jboss/jboss-5.1.0.GA/server/standard/deploy/ecom.ear/} // for this

                              21:12:26,691 ERROR [ClientConsumer] RuntimeException was thrown from onMessage, 5168188334375036 will be redelivered
                              2) WarClassLoaderDeployer is uncommented,
                              the code you've posted above is in use.
                              Exceptions now are gone!
                              What is printed:
                              21:23:48,171 INFO  [EventListenerServlet] Obtained message delegator->JBossMessage[5168191193776141]:PERSISTENT, deliveryId=13
                              21:23:48,171 INFO  [EventListenerServlet] BaseClassLoader@876cb0{vfsfile:/C:/jboss/jboss-5.1.0.GA/server/standard/conf/jboss-service.xml} //for incoming JMS Message
                              21:23:48,171 INFO  [EventListenerServlet] BaseClassLoader@1e59a4d{vfsfile:/C:/jboss/jboss-5.1.0.GA/server/standard/deploy/ecom.ear/htc.war/} // for this
                              Thank you for your guidance!
                              Is there an explanation to such difference between 5.0.1 and 5.1.0?
                              I remember you noticed this is not a solution really.
                              Do you have any assumptions what could be the cause of such behavior?
                              • 12. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                                Ola Hamfors Newbie

                                I have the same problem but in a sligthly different setting.

                                I have a ear (The ear defines a loader-repository in jboss-app.xml) with 2 nested jar files (ejbs) and one of the jar files has a MDB that recieves object messages send from a class in the other jar file i.e within the same ear.

                                I'm using jboss-eap-5.0.0.GA. But I guess I should report this in another channel.

                                Your class loader test with the change of classloaders before obtaining the objectmessage solved the problem for me too..

                                • 13. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                                  Michael Brown Newbie

                                  I'm having exactly the same issue as Ola Hamfors above. My setup is almost identical to his, and I'm also using JBoss EAP 5.0.0GA. jaikiran pai's "solution" number 2) of changing the classloader in onMessage() solved the problem. Is there a proper solution for this, or is it a JBoss bug?

                                  • 14. Re: JMS Consumer (servlet) can not resolve class of the object passed in ObjectMessage
                                    Ola Hamfors Newbie

                                    Yes, is was a bug and it is solved in 5.0.1GA. I think the patch was called (JBPAPP-3748)

                                    1 2 Previous Next