1 2 Previous Next 18 Replies Latest reply on Mar 8, 2006 4:23 PM by clebert.suconic

    Hibernate Proxy possible fix

    johnv/dpol

      Hi Clebert

      I have been taking a look at the JBoss-Serialization code. It has currently problems with the HibernateProxy class. (saw there is no fix for it in the forums). I traced the error a little deeper and traced it to the red lines. I am not sure what should be allowed or not, but definatly the recursion there is not correct.

      Hopes it is of any use. And you are able to make a fix as author of the code. For now we will look in trying to get the CGLIB code removed from the objects/entitys, so it does not cause any errors in the first Place.

      Greets and keep the good work up,

      John van der Pol
      WPG

      /*
      * JBoss, Home of Professional Open Source
      *
      * Distributable under LGPL license.
      * See terms of license at gnu.org.
      */

      package org.jboss.serial.classmetamodel;

      import java.io.Externalizable;
      import java.io.Serializable;
      import java.lang.reflect.Constructor;

      import sun.reflect.ReflectionFactory;
      import org.jboss.logging.Logger;

      /**
      * This constructor manager requires sun package present.
      * If the class is not present, we will not be able to use this constructor manager
      * $Id: SunConstructorManager.java,v 1.7 2005/09/21 20:40:02 csuconic Exp $
      * @author Clebert Suconic
      */
      public class SunConstructorManager extends ConstructorManager
      {
      protected static final Logger log = Logger.getLogger(SunConstructorManager.class);
      static boolean supported=true;

      static
      {
      try
      {
      reflectionFactory = ReflectionFactory.getReflectionFactory();
      }
      catch (Throwable e)
      {
      log.warn(e.getMessage(),e);
      supported=false;
      }
      }

      static ReflectionFactory reflectionFactory;

      /* (non-Javadoc)
      * @see org.jboss.serial.classmetamodel.ConstructorManager#getConstructor(java.lang.Class)
      */
      public Constructor getConstructor(Class clazz) throws SecurityException, NoSuchMethodException
      {
      if (!Serializable.class.isAssignableFrom(clazz))
      {
      Constructor constr = clazz.getDeclaredConstructor(new Class[]{});
      constr.setAccessible(true);
      return constr;
      }
      else
      if (Externalizable.class.isAssignableFrom(clazz))
      {
      return clazz.getConstructor(new Class[]{});
      }
      else
      {
      Class currentClass = clazz;
      while (Serializable.class.isAssignableFrom(currentClass))
      -> should be something like while ( currentClass!=null && Serializable.class.isAssignableFrom(currentClass))
      I am not sure what you try to get here ??? the top/first class that is not assignable ?
      {//recursive that ends in NULL
      currentClass = currentClass.getSuperclass();
      }

      Constructor constr = currentClass.getDeclaredConstructor(new Class[]{});
      constr.setAccessible(true);

      // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6220682
      Constructor newConstructor = reflectionFactory.newConstructorForSerialization(clazz,constr);

      return newConstructor;
      }
      }
      /* (non-Javadoc)
      * @see org.jboss.serial.classmetamodel.ConstructorManager#isSupported()
      */
      public boolean isSupported()
      {
      return supported;
      }
      }

        • 1. Re: Hibernate Proxy possible fix
          johnv/dpol

          Clebert Suconic wrote:

          I made a fix into JBossSerialization, although JBossSerialization is not released yet.

          I need release for JBossSerialization to fix that.

          Can you download jboss-serialization from CVS, build it, and let me know if it fixes the problem?

          I will have release next week. If this doesn't fix your problem, please let me know.

          • 2. Re: Hibernate Proxy possible fix
            johnv/dpol

            It will not.
            Maybe if you include the next code it will -> another error I found, after the first fix
            (you should test your test conditions before using them)
            it is in ClassMetamodelFactory

            private static void lookupInternalMethods(Class clazz,ClassMetaData metaclass)
            {
            try
            {
            Method method = clazz.getDeclaredMethod("readResolve",new Class[]{});
            method.setAccessible(true);
            metaclass.setReadResolveMethod(method);
            }
            catch (Exception ignored)
            {
            }

            Class currentClass = clazz;
            while (( currentClass!=null) &&(Serializable.class.isAssignableFrom(currentClass)))
            {
            try
            {
            Method method = currentClass.getDeclaredMethod("readObject",new Class[]{ObjectInputStream.class});
            method.setAccessible(true);
            metaclass.setPrivateMethodRead(method);

            method = currentClass.getDeclaredMethod("writeObject",new Class[]{ObjectOutputStream.class});
            method.setAccessible(true);
            metaclass.setPrivateMethodWrite(method);
            break;
            }
            catch (Exception ignored)
            {
            }
            currentClass = currentClass.getSuperclass();
            }
            }

            The other foix works partialy, it does not throw and exception on null pointer anymore.
            But now the HibernateProxy has no empty constructor.
            This somehow you are expoecting as you filter the exception out and put the constructor on null

            anyway then you hit the above error in fieldsExplode

            Anyway i will have hibernate working for tomorrow
            so maybe some more fixes will folow.

            Greets John

            • 3. Re: Hibernate Proxy possible fix
              johnv/dpol

              Clebert Suconic wrote:

              I will write a testcase for HibernateProxy, and use this fix.


              Clebert

              • 4. Re: Hibernate Proxy possible fix
                johnv/dpol

                Anyway the fix works, now deserialization breaks :(

                Somehow the CGLIBLazyInitializer can not be initialized. I think it misses the empty constructor.
                As this issue is blocking a delivery of a software of us i have to shift my attention now to export cglib removed code.
                I will write a code now that will just strip all cglib code (passing the real objects)

                maybe later I have time to fix the deserialization.

                greets John

                12:16:18,906 ERROR [STDERR] Caused by: org.jboss.serial.exception.SerializationException
                12:16:18,906 ERROR [STDERR] at org.jboss.serial.persister.PrivateWritePersister.readData(PrivateWritePersister.java:119)
                12:16:18,906 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.readObjectDescriptionFromStreaming(ObjectDescriptorFactory.java:141)
                12:16:18,906 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.objectFromDescription(ObjectDescriptorFactory.java:40)
                12:16:18,906 ERROR [STDERR] at org.jboss.serial.objectmetamodel.DataContainer$DataContainerInput.readObject(DataContainer.java:644)
                12:16:18,921 ERROR [STDERR] at org.jboss.serial.io.JBossObjectInputStream.readObjectOverride(JBossObjectInputStream.java:70)
                12:16:18,921 ERROR [STDERR] at java.io.ObjectInputStream.readObject(ObjectInputStream.java:333)
                12:16:18,921 ERROR [STDERR] at org.jboss.serial.io.MarshalledObject.get(MarshalledObject.java:68)
                12:16:18,921 ERROR [STDERR] at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:61)
                12:16:18,921 ERROR [STDERR] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:98)
                12:16:18,921 ERROR [STDERR] at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:102)
                12:16:18,937 ERROR [STDERR] ... 42 more
                12:16:18,937 ERROR [STDERR] Caused by: java.lang.reflect.InvocationTargetException
                12:16:18,937 ERROR [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                12:16:18,937 ERROR [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                12:16:18,937 ERROR [STDERR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                12:16:18,937 ERROR [STDERR] at java.lang.reflect.Method.invoke(Method.java:585)
                12:16:18,937 ERROR [STDERR] at org.jboss.serial.persister.PrivateWritePersister.readData(PrivateWritePersister.java:109)
                12:16:18,953 ERROR [STDERR] ... 51 more
                12:16:18,953 ERROR [STDERR] Caused by: org.jboss.serial.exception.SerializationException: Could not create instance of org.hibernate.proxy.CGLIBLazyInitializer - org.hibernate.proxy.CGLIBLazyInitializer
                12:16:18,953 ERROR [STDERR] at org.jboss.serial.classmetamodel.ClassMetaData.newInstance(ClassMetaData.java:223)
                12:16:18,953 ERROR [STDERR] at org.jboss.serial.persister.RegularObjectPersister.readData(RegularObjectPersister.java:134)
                12:16:18,953 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.readObjectDescriptionFromStreaming(ObjectDescriptorFactory.java:141)
                12:16:18,968 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.objectFromDescription(ObjectDescriptorFactory.java:40)
                12:16:18,968 ERROR [STDERR] at org.jboss.serial.objectmetamodel.DataContainer$DataContainerInput.readObject(DataContainer.java:644)
                12:16:18,968 ERROR [STDERR] at org.jboss.serial.persister.RegularObjectPersister.defaultRead(RegularObjectPersister.java:189)
                12:16:18,968 ERROR [STDERR] at org.jboss.serial.persister.RegularObjectPersister.readData(RegularObjectPersister.java:136)
                12:16:18,968 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.readObjectDescriptionFromStreaming(ObjectDescriptorFactory.java:141)
                12:16:18,968 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.objectFromDescription(ObjectDescriptorFactory.java:40)
                12:16:18,984 ERROR [STDERR] at org.jboss.serial.objectmetamodel.DataContainer$DataContainerInput.readObject(DataContainer.java:644)
                12:16:18,984 ERROR [STDERR] at org.jboss.serial.persister.ArrayPersister.readObjectArray(ArrayPersister.java:174)
                12:16:18,984 ERROR [STDERR] at org.jboss.serial.persister.ArrayPersister.readData(ArrayPersister.java:150)
                12:16:18,984 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.readObjectDescriptionFromStreaming(ObjectDescriptorFactory.java:141)
                12:16:18,984 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.objectFromDescription(ObjectDescriptorFactory.java:40)
                12:16:19,015 ERROR [STDERR] at org.jboss.serial.objectmetamodel.DataContainer$DataContainerInput.readObject(DataContainer.java:644)
                12:16:19,031 ERROR [STDERR] at org.jboss.serial.persister.RegularObjectPersister.defaultRead(RegularObjectPersister.java:189)
                12:16:19,031 ERROR [STDERR] at org.jboss.serial.persister.RegularObjectPersister.readData(RegularObjectPersister.java:136)
                12:16:19,031 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.readObjectDescriptionFromStreaming(ObjectDescriptorFactory.java:141)
                12:16:19,031 ERROR [STDERR] at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.objectFromDescription(ObjectDescriptorFactory.java:40)
                12:16:19,046 ERROR [STDERR] at org.jboss.serial.objectmetamodel.DataContainer$DataContainerInput.readObject(DataContainer.java:644)
                12:16:19,046 ERROR [STDERR] at org.jboss.serial.persister.ObjectInputStreamProxy.readObjectOverride(ObjectInputStreamProxy.java:50)
                12:16:19,046 ERROR [STDERR] at java.io.ObjectInputStream.readObject(ObjectInputStream.java:333)
                12:16:19,046 ERROR [STDERR] at java.util.Hashtable.readObject(Hashtable.java:848)
                12:16:19,078 ERROR [STDERR] ... 56 more
                12:16:19,078 ERROR [STDERR] Caused by: java.lang.InstantiationException: org.hibernate.proxy.CGLIBLazyInitializer
                12:16:19,078 ERROR [STDERR] at java.lang.Class.newInstance0(Class.java:335)
                12:16:19,093 ERROR [STDERR] at java.lang.Class.newInstance(Class.java:303)
                12:16:19,093 ERROR [STDERR] at org.jboss.serial.classmetamodel.ClassMetaData.newInstance(ClassMetaData.java:215)
                12:16:19,093 ERROR [STDERR] ... 78 more
                12:16:20,937 INFO [STDOUT] java.lang.reflect.UndeclaredThrowableException

                • 5. Re: Hibernate Proxy possible fix
                  johnv/dpol

                  Clebert Suconic wrote:

                  How are you creating the proxy?
                  I need to create a testcase for that.

                  • 6. Re: Hibernate Proxy possible fix
                    johnv/dpol

                    Actually quit easy, there are some postings related to it on the forum already.
                    create in the 404 version an entity and try to export that entity (make a remote call that retrieves the entity)

                    you make an entity to define a class on a table and define it as an Entity (Hibernate/annotation -> this adds the cglib wrapper)
                    it seems it goes wrong when data is lazy loaded only, but i think it goes always wrong
                    if you need lazy loaded data/entities, just add a relation to another table or the same table. (lazy loading is default behavior in hibernate)

                    Anyway if you need more help just ask me.

                    I think it has escaped detection as most tests are done with seam, which uses local interfaces as far as i understood.

                    We however need to export data to a swing client.

                    • 7. Re: Hibernate Proxy possible fix
                      johnv/dpol

                      Clebert Suconic wrote:


                      I?m trying to use HibernateProxyFactory to create a Proxy.
                      I need to isolate the problem in a low level, without all the Hibernate Session and Database framework. I thought you had isolated it that way. I guess I will be able to create the proxy using the API directly.

                      Clebert

                      • 8. Re: Hibernate Proxy possible fix
                        johnv/dpol

                        Hi Clebert

                        I understand that you want to isolate it in a low level.
                        Sadly enough that was not possible.
                        I have some 100 levels of debugging to reach the error (several levels of writeObjects).

                        A simple way to make the error I think is to make a class directly derived from serializable and have it not have a base constructor. Maybe it only goes wrong if these classes are in a structure (Collection/Map)
                        It mimics what went wrong with the HibernateProxy.

                        Anyway after the fixes I sent you, it does work in serialization and as you can review/see they were errors and the fix is clean.

                        Only deserialization does not work yet and actualy deserialization of CGLIBLazyInitializer not HibernateProxy

                        I think now is the time for the guys from the Hibernate department and especialy the proxy/cglib guys to fix their part

                        CGLIBLazyInitializer deserialization.

                        They will also more easily create a working test case on their level of concern

                        Greets John

                        • 9. Re: Hibernate Proxy possible fix
                          johnv/dpol

                          Clebert Suconic wrote:

                          Don?t think the constructor is the problem.

                          I?m testing classes without default constructor on jboss-serialization project.

                          Look at org.jboss.serial.data.TestParent for example.

                          I?m still working on the problem.

                          • 10. Re: Hibernate Proxy possible fix
                            johnv/dpol

                            Clebert Suconic wrote:

                            Replicated the problem reliably:


                            java.lang.NullPointerException

                            at java.lang.Class.isAssignableFrom(Native Method)
                            at org.jboss.serial.classmetamodel.SunConstructorManager.getConstructor(SunConstructorManager.java:66)
                            at org.jboss.serial.classmetamodel.ClassMetamodelFactory.findConstructor(ClassMetamodelFactory.java:288)
                            at org.jboss.serial.classmetamodel.ClassMetamodelFactory.getClassMetaData(ClassMetamodelFactory.java:257)
                            at org.jboss.serial.persister.ClassReferencePersister.writeData(ClassReferencePersister.java:44)
                            at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.describeObject(ObjectDescriptorFactory.java:117)
                            at org.jboss.serial.objectmetamodel.DataContainer$DataContainerOutput.writeObject(DataContainer.java:266)
                            at org.jboss.serial.persister.ArrayPersister.saveObjectArray(ArrayPersister.java:96)
                            at org.jboss.serial.persister.ArrayPersister.writeData(ArrayPersister.java:87)
                            at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.describeObject(ObjectDescriptorFactory.java:117)
                            at org.jboss.serial.objectmetamodel.DataContainer$DataContainerOutput.writeObject(DataContainer.java:266)
                            at org.jboss.serial.persister.RegularObjectPersister.defaultWrite(RegularObjectPersister.java:81)FieldsManager in use = org.jboss.serial.classmetamodel.ReflectionFieldsManager

                            • 11. Re: Hibernate Proxy possible fix
                              johnv/dpol

                              I saw you are testing against that one. (missing constructor)

                              The real problem is a serializable class without a super class that is not

                              like class serializetest extends Serializable
                              {
                              }

                              This one is serializable but when you look for the top in the code it breaks as it will end up in null.
                              Your test is too optimistic (always test on null).

                              Then you do test in your catch in a higher level on a missing constructor implementation.
                              But it does not catch a null pounter exception. -> which then is catched on a wrong level (too late)

                              while(Serializable.class.isAssignableFrom(currentClass) )
                              {
                              currentClass = currentClass.getSuperclass();
                              }

                              Probably the error apears in more parts of your code. I would advice a check on ".getSuperclass()" in loops

                              Hope this is enough info for test cases

                              greets John

                              • 12. Re: Hibernate Proxy possible fix
                                johnv/dpol

                                Clebert Suconic wrote:

                                That?s not the problem.
                                The problem is on ArrayPersister for classes..
                                I?m looking for the metadata on classes. Classes don?t have a constructor.
                                I?m already fixing the problem? need 20 more minutes.

                                Clebert

                                • 13. Re: Hibernate Proxy possible fix
                                  johnv/dpol

                                  As it was happening with only one entity I took a deeper look. The entity had four references to other objects (contract, contractparty, contractrole and context).

                                  The contract linked it in a strange way. In the constructor of the
                                  contractparty role it set the references, but then called an
                                  AddContractPartyRole to each different Object. This is not needed as hibernate adds it to the lists. These additions then checked if the element was not yet present and if not, added it.

                                  Well after removing this strange and unneeded code it worked again.

                                  I also took a deeper look on the code, strangely it reports that the field name correctly and then it loads the bytes. I assume the object content is saved as an index/unique value which loads / constructs the object from a cache (map). I think here it goes wrong.

                                  Hope my info is useful and hope you can fix it soon, as I think there are more people making some mistakes in the hibernate use. And when they will get this deserialization issue they will be totally lost.

                                  Anyway as far as it looks now my code works.


                                  Greets John van der Pol

                                  • 14. Re: Hibernate Proxy possible fix
                                    johnv/dpol

                                    Clebert Suconic wrote:


                                    John...

                                    I really think you should use forums :-)

                                    Don't you want to register your discoveries?

                                    And... can you create a testcase for this and send me? It would be really great.

                                    I mean, I will try replicate what you described me, but if you can reproduce it in a testcase, that's great.


                                    Clebert

                                    1 2 Previous Next