5 Replies Latest reply on Sep 2, 2001 6:33 PM by lothar

    Passivation problem(again).....

    pwinstonr

      Maybe, I'll try to explain my problem a little bit more detailed. Hopefully, somebody could help me out here.
      I have a SFSB "PersonSFSB", it holds an object called "Person" as its attribute. This "Person" object internally holds another object called "Address" as its attribute. On the ejbCreate() method of "PersonSFSB" I instantiate the "Person" object. When the person object instantiates it also instanties the "Address" object.

      PersonSFSB.ejbCreate()->new Person()->new Address()

      When the "Address" object is instantiated, it uses the JBoss connection pool and hits the Oracle database to load its attributes. So, in effect there is no database connection done directly from the "PersonSFSB". The database hit occurs deep in the object hierarchy.

      new Address()->hit database->load Address attributes->close database

      The above scenario works fine except when JBoss tried to passivate "PersonSFSB". It throws me the following exception.

      java.rmi.ServerException: Could not passivate; nested exception is:
      java.io.NotSerializableException: org.jboss.pool.jdbc.xa.wrapper.XAClientConnection
      java.io.NotSerializableException: org.jboss.pool.jdbc.xa.wrapper.XAClientConnection
      at java.io.ObjectOutputStream.outputObject(ObjectOutputStream.java:1148)
      at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:366)
      at java.io.ObjectOutputStream.outputClassFields(ObjectOutputStream.java:1827)
      at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:480)

      I understand that all db connections need to be put back in the pool if connected from SFSB. But in my case, I'm not making a DB connection from my SFSB at all. All of it is occuring deep in the object hierarchy. I've also double checked that the DB Connections are closed properly after the work is done.
      Is there any checklist I could go through to get rid off this issue. Or could I be making an obvious mistake here. Please write in, any help will be truly appreciated.
      Thanks,
      Winston.

        • 1. Re: Passivation problem(again).....

          Closing the connection is not enough. When the reference to that connection is still in a bean instance field the bean can not be passivated because the Connection is not a serializable object - closed or not. U will have to mark the bean instance field in which u hold the reference to the connection as transient or assign a null to it.

          • 2. Re: Passivation problem(again).....
            pwinstonr

            Lothar,
            Thanks a lot for the reply. Declaring the variable "Person" as transient solved the problem, but caused other issues. Based on your suggestion can I assume the following things.

            1)SFSB needs to do the database hits directly from within. So that during ejbPassivate() we release the connection to the pool and ejbActivate() looksup the connection again.
            2)If SFSB holds any reference to an object(say A), where A might lookup the connection pool and release it temporarily from within(but doesnt hold a global reference to the connection), then A needs to be declared as transient.

            Are these above assumptions correct. Are these standards??? Anyway, since I declared my "Person" object as transient, the container did not write the "Person" object to the disk while passivating. But, when I sent a request to the SFSB after it passivated, it tries to do ejbActivate() and finds that "Person" object was not stored in the disk, so it throws a Null pointer exception. I definetly dont want to assign null to the object during ejbPassivate() cause that will nullify my state and would get nullpointerexceptions when ejbActivate() occurs. Below is the error.

            java.rmi.ServerException: Transaction rolled back; nested exception is:
            java.lang.NullPointerException
            java.lang.NullPointerException
            at com.intelitix.shopping.PersonSessionBean.readyForCheckout(CartSessionBean.java:160)
            at java.lang.reflect.Method.invoke(Native Method)
            at org.jboss.ejb.StatefulSessionContainer$ContainerInterceptor.invoke(StatefulSessionContainer.java:650)
            at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:128)
            at org.jboss.ejb.plugins.TxInterceptorBMT.invoke(TxInterceptorBMT.java:276)
            at org.jboss.ejb.plugins.StatefulSessionInstanceInterceptor.invoke(StatefulSessionInstanceInterceptor.java:209)
            at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
            at org.jboss.ejb.StatefulSessionContainer.invoke(StatefulSessionContainer.java:341)
            at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invoke(JRMPContainerInvoker.java:483)
            at org.jboss.ejb.plugins.jrmp.interfaces.GenericProxy.invokeContainer(GenericProxy.java:335)
            at org.jboss.ejb.plugins.jrmp.interfaces.StatefulSessionProxy.invoke(StatefulSessionProxy.java:136)

            Any suggestions for the above problem.
            Thanks
            Winston.

            • 3. Re: Passivation problem(again).....
              pwinstonr

              Lothar
              This following exception was also thrown just after I clicked on other areas of my application, after it threw the exceptions I've mentioned in my previous post.

              java.rmi.NoSuchObjectException: Could not activate; nested exception is:
              java.io.FileNotFoundException: C:\JBoss-2.4.0_Tomcat-3.2.3\jboss\bin\sessions\PersonSession\999207139821.ser (The system cannot find the file specified)
              at org.jboss.ejb.plugins.AbstractInstanceCache.get(AbstractInstanceCache.java:175)
              at org.jboss.ejb.plugins.StatefulSessionInstanceInterceptor.invoke(StatefulSessionInstanceInterceptor.java:157)
              at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
              at org.jboss.ejb.StatefulSessionContainer.invoke(StatefulSessionContainer.java:341)
              at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invoke(JRMPContainerInvoker.java:483)
              at org.jboss.ejb.plugins.jrmp.interfaces.GenericProxy.invokeContainer(GenericProxy.java:335)
              at org.jboss.ejb.plugins.jrmp.interfaces.StatefulSessionProxy.invoke(StatefulSessionProxy.java:136)
              at $Proxy13.resetCart(Unknown Source)

              Regards,
              Winston

              • 4. Re: Passivation problem(again).....

                Hi,

                Can the system serialize the Person and Address objects?

                From the exceptions thrown, I would guess one of the class does not implement the Serializable interface.

                FE

                • 5. Re: Passivation problem(again).....

                  The ejbPassivate serves as a place where all resources which can not be or are not wanted to be passivated are released, but only such resources. A typical example of a non passivable resource is a db connection, so lets assume u have an instance field named con of type java.sql.Connection. During passivate u would do a con.close(); con=null; now the con field can be serialized cause a null can always be serialized. When the con field would contain a Connection object closed or not an exception would be thrown during the serialization of the bean. You do the same with resources which are serializable but you dont want them to be serialized. The method with adding null to fields before serialization is equivalent with marking the fields as transient. But remember that you have to do clean up (close the connection) on a transient field too, it saves you only the null assignment. Also be aware, that a transient field will possibly not have a null value after deserialization. If i understand the person field holds info about a person which can not be derived from any other serializable fields. When so this field must be serialized in order not to loose its value - u may not mark it as transient nor assign a null to it - as u saw u will loose its value. Person is a data field a value of which must be preserved and will be preserved by the serialization. I assume the Person class has only some primitive type fields like name, birthDate etc. if so u only need to implement the java.io.Serializable in the class in order to make the class serializable, all the serialization stuff will be handled by the jvm automatically. Now the ejbActivate - very simple. A rule u will use 90% of cases is "you released it in ejbPassivate -> aquire it a new in ejbActivate" the 10% will be some lazy-loding of resouces stuff. So u will do a con=dataSource.createConnection() in ejbActive(). For further reading i recommed ejb spec, javadoc for java.io.Serialiazable and the serialization trial in the java tutorial. Have fun :)