Followup from some testing
If I try
bean = home.create(); bean.method1(); bean.method2(); bean.remove();
then - after method1 completes (on method exit) Jboss shouts:
2004-10-05 23:36:09,053 INFO [org.jboss.resource.connectionmanager.CachedConnectionManager] Closing a connection for you. Please close them yourself: org.jboss.resource.adapter.jdbc.WrappedConnection@1870cfc java.lang.Exception: STACKTRACE ...
bean.method2() finds an existing hibernate session (in the stateful beans state) - but - when it tries to access this session it gets told that the underlying database connection is closed.
Can a connection not be held in a stateful beans state?
The config for the bean looks like:
<session > <description>>Config lookup bean (key/val)</description> <ejb-name>AdminSB</ejb-name> <home>org.longship.joti.ejb.interfaces.AdminSBHome</home> <remote>org.longship.joti.ejb.interfaces.AdminSB</remote> <ejb-class>org.longship.joti.ejb.session.AdminSBSession</ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> </session>
From the looks of your code, it looks like you're coding to an anti-pattern. See http://blog.hibernate.org/cgi-bin/blosxom.cgi/2004/01/27#perf-problems
Have you tried this: only call flush or commit at the last method ? This is probably what Gavin is describing in his blog item e.g. session-per-application-transaction-with-flush-delayed-to-the-last-request
I'm trying for what I guess I'd call
So - a request comes in (servlet). That creates a service object (business layer stub) which will call the business logic in the session beans.
To avoid session-per-operation (which was the code I inherited) I thought - OK - let's move the session into the state of the bean.
So logic should be:
bean = home.create(); bean.method1(); // Calls getSession - Session created bean.method2(); // Calls getSession - returns stored session bean.remove(); // Session removed.
Note - you need to nullify the session at passivate (or at least I think you do) - so the getSession method was created - to create a session if one didn't exist from before or if passivate had been called. This would look like
bean = home.create(); bean.method1(); // Calls getSession - Session created Bean passivated - session closed bean.method2(); // Calls getSession - Session created bean.remove(); // Session removed.
The problem is that when method1 exits - then I get the
2004-10-05 23:36:09,053 INFO [org.jboss.resource.Connectionmanager.CachedConnectionManager] Closing a connection for you. Please close them yourself: org.jboss.resource.adapter.jdbc.WrappedConnection@1870cfc java.lang.Exception: STACKTRACE
error - even though the session is stored in an active stateful session beans session.
NB - this is a gradual process - moving now from session per operation to session per bean per request - will move to session per request if I can figure out how to share the session between bean instances without returning it over RMI from the EJB container.
OK - I've removed the exception.
The bean now implements javax.ejb.SessionSynchronization - and in the beforeCompletion method it calls session.disconnect(). In the getSession method it calls session.reconnect().
So - the session stays but the connection doesn't.
(Have the feeling this is getting far far off the JCA topic here :-))
So - I have one-session-per-ejb-per-request-but-that-connects-disconnects-with-each-method-call
Now all I need to figure out how to share a given session between session beans that are used in the same request (servlet/application) and maybe to keep the connection open (not sure if it's a good idea to do this or not -or even if it's possible).
beforeCompletion is not invoked if the transaction rollsback