13 Replies Latest reply on Jun 23, 2006 11:50 AM by Clebert Suconic

    Serialize a Spring Bean Factory/Context

    Matthew Smith Newbie

      I'm attempting to serialize the state of a fairly complex Spring Bean Context. I've been unsuccessful so far. I've created a very basic test case which fails, and posted a JIRA issue for it here:

      http://jira.jboss.com/jira/browse/JBSER-78

      Regards,
      Matthew Smith


        • 1. Re: Serialize a Spring Bean Factory/Context
          Matthew Smith Newbie

          p.s. - the exception is this:

          java.lang.ClassCastException: java.lang.Class
          at org.jboss.serial.persister.ArrayPersister.saveObjectArray(ArrayPersister.java:106)
          at org.jboss.serial.persister.ArrayPersister.writeData(ArrayPersister.java:101)
          at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.describeObject(ObjectDescriptorFactory.java:275)
          at org.jboss.serial.objectmetamodel.DataContainer$DataContainerDirectOutput.writeObject(DataContainer.java:202)
          at org.jboss.serial.persister.ObjectOutputStreamProxy.writeObjectOverride(ObjectOutputStreamProxy.java:60)
          at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:305)

          • 2. Re: Serialize a Spring Bean Factory/Context
            Clebert Suconic Master

            Do you think this might be caused by http://jira.jboss.com/jira/browse/JBSER-77?

            I validated the JIRA with a testcase and JBSER-77 is a bug indeed. Easily reproduceble

            I'm just wondering if this might be the same bug or not.

            • 3. Re: Serialize a Spring Bean Factory/Context
              Matthew Smith Newbie

              I took a look at JBSER-77 and threw a breakpoint on the line that Oleg mentioned:

              persister.writeData(metaData, cache.getOutput(), obj, cache.getSubstitution());

              persister is of course an Array Persister (per the stack trace I posted before),

              and

              obj is a java.lang.Class representing org.springframework.core.io.Resource[]

              . . . so . . . yes I think this is likely to be the same bug.

              I'll mark JBSER-78 as a dupe of JBSER-77. As soon as you have a new release I'll test the fix with my particular case. That way you don't need to introduce a test case with a dependency on an external library....

              Regards,
              Matthew Smith

              • 4. Re: Serialize a Spring Bean Factory/Context
                Clebert Suconic Master

                It's fixed on CVS now.
                I will attach a new JAR on JBSER-78, so you could validate it.

                • 5. Re: Serialize a Spring Bean Factory/Context
                  Matthew Smith Newbie

                  Clebert,

                  I tested the jar you posted to the JIRA record, and it appears to have fixed the problem which happens during serialization. Now I am seeing the following exception during deserialization:

                  Caused by: org.jboss.serial.exception.SerializationException: Could not create instance of org.springframework.context.support.ClassPathXmlApplicationContext - org.springframework.context.support.ClassPathXmlApplicationContext
                  at org.jboss.serial.classmetamodel.ClassMetaData.newInstance(ClassMetaData.java:342)
                  at org.jboss.serial.persister.RegularObjectPersister.readData(RegularObjectPersister.java:239)
                  at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.readObjectDescriptionFromStreaming(ObjectDescriptorFactory.java:411)
                  at org.jboss.serial.objectmetamodel.ObjectDescriptorFactory.objectFromDescription(ObjectDescriptorFactory.java:81)
                  at org.jboss.serial.objectmetamodel.DataContainer$DataContainerDirectInput.readObject(DataContainer.java:634)
                  at org.jboss.serial.io.JBossObjectInputStream.readObjectOverride(JBossObjectInputStream.java:163)
                  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
                  at SerializeSpringTest.deserializeObject(SerializeSpringTest.java:59)
                  ... 17 more
                  Caused by: java.lang.InstantiationException: org.springframework.context.support.ClassPathXmlApplicationContext
                  at java.lang.Class.newInstance3(Class.java:346)
                  at java.lang.Class.newInstance(Class.java:305)
                  at org.jboss.serial.classmetamodel.ClassMetaData.newInstance(ClassMetaData.java:334)
                  ... 24 more


                  Here's a snippet from the relevant VM source code I could find for the line that throws the InstantationException :

                  // NOTE: the following code may not be strictly correct under
                   // the current Java memory model.
                   /*ibm@39253*/
                   Constructor tmpConstructor = cachedConstructor;
                   Class caller = newInstanceCallerCache;
                  
                   // Constructor lookup
                   if (tmpConstructor == null) { /*ibm@39253*/
                   if (this == Class.class) {
                   throw new IllegalAccessException(
                   "Can not call newInstance() on the Class for java.lang.Class"
                   );
                   }
                   try {
                   final Constructor c =
                   getConstructor1(new Class[] {}, Member.DECLARED); /*ibm@59791*/
                   // Disable accessibility checks on the constructor
                   // since we have to do the security check here anyway
                   // (the stack depth is wrong for the Constructor's
                   // security check to work)
                   java.security.AccessController.doPrivileged
                   (new java.security.PrivilegedAction() {
                   public Object run() {
                   c.setAccessible(true);
                   return null;
                   }
                   });
                   tmpConstructor = c; /*ibm@39253*/
                   } catch (NoSuchMethodException e) {
                   throw new InstantiationException(getName());
                   }



                  • 6. Re: Serialize a Spring Bean Factory/Context
                    Clebert Suconic Master

                    From what I could see here:

                    http://www.springframework.org/docs/api/org/springframework/context/support/ClassPathXmlApplicationContext.html

                    ClassPahXMLApplicationContext is not Serializable.

                    And it's a requirement at this point, that a non-serializable-class should have a default constructor. (even a private one would be fine).

                    I know I should have this documented. (I need to finish and upload docs), but this is a requirement for now.

                    Requiring a default constructor on non-serializable was just a choice. If you have an argument to change that we could consider that (if nobody disagrees).

                    Anyway, there is another factor we should consider about NonSerializable classes. Right now the only limit I imposed on NonSerializables was the default constructor. If we stop requiring that we will probably need a library of transient by default.

                    Like, it doesn't make any sense to Serialize a FileObjecOutputStream. If we enable that through JBossSerialization we could create an invalid state. (I'm even concerned about generating GPF situations since part of these streams is native code). That would apply to other Classes as well.


                    Clebert

                    • 7. Re: Serialize a Spring Bean Factory/Context
                      Clebert Suconic Master

                      Do you really need to serialize that ClassPathXML?

                      Maybe you could set it as transient. (as it's not serializable)

                      • 8. Re: Serialize a Spring Bean Factory/Context
                        Matthew Smith Newbie

                        Clebert,

                        It would be nice if I could serialize the spring stuff without having to go create my own custom versions of all those spring class (with default constructors added). If it's possible to serialize and deserialize the object without the default constructor, and even if that would not be desirable default behavior, would you consider adding an option to JBoss serialization that would use that behavior?

                        Regards,
                        Matthew Smith

                        • 9. Re: Serialize a Spring Bean Factory/Context
                          Clebert Suconic Master

                          Yes... I can do that...

                          I'm just afraid about serializing things that don't make sense.

                          For example, if you serialize a SimpleDateFormat, you could actually serialize it with JBossSerialization. But that will take 400k.

                          I could add a parameter with JBoss*Stream to use ghost constructors with non serializable classes.

                          • 10. Re: Serialize a Spring Bean Factory/Context
                            Matthew Smith Newbie

                            hmm... yes, unintentionally serializing a simpledateformat into 400k is definately a side effect I'd like to avoid.

                            What immediately comes to mind is inclusion/exclusion lists/wildcards.... however, I'm afraid a might be bloating your API for a special case. Are there any cases other than mine where it might be useful to enable the ghost constructors for either (a) for everything or (b) for some specific list/wildcard match of packages/classes..

                            Regards,
                            Matthew Smith

                            • 11. Re: Serialize a Spring Bean Factory/Context
                              Matthew Smith Newbie

                              Clebert,

                              Considering no one else has jumped in with a similar need yet, how about providing that global option, and then I'll worry about making all my simpledateformat's transient in my class hierarchy, or maybe forking jboss serialization to provide myself with a filtering mechanism.

                              Regards,
                              Matthew Smith

                              • 12. Re: Serialize a Spring Bean Factory/Context
                                Clebert Suconic Master

                                The only problem I'm facing on this is... The class metadata cache is static, so it would need a static option.

                                But I will find a way of doing this. (Maybe have an extra fields to the extra constructor).

                                • 13. Re: Serialize a Spring Bean Factory/Context
                                  Clebert Suconic Master

                                  http://jira.jboss.org/jira/browse/JBSER-81


                                  Usually I'm really fast on fixing bugs and implementing new features.

                                  But I wont have time next week to do this.

                                  I might try doing it before 5-Jul-06 (The due date I set on JIRA), but I can't promisse.

                                  If you want it sooner, I could help you doing that (showing where to change in the code), then you would be able to test yourself. You could provide a patch for this (or who knows... becoming a contributor ;-) )

                                  Clebert