7 Replies Latest reply on Mar 31, 2004 7:30 PM by afleet

    Problem with serialization of Stateful SB handle

    afleet Newbie

      Hi,
      I have a client app of a stateful session bean. The app serializes the
      component interface to a file, recreates it and uses it. (Code below).
      The output from the Session bean is a follows...

      15:14:17,421 INFO [STDOUT] HelloBeanEJB()
      15:14:17,421 INFO [STDOUT] setSessionContext
      15:14:17,421 INFO [STDOUT] ejbCreate
      15:14:27,531 INFO [STDOUT] HelloBeanEJB()
      15:14:27,531 INFO [STDOUT] setSessionContext

      The first 3 lines are prior to serialization. What confuses me here is when
      I deserialize the handle and use it I get the bean constructor &
      setSessionContext called... I had assumed the deserialized reference
      would be for the same bean...


      Client Code:

      InitialContext initial = new InitialContext(Properties);
      Object objref = initial.lookup("SessionTestBean");

      HelloBeanHome home =
      (HelloBeanHome)PortableRemoteObject.narrow(objref,
      HelloBeanHome.class);

      HelloBean hello = home.create();
      System.out.println(hello.sayHello());

      FileOutputStream out = new FileOutputStream("theObject");
      ObjectOutputStream s = new ObjectOutputStream(out);
      s.writeObject(hello.getHandle());
      s.flush();
      Thread.sleep(10000);

      FileInputStream in = new FileInputStream("theObject");
      ObjectInputStream si = new ObjectInputStream(in);
      Handle theHandle = (Handle)si.readObject();
      HelloBean hello1 = (HelloBean)theHandle.getEJBObject();;
      System.out.println(hello1.sayHello());


      Thanks,

      Andy

        • 1. Re: Problem with serialization of Stateful SB handle
          micke Novice

          Unfortunately there is no magic in the land of EJBs :)
          If you look at your serialized handle you can see that its just
          reference to your bean. When you execute getEJBObject() on the
          handle, you instruct the container to find the bean with the id in your handle. The log lines you get is home invocation locating your bean.

          • 2. Re: Problem with serialization of Stateful SB handle
            micke Novice

            Unfortunately there is no magic in the land of EJBs :)
            If you look at your serialized handle you can see that its just
            reference to your bean. When you execute getEJBObject() on the
            handle, you instruct the container to find the bean with the id in your handle. The log lines you get is home invocation locating your bean.

            • 3. Re: Problem with serialization of Stateful SB handle
              afleet Newbie

              Thanks,
              however I'm still confused!. The first 3 log lines are the initial create &
              invocation. However why is the constructor & setSessionContext called
              when I invoke through the serialized/unserialized handle?. If i'm invoking
              on the same bean I would not have expected this - simply an invocation
              of the business method,

              Andy

              • 4. Re: Problem with serialization of Stateful SB handle
                micke Novice

                How do you expect it to work? Using the handle is not the same thing as reusing your existing remote interface to call the bean.You have an id(Handle) of an EJB and want the remote interface for it(getEJBObject()). It’s a similar process as when you created the bean in the first place. First you need a JNDI lookup, then you need the container to find the bean for you and to set up its context. After that your bean is ready to be called through its remote interface.

                Remember, its not the bean you are serializing, just the reference.

                • 5. Re: Problem with serialization of Stateful SB handle
                  afleet Newbie

                  Hi Micke,
                  thanks for staying with me on this one!. When you ask how would I
                  expect it to work, I can only say I would expect the business method on
                  the _same_ session bean to be invoked after deserialization as before.
                  (Remember, I'm serializing the value from the remote interface
                  getHandle() method).

                  I did some further investigation and found a section in the EJB spec which
                  clarifies this. I've included it below.

                  I changed my session bean to output toString() on the constructor and
                  business method. Here's the output...

                  10:57:30,875 INFO [STDOUT] HelloBeanEJB() mybean.HelloBeanEJB@1e2fe5d

                  10:57:30,875 INFO [STDOUT] setSessionContext

                  10:57:30,875 INFO [STDOUT] ejbCreate

                  10:57:30,937 INFO [STDOUT] sayHello methodmybean.HelloBeanEJB@1e2fe5d

                  <At this point I serialize & descrialize the Handle and call getEJBObject() >

                  10:57:40,968 INFO [STDOUT] HelloBeanEJB() mybean.HelloBeanEJB@1f6f3dc

                  10:57:40,984 INFO [STDOUT] setSessionContext

                  <The invocation on the remote interface obtained from the
                  deserialized handle goes back the the original bean>

                  10:57:41,046 INFO [STDOUT] sayHello methodmybean.HelloBeanEJB@1e2fe5d

                  say Hello is the the businesss method. As you can see I still have a
                  spurious constructor & setSessionContext calls (this is when I deserialize
                  the remote interface) _however_ the sayHello() method is called on the
                  same bean after deserialization as before. It appears JBoss creates a
                  session bean that is not used...

                  I also called isIdentical(...) in the client on the before and after
                  serializated remote interface reference ... they are identical.

                  Thanks, for the discussion, the spec section (page 69 & 70, EJB 2.1) is
                  included below,

                  Andy

                  P.S. Is there a formal mechanism to register bugs if you do not have
                  a support contract?

                  <From the Spec>

                  A client creates a remote Cart session object, which provides a shopping
                  service, using a create method of the Cart’s remote home
                  interface. The client then uses this session object to fill the cart with items
                  and to purchase its contents.

                  Suppose that the end-user wishes to start the shopping session, suspend
                  the shopping session temporarily for a day or two, and later complete the
                  session. The client might implement this feature by getting the session
                  object’s handle, saving the serialized handle in persistent storage, and
                  using it later to reestablish access to the original Cart.

                  For the following example, we start by looking up the Cart’s remote home
                  interface in JNDI. We then use the remote home interface to create a
                  Cart session object and add a few items to it:

                  CartHome cartHome =
                  (CartHome)javax.rmi.PortableRemoteObject.narrow(
                  initialContext.lookup(...), CartHome.class);

                  Cart cart = cartHome.createLargeCart(...);

                  cart.addItem(66);

                  cart.addItem(22);

                  Next we decide to complete this shopping session at a later time so we
                  serialize a handle to this cart session object and store it in a file:

                  Handle cartHandle = cart.getHandle();
                  // serialize cartHandle, store in a file...

                  Finally we deserialize the handle at a later time, re-create the reference to
                  the cart session object, and purchase the contents of the shopping cart:

                  Handle cartHandle = ...; // deserialize from a file...

                  Cart cart = (Cart)javax.rmi.PortableRemoteObject.narrow(

                  cartHandle.getEJBObject(), Cart.class);

                  cart.purchase();

                  cart.remove();

                  • 7. Re: Problem with serialization of Stateful SB handle
                    afleet Newbie

                    Thanks Scott,
                    I've posted this as a bug, the test case demonstrates the issue and
                    I also commented that I get the following server warning after the client
                    runs;

                    13:25:25,765 WARN [AbstractInstanceCache] Unable to
                    passivate due to ctx lock, id=dshx0pi7-4

                    So even though the core issue is 'in discussion' I think it requires
                    a look into,

                    Andy