I've been looking in lots of places for examples on how to do transactions with stateful session beans, but either the tutorials avoid the subject ("and now transactions with entity beans...") or they parrot the usual stuff about transaction attributes.
What I've done is to declare the methods of my session bean as having the "Required" transaction attribute, and then to throw an EJBException when I want the transaction rolled back. Just to make sure I get the correct behaviour, I also call setRollbackOnly on the SessionContext object provided by setSessionContext. (Actually, this last detail seems to make no difference to the behaviour I'm about to describe.)
What I get is an exception, as expected:
[FundManager] TRANSACTION ROLLBACK EXCEPTION:this.funds >= 0; nested exception is:
javax.ejb.EJBException: this.funds >= 0
But then, upon subsequent method calls on the same object I get this kind of thing:
[FundManager] TRANSACTION ROLLBACK EXCEPTION:Could not activate; nested exception is:
java.io.FileNotFoundException: D:\Software\JBoss\JBoss-2.4.3_Jetty-3.1.3-1\jboss\db\sessions\FundManager\1008087785479.ser (The system cannot find the file specified); nested exception is:
java.rmi.NoSuchObjectException: Could not activate; nested exception is:
java.io.FileNotFoundException: D:\Software\JBoss\JBoss-2.4.3_Jetty-3.1.3-1\jboss\db\sessions\FundManager\1008087785479.ser (The system cannot find the file specified)
[FundManager] java.rmi.NoSuchObjectException: Could not activate; nested exception is:
[FundManager] java.io.FileNotFoundException: D:\Software\JBoss\JBoss-2.4.3_Jetty-3.1.3-1\jboss\db\sessions\FundManager\1008087785479.ser (The system cannot find the file specified)
[FundManager] at org.jboss.ejb.plugins.AbstractInstanceCache.get(AbstractInstanceCache.java:211)
[FundManager] at org.jboss.ejb.plugins.StatefulSessionInstanceInterceptor.invoke(StatefulSessionInstanceInterceptor.java:194)
[FundManager] at org.jboss.ejb.plugins.TxInterceptorCMT.invokeNext(TxInterceptorCMT.java:133)
[FundManager] at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:307)
[FundManager] at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:99)
[FundManager] at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:195)
[FundManager] at org.jboss.ejb.StatefulSessionContainer.invoke(StatefulSessionContainer.java:341)
[FundManager] at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invoke(JRMPContainerInvoker.java:395)
[FundManager] at java.lang.reflect.Method.invoke(Native Method)
[FundManager] at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:241)
[FundManager] at sun.rmi.transport.Transport$1.run(Transport.java:152)
[FundManager] at java.security.AccessController.doPrivileged(Native Method)
[FundManager] at sun.rmi.transport.Transport.serviceCall(Transport.java:148)
[FundManager] at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:465)
[FundManager] at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:706)
[FundManager] at java.lang.Thread.run(Thread.java:484)
Now, the subsequent calls all take place on a reference which is held by the client. So, I tried to do some things with getting a Handle for that reference, then getting the EJBObject, and then trying to invoke those methods. Still no luck there, either!
The big question is: does anyone else do this kind of thing, or is this all unsupported (in JBoss 2.4.3/2.4.4beta integrated with Jetty 3.1.3-1)?
The transactions with Stateful is one of my favorite patterns, I cover it in great detail in the JBoss Group training. That being said I think your problem is simply one of persistence check the FAQ there is an entry for this problem (persistence)
I had a look at the FAQ entry, but this didn't really help. I also noticed that someone else had very similar error reports and was also referred to that entry.
For me, the problems with accessing the session bean in question only ever happen after a transaction rollback. Until that time, there are no problems with accessing the bean at all. Of course, this could be the first time that any persistence is attempted, but I haven't looked at the JBoss source code.
Now, what I've tried to do is to make the attributes of the bean public, which may have been what the FAQ entry was getting at, although the wording wasn't really clear enough - obviously, my accessor methods are public... Unfortunately, this doesn't improve the situation.
I've also made changes to the Stateful SessionBean cache-policy-conf section in standardjboss.xml, so that ridiculously high values for the age properties were used. This also had no effect.
Are there any complete examples of this anywhere?
I managed to get transactions working with stateful session beans, although it's hard to follow the documentation available in various places and get something working as expected.
See http://www.jboss.org/modules/bb/index.html?module=bb&op=viewtopic&t=forums/ for my progress on this topic.
I have the same problem on JBoss 2.4.3. When I throw an EJBException in a stateful session bean, any subsequent call to the bean gets a FileNotFoundException on activation, even though the bean hasn't been passivated.
Normal passivation works fine on our bean. I checked the FAQ on the subject but don't feel it addresses this particular problem.
Digging deeper into the EJB Spec in section 18.3.1 it appears that when a non app-exception is thrown, (by the spec) it discards the instance of the session bean. Therefor if subsequent calls are desired the programmer should recreate the session bean from the home interface. Otherwise the bean writer should use app-exceptions and setRollBackOnly where applicable to communicate an exception/rollback/and keep a reference to the instance.
This includes security exceptions which is giving us big piles of grief right now.
I understand why system exceptions (defined, I think, as all RuntimeException subclasses and RemoteException) should cause transaction rollback, but I don't understand why a security exception should invalidate an sfsb instance. This means all my state is lost and I have to keep a copy of it on the client - making the whole sfsb idea kind of useless.