dain 2005/02/25 18:06:11
Modified: modules/core/src/java/org/openejb/sfsb CreateMethod.java
StatefulInstanceContext.java
StatefulInstanceInterceptor.java
Log:
Added support for in-tx cacheing back in
This unturned a load of places that were not handling transaction contexts
properly and bugs in the context itself
Changed instance contexts so they track entrancy and can be killed as
required by the spec
Made all instance context fields final
Revision Changes Path
1.4 +1 -3
openejb/modules/core/src/java/org/openejb/sfsb/CreateMethod.java
Index: CreateMethod.java
===================================================================
RCS file:
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/sfsb/CreateMethod.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- CreateMethod.java 18 Jul 2004 22:32:24 -0000 1.3
+++ CreateMethod.java 25 Feb 2005 23:06:11 -0000 1.4
@@ -117,8 +117,6 @@
invocation.setTransactionContext(TransactionContext.getContext());
}
}
- // associate the new sfsb with the tx cache
- invocation.getTransactionContext().associate(ctx);
// return a ref
EJBInterfaceType type = invocation.getType();
1.11 +45 -24
openejb/modules/core/src/java/org/openejb/sfsb/StatefulInstanceContext.java
Index: StatefulInstanceContext.java
===================================================================
RCS file:
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/sfsb/StatefulInstanceContext.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- StatefulInstanceContext.java 15 Feb 2005 03:24:03 -0000 1.10
+++ StatefulInstanceContext.java 25 Feb 2005 23:06:11 -0000 1.11
@@ -60,6 +60,7 @@
import org.openejb.AbstractInstanceContext;
import org.openejb.EJBOperation;
import org.openejb.EJBInvocation;
+import org.openejb.cache.InstanceCache;
import org.openejb.dispatch.SystemMethodIndices;
import org.openejb.proxy.EJBProxyFactory;
@@ -70,20 +71,20 @@
*/
public class StatefulInstanceContext extends AbstractInstanceContext {
private static final Log log =
LogFactory.getLog(StatefulInstanceContext.class);
- private final Object containerId;
private final Object id;
private final StatefulSessionContext statefulContext;
+ private final EJBInvocation setContextInvocation;
+ private final EJBInvocation unsetContextInvocation;
private final EJBInvocation afterBeginInvocation;
private final EJBInvocation beforeCompletionInvocation;
- private boolean dead = false;
+ private final SystemMethodIndices systemMethodIndices;
private BeanTransactionContext preexistingContext;
private EJBOperation operation;
- private final SystemMethodIndices systemMethodIndices;
+ private InstanceCache cache;
public StatefulInstanceContext(Object containerId, EJBProxyFactory
proxyFactory, SessionBean instance, Object id, TransactionContextManager
transactionContextManager, UserTransactionImpl userTransaction,
SystemMethodIndices systemMethodIndices, Interceptor systemChain, Set
unshareableResources, Set applicationManagedSecurityResources) {
//currently stateful beans have no timer service.
- super(systemChain, unshareableResources,
applicationManagedSecurityResources, instance, proxyFactory, null);
- this.containerId = containerId;
+ super(containerId, instance, systemChain, proxyFactory, null,
unshareableResources, applicationManagedSecurityResources);
this.id = id;
statefulContext = new StatefulSessionContext(this,
transactionContextManager, userTransaction);
this.systemMethodIndices = systemMethodIndices;
@@ -98,13 +99,10 @@
}
}
- public Object getContainerId() {
- return containerId;
- }
-
public EJBOperation getOperation() {
return operation;
}
+
public void setOperation(EJBOperation operation) {
statefulContext.setState(operation);
this.operation = operation;
@@ -118,11 +116,6 @@
return id;
}
- public void setId(Object id) {
- // @todo remove setId from the EJBInstanceContext interface
- throw new UnsupportedOperationException();
- }
-
public BeanTransactionContext getPreexistingContext() {
return preexistingContext;
}
@@ -131,6 +124,14 @@
this.preexistingContext = preexistingContext;
}
+ public InstanceCache getCache() {
+ return cache;
+ }
+
+ public void setCache(InstanceCache cache) {
+ this.cache = cache;
+ }
+
public void die() {
if (preexistingContext != null) {
try {
@@ -140,18 +141,33 @@
}
preexistingContext = null;
}
- dead = true;
- }
-
- public boolean isDead() {
- return dead;
+ if (cache != null) {
+ cache.remove(id);
+ cache = null;
+ }
+ super.die();
}
public StatefulSessionContext getSessionContext() {
return statefulContext;
}
+ public void setContext() throws Throwable {
+ if (isDead()) {
+ throw new IllegalStateException("Context is dead: container=" +
getContainerId() + ", id=" + getId());
+ }
+ systemChain.invoke(setContextInvocation);
+ }
+
+ public void unsetContext() throws Throwable {
+ if (isDead()) {
+ throw new IllegalStateException("Context is dead: container=" +
getContainerId() + ", id=" + getId());
+ }
+ systemChain.invoke(unsetContextInvocation);
+ }
+
public void associate() throws Throwable {
+ super.associate();
if (getInstance() instanceof SessionSynchronization) {
assert(getInstance() != null);
systemChain.invoke(afterBeginInvocation);
@@ -159,6 +175,7 @@
}
public void beforeCommit() throws Throwable {
+ super.beforeCommit();
if (getInstance() instanceof SessionSynchronization) {
assert(getInstance() != null);
systemChain.invoke(beforeCompletionInvocation);
@@ -166,13 +183,17 @@
}
public void afterCommit(boolean committed) throws Throwable {
- if (!dead) {
- // @todo fix me
-// container.getInstanceCache().putInactive(id, this);
- }
+ super.beforeCommit();
if (getInstance() instanceof SessionSynchronization) {
assert(getInstance() != null);
systemChain.invoke(systemMethodIndices.getAfterCompletionInvocation(this,
committed));
+ }
+ }
+
+ public void unassociate() throws Throwable {
+ super.unassociate();
+ if (!isDead() && cache != null) {
+ cache.putInactive(id, this);
}
}
}
1.5 +27 -21
openejb/modules/core/src/java/org/openejb/sfsb/StatefulInstanceInterceptor.java
Index: StatefulInstanceInterceptor.java
===================================================================
RCS file:
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/sfsb/StatefulInstanceInterceptor.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- StatefulInstanceInterceptor.java 15 Feb 2005 03:24:03 -0000 1.4
+++ StatefulInstanceInterceptor.java 25 Feb 2005 23:06:11 -0000 1.5
@@ -57,10 +57,13 @@
import org.apache.geronimo.transaction.context.BeanTransactionContext;
import org.apache.geronimo.transaction.context.TransactionContextManager;
import org.apache.geronimo.transaction.context.UnspecifiedTransactionContext;
+import org.apache.geronimo.transaction.InstanceContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openejb.EJBInvocation;
+import org.openejb.NotReentrantLocalException;
+import org.openejb.NotReentrantException;
import org.openejb.transaction.UncommittedTransactionException;
import org.openejb.cache.InstanceCache;
import org.openejb.cache.InstanceFactory;
@@ -96,26 +99,36 @@
ejbInvocation.setEJBInstanceContext(ctx);
// resume the preexisting transaction context
- TransactionContext oldContext =
transactionContextManager.getContext();
+ TransactionContext oldTransactionContext =
transactionContextManager.getContext();
if (ctx.getPreexistingContext() != null) {
BeanTransactionContext preexistingContext =
ctx.getPreexistingContext();
ctx.setPreexistingContext(null);
- preexistingContext.setOldContext((UnspecifiedTransactionContext)
oldContext);
+ preexistingContext.setOldContext((UnspecifiedTransactionContext)
oldTransactionContext);
ejbInvocation.setTransactionContext(preexistingContext);
transactionContextManager.setContext(preexistingContext);
preexistingContext.resume();
}
+ // check reentrancy
+ if (ctx.isInCall()) {
+ if (ejbInvocation.getType().isLocal()) {
+ throw new NotReentrantLocalException("Stateful session beans
do not support reentrancy: " + containerId);
+ } else {
+ throw new NotReentrantException("Stateful session beans do
not support reentrancy: " + containerId);
+ }
+ }
+
+ InstanceContext oldInstanceContext =
ejbInvocation.getTransactionContext().beginInvocation(ctx);
try {
// invoke next
InvocationResult invocationResult = next.invoke(invocation);
// if we have a BMT still associated with the thread, suspend it
and save it off for the next invocation
TransactionContext currentContext =
transactionContextManager.getContext();
- if (oldContext != currentContext) {
+ if (oldTransactionContext != currentContext) {
BeanTransactionContext preexistingContext =
(BeanTransactionContext)currentContext;
- if (preexistingContext.getOldContext() != oldContext) {
+ if (preexistingContext.getOldContext() !=
oldTransactionContext) {
throw new UncommittedTransactionException("Found an
uncommitted bean transaction from another session bean");
}
// suspend and save off the BMT context
@@ -124,9 +137,9 @@
ctx.setPreexistingContext(preexistingContext);
// resume the old unsupported transaction context
- ejbInvocation.setTransactionContext(oldContext);
- transactionContextManager.setContext(oldContext);
- oldContext.resume();
+ ejbInvocation.setTransactionContext(oldTransactionContext);
+ transactionContextManager.setContext(oldTransactionContext);
+ oldTransactionContext.resume();
}
return invocationResult;
@@ -135,7 +148,7 @@
ctx.die();
// if we have tx context, other then our old tx context,
associated with the thread roll it back
- if (oldContext != transactionContextManager.getContext()) {
+ if (oldTransactionContext !=
transactionContextManager.getContext()) {
try {
transactionContextManager.getContext().rollback();
} catch (Exception e) {
@@ -143,18 +156,14 @@
}
// and resume the old transaction
- ejbInvocation.setTransactionContext(oldContext);
- transactionContextManager.setContext(oldContext);
- oldContext.resume();
+ ejbInvocation.setTransactionContext(oldTransactionContext);
+ transactionContextManager.setContext(oldTransactionContext);
+ oldTransactionContext.resume();
}
throw t;
} finally {
- if (ctx.isDead()) {
- cache.remove(ctx.getId());
- }
-
- // remove the reference to the context from the invocation
+
ejbInvocation.getTransactionContext().endInvocation(oldInstanceContext);
ejbInvocation.setEJBInstanceContext(null);
}
}
@@ -167,10 +176,8 @@
ctx = (StatefulInstanceContext) factory.createInstance();
assert ctx.getInstance() != null: "Got a context with no
instance assigned";
id = ctx.getId();
+ ctx.setCache(cache);
cache.putActive(id, ctx);
-
- TransactionContext transactionContext =
ejbInvocation.getTransactionContext();
- transactionContext.associate(ctx);
} else {
// first check the transaction cache
TransactionContext transactionContext =
ejbInvocation.getTransactionContext();
@@ -186,7 +193,6 @@
throw new NoSuchObjectException(id.toString());
}
}
- transactionContext.associate(ctx);
}
if (ctx.isDead()) {