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

[1169 byte] By [allanchiwingtana] at [2007-9-28 17:27:17]
# 1

You are probably keeping a class instance variable of a your connection object, which cannot be (and won't ever be able to be) serialized by the VM when the bean tries to passivate itself. You should just get a connection ...use it ...then release it back to the pool. You can't passivate a connection object.

I almost get the feeling you are using this session bean as a shared connection object in your app ...why don't you go with a connection pool that uses the singleton pattern instead?

However you are approaching this, you will never be able to serialize your connection object (unless you declare it as transient ...but I don't think that is going to fit with what I presume you are trying to achieve here). I hope I have shed some light here :)

GumB.a at 2007-7-12 14:57:26 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

thx for the reply GumB

i'm fairly new to EJBs. myself and a coworker have a project to do.. so yes you are right, this class was kindof our database interface class, and was passed around to minimize the number of connections req'd.

could u elaborate a bit about how to use a connection pool? i do have an o-reilly book here on j2EE so i'll look up some on what you said

thx

allanchiwingtana at 2007-7-12 14:57:26 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

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 > top of Java-index,Other Topics,Patterns & OO Design...
# 4
that'd be great GumB. thx for your help! i'll do some reading today so i understand what you're talking about :P
allanchiwingtana at 2007-7-12 14:57:26 > top of Java-index,Other Topics,Patterns & OO Design...
# 5
btw, the transient fix worked :)albeit it was slow to test, cuz jboss doesn't seem to autopassivate until 15 mins after each execution.:D
allanchiwingtana at 2007-7-12 14:57:26 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

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 > top of Java-index,Other Topics,Patterns & OO Design...
# 7
looks good gumB. i have some other work to attend to but i'll try this out once i get a chance.thanks again for all the help! it is appreciated
allanchiwingtana at 2007-7-12 14:57:26 > top of Java-index,Other Topics,Patterns & OO Design...