I'm seeing some issues related to caching and passivation of nested SFSBs (i.e. one SFSB holds a ref to another, i.e. through an @EJB annotation). I'd like to get some input as to what the proper behavior is.
What I'm seeing is:
If the nested bean declares an @Remote interface, when the parent bean is being constructed for the nested bean an instance of StatefulBeanContext ends up being cached. This works fine.
If the nested bean does not declare an @Remote interface, when the parent bean is being constructed, for the nested bean an instance of ProxiedStatefulBeanContext ends up being cached. This leads to problems.
The problem occurs if the parent bean is later removed. This does not result in a call to remove the child bean from the cache. (I don't know if that's a problem or not; Chapter 11.7 of Bill Burke's book says it should be removed, but I couldn't find a discussion of that in the spec.)
A replicated ProxiedStatefulBeanContext is useless if its parent is not in the cache. The replication clears the transient reference to the parent bean. If the context is later used, ProxiedStatefulBeanContext.getDelegate() will attempt to look up the parent, which will result in a NoSuchEjbException.
The problem occurs when the background passivation thread decides to passivate the orphaned ProxiedStatefulBeanContext and calls prePassivate(). You get this:
javax.ejb.NoSuchEJBException: Could not find Stateful bean: a1g1m-b11vx1-exf6itu4-1-exf6mcqp-1v at org.jboss.ejb3.cache.tree.StatefulTreeCache.get(StatefulTreeCache.java:148) at org.jboss.ejb3.stateful.StatefulBeanContextReference.getBeanContext(StatefulBeanContextReference.java:72) at org.jboss.ejb3.stateful.ProxiedStatefulBeanContext.getDelegate(ProxiedStatefulBeanContext.java:70) at org.jboss.ejb3.stateful.ProxiedStatefulBeanContext.getContainer(ProxiedStatefulBeanContext.java:213) at org.jboss.ejb3.stateful.StatefulBeanContext.prePassivate(StatefulBeanContext.java:178) at org.jboss.ejb3.cache.tree.StatefulTreeCache$ClusteredStatefulCacheListener.nodePassivated(StatefulTreeCache.java:376) at org.jboss.cache.notifications.Notifier.notifyNodePassivated(Notifier.java:423) ...
Id a1g1m-b11vx1-exf6itu4-1-exf6mcqp-1v belongs to the parent bean.
Some solutions I can see are:
1) If the child bean is meant to be removed along with the parent, fix whatever's preventing that from happening.
2) Have the StatefulCache impls not cache instances of ProxiedStatefulBeanContext. I don't understand the usage of this class well enough to know whether that's a valid solution or not. I doubt it.
3) Have the StatefulCache impls catch NoSuchEjbException when they call prePassivate(). Check if the context type is ProxiedStatefulBeanContext; if it is, suppress the exception and remove the useless context from the cache. That's ugly but limited in scope.
Any comments/suggestions are most appreciated.