14 Replies Latest reply on May 15, 2012 5:40 PM by clebert.suconic

    JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object

    sraue

      I try to port our application from jboss 4.2.2GA to jboss 7.1.1. After 4 weeks of work most parts of the application are running now on jboss 7.1.1.

      But we are facing now a problem with hornetq:

       

      We have made a data transfer object generator library some years ago which generate dto instances on the fly only knowing the respective interface

      of the dto to generate. The library produces java.lang.reflect.Proxy objects which we - stateless session beans - send as object messages to message queues.

      The respective MessageListener of our application gets the message - onMessage is called with the message object - but when we call ( ( ObjectMessage )inMessage ).getObject()

      we get a long stack trace:

       

      .....

       

      Caused by: javax.jms.JMSException: com.pvs.pmm.sratest.events.data.MyObjectMessage from [Module "org.hornetq:main" from local module loader @2adb1d4 (roots: /home/sra/newworkspace/workspace/jboss/modules)]

          at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)

          at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:468)

          at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:456)

          at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:423)

          at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)

          at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:120)

          at java.lang.Class.forName0(Native Method) [rt.jar:1.6.0_29]

          at java.lang.Class.forName(Class.java:247) [rt.jar:1.6.0_29]

          at java.io.ObjectInputStream.resolveProxyClass(ObjectInputStream.java:675) [rt.jar:1.6.0_29]

          at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1530) [rt.jar:1.6.0_29]

          at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1492) [rt.jar:1.6.0_29]

          at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731) [rt.jar:1.6.0_29]

          at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) [rt.jar:1.6.0_29]

          at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350) [rt.jar:1.6.0_29]

          at org.hornetq.jms.client.HornetQObjectMessage.getObject(HornetQObjectMessage.java:158)

          at com.pvs.pmm.sratest.events.receivers.TestReceiver.onMessage(TestReceiver.java:28) [pmm-ejb.jar:]

         ... 54 more

       

      .......

       

      com.pvs.pmm.sratest.events.data.MyObjectMessage is the interface from which the proxy object has been generated.

       

      When we send an instance of a class which implements  com.pvs.pmm.sratest.events.data.MyObjectMessage all

      is fine. We used our dto generator (sending jms message objects) with jboss 4.0.5, 4.2.2GA and I have ported our

      application successful to jboss 6 some years ago.

       

      PLEASE HELP!

        • 1. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
          clebert.suconic

          This seems a classLoader issue to me.

           

          If you do Thread.currentThread().getContextClassLoader().findClass(your-class-name);

           

          what would you get?

          • 2. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
            sraue

            Thread.currentThread().getContextClassLoader().findClass(your-class-name);

             

            method is not visible in my MessageListener but

             

            Thread.currentThread().getContextClassLoader().loadClass(your-class-name);

             

            does not throw any exception and returns my interface class.

            • 3. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
              sraue

              Here is how the proxy object message is created

               

              HashMap <String,Object> values = new HashMap<String, Object>();

              MyObjectMessage            dto      = ( MyObjectMessage )Proxy.newProxyInstance( MyObjectMessage.class.getClassLoader(),

                                                                                                                                        new Class[]{ MyObjectMessage.class },

                                                                                                                                        new GenericDTOImpl( values ) );

               

              values.put( "stringValue", "HUHU" ); 

              values.put( "longValue",   4711L );

              values.put( "intValue",      42 );

              ObjectMessage message = session.createObjectMessage( dto );

              -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

               

              MyObjectMessage is:

               

              public interface MyObjectMessage {

                   String getStringValue();

                   Long  getLongValue();

                   int     getIntValue();

              }

               

              GenericDTOImpl implements public Object invoke(Object proxy, Method m, Object[] args)

              which returns the HashMap value when the respective getXX method is called on the dto

              - e.g. dto.getStringValue() returns "HUHU", dto.getLongValue() returns 4711 and dto.getIntValue() returns 42.

              • 4. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                clebert.suconic

                How are you consuming? MDBs?

                 

                try doing this:

                 

                 

                Thread.currentThread().setContextClassLoader(someOfYourClass.getClassLoader());

                 

                try

                {

                   message.getObject();

                }

                finally

                {

                   setTheClassLoader back to what it was
                }

                 

                If you are doing your own Consumer, you are doing something out of EE support and then you have to do something like that.

                 

                 

                If you're not doing anything special.. (plain MDBs or regular recieve on a consumer).. then you are hittnig a bug and you need to provide a testcase showing of the bug to hornetQ and AS7 teams.

                • 5. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                  sraue

                  I get the same exception and I don't think that changes like this can help.

                  As I wrote when I send an object of a class which implements the interface

                  class com.pvs.pmm.sratest.events.data.MyObjectMessage everything is fine

                  - no exception etc.. It must have something to do with the proxy objects.

                  Are proxy objects handled different than objects of ordinary classes?

                  • 6. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                    ataylor

                    I would suggest providing a test that we can look at, i will then get thge AS7 guys to look at it, the classloaders in AS7 are much stricter than in previous versions, i.e. you arent supposed to have access to stuff you arent supposed too, so maybe this is one of those instances.

                    • 7. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                      jaikiran

                      How does the packaging of the application look like:

                       

                      1) Where is the MyObjectMessage.class located?

                      2) Where is the MDB located?

                       

                      The exception stacktrace you posted doesn't look like the complete exception stacktrace. Please post the complete exception stacktrace. Also please post the output of:

                       

                      Thread.currentThread().getContextClassLoader()

                       

                      from within the onMessage() method of the MDB.

                      • 8. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                        sraue

                        Here is an example ant project of what fails (and what works):

                         

                        1. unzip jboss 7.1.1 final somewhere

                        2. run jboss/bin/add-user.(bat/sh)

                            and add the application user "testuser"

                            with password "testpassword"

                        3. unzip the attached zip file

                        4. go into jms-proxy-test - directory from zip file

                        5. edit build.xml -> set jboss.home appropriate

                        6. run ant

                        7. run jboss/bin/standalone.(bat/sh)

                            and wait until jms-proxy-test.ear has been deployed

                        8. run ant run-client

                         

                        There are two services - stateless session beans - inside the

                        project:

                         

                        one that works fine by sending an instance of an ordinary class (TestObjectServiceImpl.java) and

                        one tha fails by sending a proxy object (TestProxyServiceImpl.java).

                         

                        The client class first calls the object sending service and then the

                        proxy object sending one

                        • 9. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                          sraue

                          Any news regarding my problem?

                          • 10. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                            sraue

                            I have managed to resolve the problem. It is a problem in org.hornetq.utils.ObjectInputStreamWithClassLoader:

                            The ObjectInputStreams'  resolveProxyClass method has to be overriden:

                             

                               @Override

                                protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException

                                {

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

                                   ClassLoader nonPublicLoader = null;

                                   boolean hasNonPublicInterface = false;

                                   // define proxy in class loader of non-public interface(s), if any

                                   Class[] classObjs = new Class[interfaces.length];

                                   for (int i = 0; i < interfaces.length; i++) {

                                      Class cl = Class.forName(interfaces[i], false, latestLoader);

                                      if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {

                                         if (hasNonPublicInterface) {

                                            if (nonPublicLoader != cl.getClassLoader()) {

                                               throw new IllegalAccessError("conflicting non-public interface class loaders");

                                            }

                                         } else {

                                            nonPublicLoader = cl.getClassLoader();

                                            hasNonPublicInterface = true;

                                         }

                                      }

                                      classObjs[i] = cl;

                                   }

                                   try {

                                      return Proxy.getProxyClass(hasNonPublicInterface ? nonPublicLoader : latestLoader, classObjs);

                                   } catch (IllegalArgumentException e) {

                                      throw new ClassNotFoundException(null, e);

                                   }

                               }

                             

                            What do I have to do that the fix goes into the hornetq svn - into the next release?

                             

                            I've made a jira issue (HornetQ/HORNETQ-905)

                            • 11. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                              clebert.suconic

                              We are using github now...

                               

                              If you can help, I would need a test on ObjectInputStreamWithClassLoaderTest

                               

                               

                              What's the deal on nonPublicLoader? Why you can't mix classLoaders there, and why you can't just use a Class.forName(interfaceName) if the classLoader couldn't solve it?

                               

                               

                              If I have a test on ObjectinputStreamWithClassLoaderTest I will push the change right away.

                              • 12. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                                sraue

                                I have just copied the code of ObjectInputStreams' resolveProxyClass of the jdk

                                and changed the line

                                 

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

                                 

                                according to the code of ObjectInputStreamWithClassLoader.resolveClass.

                                Your questions should go to the people developing the jdk because I cannot answer them.

                                • 13. Re: JBoss AS 7.1.1.Final cannot getObject when sending java.lang.reflect.Proxy object
                                  clebert.suconic

                                  Sorry, I thought it was something you came up with.