glassfish
  1. glassfish
  2. GLASSFISH-12599

Injected Session Bean not serializable when it should be

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 3.1
    • Fix Version/s: 3.1_ms07
    • Component/s: cdi
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      12,599
    • Status Whiteboard:
      Hide

      weld-int-required

      Show
      weld-int-required

      Description

      I have a stateless session bean Foo (no-interface local view) which implements
      Serializable.

      When I inject this bean into a client class FooClient, in one of the following ways,

      @Inject
      private Foo foo;

      or

      @EJB
      private Foo foo;

      the injected member foo fails to serialize and deserialize correctly.

      I tested this using writeObject(foo) to a stream followed by readObject(...)
      from that stream.

      In the first case (@Inject), I get a null pointer exception when calling any
      method on the object returned by readObject().

      In the second case (@EJB), writeObject(foo) fails because
      com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate is not serializable.

      In the first case, the injected instance is a javaassist proxy wrapping a
      Glassfish proxy wrapping the Foo implementation. The javasssist proxy appears to
      be broken as reported in https://jira.jboss.org/browse/JASSIST-97.

      After patching the weld-osgi-bundle.jar with javassist-3.12.1.GA which fixes the
      bug, I ran into the same problem with EJBLocalObjectInvocationHandlerDelegate as
      in the second case.

      To sum up:
      1) Glassfish needs to ensure that any proxy it generates for a serializable EJB
      is also serializable.

      2) Weld needs to be upgraded to a newer version containing the Javassist bugfix.

        Activity

        Harald Wellmann created issue -
        Hide
        Sivakumar Thyagarajan added a comment -

        As part of Weld 1.1, there is work going in the Weld SPI around better handling
        of serialization of dynamically created client proxies and we are handling this
        as part of GF3.1.

        Is FooClient a Java EE application client or a Servlet/EJB/ManagedBean where the
        injection is being done? Could you explain the use-case on why you explicitly
        serialize the injected bean? Could you please share the application (client) and
        the NPE stack-trace?

        Show
        Sivakumar Thyagarajan added a comment - As part of Weld 1.1, there is work going in the Weld SPI around better handling of serialization of dynamically created client proxies and we are handling this as part of GF3.1. Is FooClient a Java EE application client or a Servlet/EJB/ManagedBean where the injection is being done? Could you explain the use-case on why you explicitly serialize the injected bean? Could you please share the application (client) and the NPE stack-trace?
        Hide
        Harald Wellmann added a comment -

        My application uses Wicket for the web UI, and Wicket serializes each page to
        the page store at the end of the HTTP request.

        Session beans get injected into my Wicket components for communicating with the
        backend.

        As I said, it is completely trivial to reproduce the problem construct in a
        simple test case using writeObject() on a HelloWorld SLSB, and this is
        absolutely independent of Wicket.

        This test also fails when using @EJB à la Java EE 5 instead of @Inject, so I
        would think that Weld does not enter the scene, and this part of the problem is
        entirely on the Glassfish side - assuming that
        com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate is within the
        Glassfish domain and not third-party code.

        Show
        Harald Wellmann added a comment - My application uses Wicket for the web UI, and Wicket serializes each page to the page store at the end of the HTTP request. Session beans get injected into my Wicket components for communicating with the backend. As I said, it is completely trivial to reproduce the problem construct in a simple test case using writeObject() on a HelloWorld SLSB, and this is absolutely independent of Wicket. This test also fails when using @EJB à la Java EE 5 instead of @Inject, so I would think that Weld does not enter the scene, and this part of the problem is entirely on the Glassfish side - assuming that com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate is within the Glassfish domain and not third-party code.
        Hide
        Harald Wellmann added a comment -

        My application uses Wicket for the web UI, and Wicket serializes each page to
        the page store at the end of the HTTP request.

        Session beans get injected into my Wicket components for communicating with the
        backend.

        As I said, it is completely trivial to reproduce the problem in a simple test
        case using writeObject() on a HelloWorld SLSB, and this is absolutely
        independent of Wicket.

        This test also fails when using @EJB à la Java EE 5 instead of @Inject, so I
        would think that and this part of the problem has nothing to do with Weld and is
        entirely on the Glassfish side - assuming that
        com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate is within the
        Glassfish domain and not third-party code.

        Show
        Harald Wellmann added a comment - My application uses Wicket for the web UI, and Wicket serializes each page to the page store at the end of the HTTP request. Session beans get injected into my Wicket components for communicating with the backend. As I said, it is completely trivial to reproduce the problem in a simple test case using writeObject() on a HelloWorld SLSB, and this is absolutely independent of Wicket. This test also fails when using @EJB à la Java EE 5 instead of @Inject, so I would think that and this part of the problem has nothing to do with Weld and is entirely on the Glassfish side - assuming that com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate is within the Glassfish domain and not third-party code.
        Hide
        Mahesh Kannan added a comment -

        Assigning this to Marina.

        Marina: Check with Linda if Local EJB references have to be Serializable

        Show
        Mahesh Kannan added a comment - Assigning this to Marina. Marina: Check with Linda if Local EJB references have to be Serializable
        Hide
        marina vatkina added a comment - - edited

        Seems like a CD issue: neither the CDI spec nor the EJB spec imposes
        requirements that proxies be serializable. Latest Weld expects them to be
        "passivateable". Older versions of weld maybe required it to be serializable,
        but weld 1.1 doesn't.

        Show
        marina vatkina added a comment - - edited Seems like a CD issue: neither the CDI spec nor the EJB spec imposes requirements that proxies be serializable. Latest Weld expects them to be "passivateable". Older versions of weld maybe required it to be serializable, but weld 1.1 doesn't.
        Hide
        Harald Wellmann added a comment -

        Just to make the point clearer: The question is not whether EJB or CDI proxies
        should be serializable IN GENERAL.

        But when a user-defined class Foo implements Serializable, any proxy to Foo must
        satisfy the contract of the original class Foo, so the proxy should be
        serializable too.

        Show
        Harald Wellmann added a comment - Just to make the point clearer: The question is not whether EJB or CDI proxies should be serializable IN GENERAL. But when a user-defined class Foo implements Serializable, any proxy to Foo must satisfy the contract of the original class Foo, so the proxy should be serializable too.
        Hide
        marina vatkina added a comment -

        Neither spec require ANY proxies to be serializable, whether the bean class
        implements it or not. So even if Foo implements Serializable, it's proxy is not
        required to do so.

        Show
        marina vatkina added a comment - Neither spec require ANY proxies to be serializable, whether the bean class implements it or not. So even if Foo implements Serializable, it's proxy is not required to do so.
        Hide
        Sivakumar Thyagarajan added a comment -

        The weld proxy is serializable and for classes that implement serializable its
        weld proxy must be serializable too. It appears that the weld de-serializable
        should be fixed with an upgrade of javassist. Weld 1.1 trunk nows uses 3.13.0-GA
        and once we have an integration of Weld 1.1.BETA2 with this, this issue should
        be fixed. I will re-check this scenario after the integration and close this
        issue for the @Inject part.

        Show
        Sivakumar Thyagarajan added a comment - The weld proxy is serializable and for classes that implement serializable its weld proxy must be serializable too. It appears that the weld de-serializable should be fixed with an upgrade of javassist. Weld 1.1 trunk nows uses 3.13.0-GA and once we have an integration of Weld 1.1.BETA2 with this, this issue should be fixed. I will re-check this scenario after the integration and close this issue for the @Inject part.
        Hide
        Sivakumar Thyagarajan added a comment -

        Marking as weld-int-required

        Show
        Sivakumar Thyagarajan added a comment - Marking as weld-int-required
        Hide
        Sivakumar Thyagarajan added a comment -

        Since Weld 1.1.BETA2 with the latest javassist release is integrated and a test-
        case [1] that tries to reproduce this behaviour passes, I am closing this issue.

        [1] https://svn.dev.java.net/svn/glassfish-svn/trunk/v2/appserv-
        tests/devtests/cdi/javaee-integration/no-interface-local-view-proxy-serializable

        Show
        Sivakumar Thyagarajan added a comment - Since Weld 1.1.BETA2 with the latest javassist release is integrated and a test- case [1] that tries to reproduce this behaviour passes, I am closing this issue. [1] https://svn.dev.java.net/svn/glassfish-svn/trunk/v2/appserv- tests/devtests/cdi/javaee-integration/no-interface-local-view-proxy-serializable
        kenaiadmin made changes -
        Field Original Value New Value
        issue.field.bugzillaimportkey 12599 44203
        Hide
        buddypine added a comment -

        There is an error in the tests, the SLSB is actually marked as @Stateful - but the test still passes when changed to @Stateless.

        However if I directly inject the SLSB into the servlet then try to serialize the injected proxy it fails with a NotSerializableException.
        Should the injected SLSB proxy not be serializable?

        @WebServlet(name = "mytest", urlPatterns = { "/myurl" })
        public class NoInterfaceProxySerializableEJBTestServlet extends HttpServlet {
        
            @Inject
            HelloNoInterfaceLocalViewSlessEJB helloNoInterfaceLocalViewSlessEJB;
        .. 
        
        [#|2011-11-24T08:45:26.535+0100|SEVERE|glassfish3.1.1|
        javax.enterprise.system.std.com.sun.enterprise.server.logging
        |_ThreadID=22;_ThreadName=Thread-6;|
        java.io.NotSerializableException: test.ejb.__EJB31_Generated__HelloNoInterfaceLocalViewSlessEJB__Intf____Bean__
        
        Show
        buddypine added a comment - There is an error in the tests, the SLSB is actually marked as @Stateful - but the test still passes when changed to @Stateless. However if I directly inject the SLSB into the servlet then try to serialize the injected proxy it fails with a NotSerializableException. Should the injected SLSB proxy not be serializable? @WebServlet(name = "mytest" , urlPatterns = { "/myurl" }) public class NoInterfaceProxySerializableEJBTestServlet extends HttpServlet { @Inject HelloNoInterfaceLocalViewSlessEJB helloNoInterfaceLocalViewSlessEJB; .. [#|2011-11-24T08:45:26.535+0100|SEVERE|glassfish3.1.1| javax.enterprise.system.std.com.sun.enterprise.server.logging |_ThreadID=22;_ThreadName= Thread -6;| java.io.NotSerializableException: test.ejb.__EJB31_Generated__HelloNoInterfaceLocalViewSlessEJB__Intf____Bean__
        Hide
        marina vatkina added a comment -

        Do you have beans.xml in the your module? If not, local EJB reference is not serializable without CDI being enabled.

        Show
        marina vatkina added a comment - Do you have beans.xml in the your module? If not, local EJB reference is not serializable without CDI being enabled.
        Show
        buddypine added a comment - Yes I do. I'm simply modifying the Glassfish tests from here - http://java.net/projects/glassfish/sources/svn/show/trunk/v2/appserv-tests/devtests/cdi/javaee-integration/no-interface-local-view-proxy-serializable .

          People

          • Assignee:
            Sivakumar Thyagarajan
            Reporter:
            Harald Wellmann
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: