EJB - Could not passivate exception
hey need help with this error. building a web application, everythings runs fine.
specs
-uses stateful ejbs
-using jboss
-apache tomcat
now i have a specific bean that opens a connection to our mysql db, and a reference to this bean is passed around.
it works fine, however about 15 mins after executing, i get this in my jboss.log file:
11:51:03,643 ERROR [Log4jService$ThrowableListenerLoggingAdapter] unhandled throwable
javax.ejb.EJBException: Could not passivate; CausedByException is:
com.mysql.jdbc.jdbc2.Connection
at org.jboss.ejb.plugins.StatefulSessionFilePersistenceManager.passivateSession(StatefulSessionFilePersistenceManager.java:293)
at org.jboss.ejb.plugins.StatefulSessionInstanceCache.passivate(StatefulSessionInstanceCache.java:78)
at org.jboss.ejb.plugins.AbstractInstanceCache$1.execute(AbstractInstanceCache.java:616)
at org.jboss.util.WorkerQueue$QueueLoop.run(WorkerQueue.java:206)
at java.lang.Thread.run(Thread.java:536)
java.io.NotSerializableException: com.mysql.jdbc.jdbc2.Connection
anybody else encountered this? any ideas?
TIA
Well, building a pool is a whole deal unto itself ...I posted one in the JDBC section last year, I will look for the link and get it for you (maybe tommorow, it's almost home time now).
For starters, take a look in your O'Reilly book and find an example that uses bean managed persistance. You will notice they probably have a method that gets a connection from a jndi data resource, and one that releases a connection by passing it back to the same jndi resource. Now don't get riled ...I used my own pool instead of a jndi resource (although we both likely should be using a jndi resource), but the concept either way is just the same.
Now, looking at an O'Reilly example you will notice that inside some of the methods the connection activity is as such:
Method starts:
- get a connection (previously built by the pool)
- use it
- release it back to the pool (still alive)
Method ends.
Your trouble is that you are just doing this once, and storing the connection as a class level variable so you can use that same connection when any of your assorted methods are called. While this would work in an app or standalone java thingy ...it won't work in the EJB lifecycle. The reson is that the container may decide to passivate (serialize) your object, and this is beyond your control ...but the class level connection object cannot be serialized, and so you get your error.
Tommorow I will gather and show you a singleton pool, but until then you could experiment with this (less than optimal) alternative.
Declare your class level connection as transient ...any thing with this keyword is ignored by serialization. Then, in your ejbPassivate bean method (called just before passivation) ...close your class level connection. Then, in ejbActivate (called when the bean is unserialized again) ...instantiate the connection again.
Anyhoo ...I will write more tomorrow when I am back at work. Soon I have to go home, and that's when my life gets real busy. Go figure, hey?
GumB.a at 2007-7-12 14:57:26 >

I'm glad the transient declaration got your design up and running. Maybe you will be happy keeping things as they are and moving on with your project. However, let's discuss some examples that move away from the idea of obtaining a connection and holding on to it for the life of the users session.
In your O'Reilly book, Chapter 10 has a bean managed persistence example. Although it is an Entity bean, you would use the same approach in a session bean that interacted with a database as well. What I want you to notice in the example is how each method gets a connection ...uses it ...then releases it.
public class ShipBean implements javax.ejb.EntityBean
{
// ... lots of this class has been snipped ...
public void ejbHomeMakeDbTable () throws SQLException
{
PreparedStatement ps = null;
Connection con = null;
try
{
con = this.getConnection ();
System.out.println("Creating table SHIP...");
ps = con.prepareStatement ("CREATE TABLE SHIP ( " +
"ID INT PRIMARY KEY, " +
"NAME CHAR(30), " +
"TONNAGE DECIMAL (8,2), " +
"CAPACITY INT" +
")" );
ps.execute ();
System.out.println("...done!");
}
finally
{
try { ps.close (); } catch (Exception e) {}
try { con.close (); } catch (Exception e) {}
}
}
public void ejbHomeDeleteDbTable () throws SQLException
{
PreparedStatement ps = null;
Connection con = null;
try
{
con = this.getConnection ();
System.out.println("Dropping table SHIP...");
ps = con.prepareStatement ("DROP TABLE SHIP");
ps.execute ();
System.out.println("...done!");
}
finally
{
try { ps.close (); } catch (Exception e) {}
try { con.close (); } catch (Exception e) {}
}
}
private Connection getConnection () throws SQLException
{
try
{
Context jndiCntx = new InitialContext ();
DataSource ds =
(DataSource)jndiCntx.lookup ("java:comp/env/jdbc/titanDB");
return ds.getConnection ();
}
catch (NamingException ne)
{
throw new EJBException (ne);
}
}
}
Of course there are deployment descriptors that you will have to set up to properly support this methodology, but they are discussed in the chapter 10 example so I won't repeat them here. I have implemented my own pool in place of the jndi resource lookup of the datasource here, but I will not digress into that at this point, because that is a slight divergence from the standard methodology you will see in most examples on the subject. You could also check out the examples that come with the Sun J2EE tutorial, you will see the exact same technique applied in those examples as well.
I guess the question I will leave you with is this: Are you implementing your business logic in the ejb session bean you are using ...or is this session bean literally just a wrapper for your users connection, which you use inside of your web app. If you are not dividing your business logic out into the session bean, then I would question why use an ejb server at all when a singleton pooled connection class could do the trick without so much overkill. However, if you are properly placing your business logic algorithms into the session bean, then I applaud you (that's the right thing to be doing with an ejb design).
The main difference in the example I have provided and your approach is that your user will dominate a connection for the whole time their session is active. Conversly, the chapter 10 example just uses a db connection for a brief moment and then releases it. Your user is guaranteed to spend far more time staring vacantly at their monitor or leaving their computer to go have lunch or dinner than they will actually using that connection, so are you sure you want them to hold it alive and to themselves the whole way through their session? You are tying up those resources, possibly for hours, when the actual processor time for the connection might actually only amount to a few seconds over the length of their whole stay.
Anyhow, if you want an example of a connection pool (as a complete alternative approach), I found the link where I posted the pool that comes in a Marty Hall Book. Please have at it look if you are interested.
http://forum.java.sun.com/thread.jsp?forum=48&thread=247327
It doesn't demonstrate the singleton, but if the code turns you on I would be happy to provide you with an example.
GumB.
GumB.a at 2007-7-12 14:57:26 >
