3 Replies Latest reply on Jul 21, 2010 10:44 AM by pmuir

    Serialization problem with CDI, EJB and Proxies

    hwellmann

      I'm using CDI to @Inject a stateless session bean Foo (no-interface local view) into a serializable bean Bar. Foo is Serializable, so I should be able to serialize and deserialize Bar without problems, but this does not work.


      (Actually, I'm not doing this manually: Bar is a Wicket component which gets (de-)serialized automatically when navigating from page to page, and there is a ComponentInstantiationListener taking care of injection on component construction, using InjectionTarget.inject(), much like in weld-wicket.)



      With Glassfish 3.01b21, I get the following exception


      java.lang.NullPointerException: null
      at javassist.util.proxy.RuntimeSupport$DefaultMethodHandler.invoke(RuntimeSupport.java:37) 
      at org.javassist.tmp.java.lang.Object_$$_javassist_224.fooMethod(Object_$$_javassist_224.java)
      



      Apparently, the javassist proxy for my Foo object does support serialization in principle, but it fails to (de)serialize the method handler.


      I searched the Weld and Javassist archives to see if this was a known problem, and I found this bug (https://jira.jboss.org/browse/JASSIST-97) which is reported to be fixed in javassist-3.12.0, which is newer than the version of Javassist bundled with the version of Weld used by Glassfish v3.0.1b21


      I unpacked the weld-osgi-bundle.jar, replaced the javassist classes by the ones from javassist-3.12.1.GA, repacked everything and launched my Glassfish instance with this modified bundle to see if this problem was solved.


      After this change, I got a different serialization problem:


      org.apache.wicket.util.io.SerializableChecker$WicketNotSerializableException: Unable to serialize class: com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate
      
      protected java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.h [class=com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate] <----- field that is not serializable
      



      Using @EJB instead of @Inject produces the same exception.


      So it seems, however hard I try to make my session bean serializable, Glassfish and/or Weld will always give me an unserializable proxy to it. Or in other words, CDI should be transparent, but is not, and I really have no clue how to get out of this situation...


      There is a Wicket extension javaee-inject (supporting Java EE 5 injections, but not CDI) which works with special serialization handlers, replacing a proxy by a reference on serialization and doing a lookup with that reference on deserialization.


      Sounds like this might solve the problem if Weld would handle EJB injections in a similar manner.


      Any other ideas....?


      Best regards,


      Harald


        • 1. Re: Serialization problem with CDI, EJB and Proxies
          andygibson.contact.andygibson.net

          I'm not sure if this is the answer since it seems like it is Wicket and not a CDI bean that is the problem, but :


          The current version of Weld in Glassfish is broken since it considers Stateless beans non-proxyable, and therefore they cannot be injected into beans with a stateful scope. Whether this is the problem or not, you might benefit from upgrading your version of Weld in Glassfish to 1.0.1 which I've documented and you can even download the weld OSGI package (you could create your own, but a more recent version wasn't working so great so I'm using an older version).



          • 2. Re: Serialization problem with CDI, EJB and Proxies
            hwellmann

            Andy, thanks for the tip, but this is not the solution. Glassfish 3.0.1b21 or higher already has Weld 1.0.1.SP3.


            The problem is not related to Wicket, it only surfaces in that context, because otherwise you probably wouldn't want to manually serialize an injected bean.


            However, it's easy to isolate this issue in a simple test case doing a round trip with writeObject()/readObject() on the injected proxy for a Stateless bean and then invoking a method on the final result.


            As far as I can tell, Weld needs to include the bugfix for JASSIST-97 which will make the Weld proxy serializable. Then we're still left with the next proxy in the chain not serializable, but that's a Glassfish issue.


            Regards,


            Harald

            • 3. Re: Serialization problem with CDI, EJB and Proxies
              pmuir

              Thanks for reporting the GlassFish issue.


              In the next release of Weld, we will upgrade Javassist.