4 Replies Latest reply on Feb 4, 2011 9:43 AM by mluisbrown

    MDB - Obejctmessage exception

    tweetysat

      Hi.

       

      I'm quite new with jms.  I'm working with jboss 5.0.1.

       

      First step was to create a producer and a consumer application.  It's working fine.  I tried sending/receiving a textmessage and an objectmessage.  It's ok.

       

      Second step.  I'm trying to create a message driven bean.  It's working fine receiving a textmessage but NOT working with an object message.

       

      Perhaps you could help me.

       

      My object

       

       

       

      package objects;

      import java.io.Serializable;

      public class Student implements Serializable

      {

          private static final long serialVersionUID = 1L;

          private String name;

          private String school;

          public String getName()

          {

              return name;

          }

          public void setName(String name)

          {

              this.name = name;

          }

          public String getSchool()

          {

              return school;

          }

          public void setSchool(String school)

          {

              this.school = school;

          }

          @Override

          public String toString()

          {

              return "Student [name="+this.name+",school="+this.school+"]";

          }

      }

       

       

       

      My mdb

       

      package jms;

      import javax.annotation.Resource;

      import javax.ejb.ActivationConfigProperty;

      import javax.ejb.MessageDriven;

      import javax.ejb.MessageDrivenContext;

      import javax.jms.JMSException;

      import javax.jms.Message;

      import javax.jms.MessageListener;

      import javax.jms.ObjectMessage;

      import javax.jms.TextMessage;

      import messages.Student;

      import org.apache.log4j.Logger;

      import myobjects.Student;

       

      @MessageDriven(name="ConsumerBean",

                     activationConfig =

                       {

                       @ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Topic"),

                       @ActivationConfigProperty(propertyName="destination",propertyValue="topic/myTopic")

                       }

                     )

      public class ConsumerBean implements MessageListener

      {

          @Override

          public void onMessage(Message message)

          {

              Logger logger = Logger.getLogger(ConsumerBean.class);

              logger.info("MDB v2 : "+message.toString());

              if(message instanceof TextMessage)

              {

                  String text = "";

                  try

                  {

                      text = ((TextMessage)message).getText();

                  }

                  catch (JMSException e)

                  {

                      e.printStackTrace();

                  }

                  logger.info("TextMessage : "+text);

              }

              else if(message instanceof ObjectMessage)

              {

                  logger.info("ObjectMessage Detected");

                  Student st = null;

                  try

                  {

                      ObjectMessage om = (ObjectMessage) message;

                      logger.info("ObjectMessage Created");

                      Student s = (Student) om.getObject();

                      logger.info("Student created");

                      logger.info(s.toString());

                  }

                  catch (Exception e)

                  {

                      e.printStackTrace();

                  }

                  logger.info("Object Message : "+st.toString());

             }

          }}

       

      Executing the line

       

       

      Student s = (Student) om.getObject();

       

       

      Produce this exception

       

       

      10:14:14,850 ERROR [STDERR] java.lang.RuntimeException: Student

      10:14:14,850 ERROR [STDERR]     at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

      10:14:14,850 ERROR [STDERR]     at java.security.AccessController.doPrivileged(Native Method)

      10:14:14,850 ERROR [STDERR]     at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

      10:14:14,850 ERROR [STDERR]     at java.lang.ClassLoader.loadClass(ClassLoader.java:307)

      10:14:14,850 ERROR [STDERR]     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

      10:14:14,850 ERROR [STDERR]     at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

      10:14:14,850 ERROR [STDERR]     at java.lang.Class.forName0(Native Method)

      10:14:14,850 ERROR [STDERR]     at java.lang.Class.forName(Class.java:247)

       

      ...
        • 1. MDB - Obejctmessage exception
          tweetysat

          Ok, I've - almost - solved the the problem.

           

          In fact the problem is that the Student class is in a package and the MDB in another package.

           

          Using

           

          logger.info(this.getClass().getClassLoader());

          logger.info(Thread.currentThread().getContextClassLoader());

           

          give me

           

          13:37:15,760 INFO  [ConsumerBean] BaseClassLoader@1a3df98{vfszip:/D:/java/jboss-5.0.1.GA/server/jms/deploy/ejb1.jar/}

          13:37:15,760 INFO  [ConsumerBean] BaseClassLoader@1a3df98{vfszip:/D:/java/jboss-5.0.1.GA/server/jms/deploy/ejb1.jar/}

           

          So if the 2 classes are in the default package (in the root of the jar), there is no problem.

          But if I use packages to store my classes it's not working.

           

          What can I do ?

          • 2. Re: MDB - Obejctmessage exception
            mluisbrown

            This is a bug, as mentioned in this thread http://community.jboss.org/message/517604#517604 , allthough supposedly it has been fixed in JBoss 5.0.1 GA.

             

            The workaround which I am using is mentioned in the thread, but here it is again:

             

             

            {code:java}

            logger.info("ObjectMessage Detected");

             

            Student st = null;

             

            // get the current TCCL

            ClassLoader originalTCCL = Thread.currentThread().getContextClassLoader();

             

            try

            {

                // temporarily change TCCL

                Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

             

                ObjectMessage om = (ObjectMessage) message;

                logger.info("ObjectMessage Created");

                Student s = (Student) om.getObject();

                logger.info("Student created");

                logger.info(s.toString());

            }

            catch (Exception e)

            {

                e.printStackTrace();

            }

            finally

            {

                // set back the original TCCL

                Thread.currentThread().setContextClassLoader(originalTCCL);

            }

             

            logger.info("Object Message : "+st.toString());

            {code}

            • 3. MDB - Obejctmessage exception
              tweetysat

              Hello Michael.

               

              Perhaps I do not explain very well my problem or perhaps I do not understand your solution but ... it's not wroking.

               

              Now I got :

               

              For the producer : the main class in the default package and the Student class in a 'objects' package.  It sends an object message to a topic.

               

              For the consumer (mdb) : the mdb is in a 'jms' package and the Student class in a 'myobjects' package.

               

              Giving me

               

              14:18:29,335 ERROR [STDERR] java.lang.RuntimeException: objects.Student

              14:18:29,351 ERROR [STDERR]     at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

              14:18:29,351 ERROR [STDERR]     at java.security.AccessController.doPrivileged(Native Method)

              14:18:29,351 ERROR [STDERR]     at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

              14:18:29,351 ERROR [STDERR]     at java.lang.ClassLoader.loadClass(ClassLoader.java:307)

              14:18:29,351 ERROR [STDERR]     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

              14:18:29,351 ERROR [STDERR]     at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

              ....

               

              And I don't understand why 'objects.Student' and not only 'Student'

               

               

              So ... the only way to make the bean working is renaming the 'myobjects' package to 'objects'.  The Student class MUST be in the same package.

               

              I don't know if your solution is supposed to solve the problem but I don't understand why

               

               

               

                          logger.info(Thread.currentThread().getContextClassLoader());

                          logger.info(this.getClass().getClassLoader());

               

               

              is giving

               

               

              14:18:29,335 INFO  [ConsumerBean] BaseClassLoader@eeeb48{vfszip:/D:/java/jboss-5.0.1.GA/server/jms/deploy/ejb1.jar/}

              14:18:29,335 INFO  [ConsumerBean] BaseClassLoader@eeeb48{vfszip:/D:/java/jboss-5.0.1.GA/server/jms/deploy/ejb1.jar/}

               

               

              so that the "temporarily change TCCL" have not effect.

              • 4. MDB - Obejctmessage exception
                mluisbrown

                And I don't understand why 'objects.Student' and not only 'Student'

                 

                 

                So ... the only way to make the bean working is renaming the 'myobjects' package to 'objects'.  The Student class MUST be in the same package.

                 

                Your class Student is in the package "objects". When you send a Student object in an object message it is serialized as an object of type "objects.Student". That same class has to be available in your MDB. However, in your MDB code you appear to be referring to a different type of Student class in the package "myobjects", ie: myobjects.Student. You need to import the "objects.Student" class in your MDB code. In Java, two classes with the same name but in different packages are two totally different classes that have nothing to do with each other. You're getting the error because the MDB can't find and load the class "objects.Student", which it needs to deserialize the object.

                 

                You can ignore what I wrote above about switching classloaders. It looked similar to a problem I was having which was due to a JBoss Messaging bug which I believe was fixed in 5.0.1.