You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2007/01/12 02:09:42 UTC
svn commit: r495458 - in
/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core:
stateful/ transaction/
Author: dain
Date: Thu Jan 11 17:09:42 2007
New Revision: 495458
URL: http://svn.apache.org/viewvc?view=rev&rev=495458
Log:
Cleaned up stateful container and instance manager
Modified:
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulBeanManagedTxPolicy.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/transaction/TransactionContext.java
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java?view=diff&rev=495458&r1=495457&r2=495458
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/BeanEntry.java Thu Jan 11 17:09:42 2007
@@ -16,29 +16,31 @@
*/
package org.apache.openejb.core.stateful;
+import java.io.Serializable;
import javax.transaction.Transaction;
-public class BeanEntry implements java.io.Serializable {
+public class BeanEntry implements Serializable {
+ private static final long serialVersionUID = 5940667199866151048L;
+
protected final Object bean;
- protected Object primaryKey;
- protected Object ancillaryState;
- protected transient Transaction transaction;
- protected long timeStamp;
- protected long timeOutInterval;
- protected boolean inQue = false;
+ protected final Object primaryKey;
+ protected boolean inQueue = false;
+ private long timeStamp;
+ private long timeOutInterval;
+ protected transient Transaction beanTransaction;
- protected BeanEntry(Object beanInstance, Object primKey, Object ancillary, long timeOut) {
+ protected BeanEntry(Object beanInstance, Object primKey, long timeOut) {
bean = beanInstance;
primaryKey = primKey;
- ancillaryState = ancillary;
- transaction = null;
+ beanTransaction = null;
timeStamp = System.currentTimeMillis();
timeOutInterval = timeOut;
}
protected boolean isTimedOut() {
- if (timeOutInterval == 0)
+ if (timeOutInterval == 0) {
return false;
+ }
long now = System.currentTimeMillis();
return (now - timeStamp) > timeOutInterval;
}
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulBeanManagedTxPolicy.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulBeanManagedTxPolicy.java?view=diff&rev=495458&r1=495457&r2=495458
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulBeanManagedTxPolicy.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulBeanManagedTxPolicy.java Thu Jan 11 17:09:42 2007
@@ -16,23 +16,21 @@
*/
package org.apache.openejb.core.stateful;
+import javax.transaction.Status;
+import javax.transaction.Transaction;
+
import org.apache.openejb.ApplicationException;
-import org.apache.openejb.InvalidateReferenceException;
+import org.apache.openejb.Container;
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.SystemException;
import org.apache.openejb.core.transaction.TransactionContainer;
import org.apache.openejb.core.transaction.TransactionContext;
import org.apache.openejb.core.transaction.TransactionPolicy;
-import javax.transaction.Status;
-import javax.transaction.Transaction;
-import java.rmi.RemoteException;
-
public class StatefulBeanManagedTxPolicy extends TransactionPolicy {
-
public StatefulBeanManagedTxPolicy(TransactionContainer container) {
- this();
- if (container instanceof org.apache.openejb.Container &&
- ((org.apache.openejb.Container) container).getContainerType() != org.apache.openejb.Container.STATEFUL) {
- throw new IllegalArgumentException();
+ if (container instanceof Container && ((Container) container).getContainerType() != Container.STATEFUL) {
+ throw new IllegalArgumentException("Container is not an StatefulContainer");
}
this.container = container;
}
@@ -45,45 +43,47 @@
return "TX_BeanManaged: ";
}
- public void beforeInvoke(Object instance, TransactionContext context) throws org.apache.openejb.SystemException, org.apache.openejb.ApplicationException {
+ public void beforeInvoke(Object instance, TransactionContext context) throws SystemException, ApplicationException {
try {
+ StatefulInstanceManager instanceManager = ((StatefulContainer)container).getInstanceManager();
- StatefulInstanceManager instanceManager = (StatefulInstanceManager) context.context.get(StatefulInstanceManager.class);
+ // suspend any transaction currently associated with this thread
// if no transaction ---> suspend returns null
context.clientTx = suspendTransaction(context);
- // Get any previously started transaction
+ // Resume previous Bean transaction if there was one
Object primaryKey = context.callContext.getPrimaryKey();
- Object possibleBeanTx = instanceManager.getAncillaryState(primaryKey);
- if (possibleBeanTx instanceof Transaction) {
- context.currentTx = (Transaction) possibleBeanTx;
+ Transaction beanTransaction = instanceManager.getBeanTransaction(primaryKey);
+ if (beanTransaction != null) {
+ context.currentTx = beanTransaction;
resumeTransaction(context, context.currentTx);
}
- } catch (org.apache.openejb.OpenEJBException e) {
+ } catch (OpenEJBException e) {
handleSystemException(e.getRootCause(), instance, context);
}
}
- public void afterInvoke(Object instance, TransactionContext context) throws org.apache.openejb.ApplicationException, org.apache.openejb.SystemException {
+ public void afterInvoke(Object instance, TransactionContext context) throws ApplicationException, SystemException {
try {
-
+ // Get the transaction after the method invocation
context.currentTx = context.getTransactionManager().getTransaction();
- /*
-
- */
- if (context.currentTx != null &&
- context.currentTx.getStatus() != Status.STATUS_COMMITTED &&
- context.currentTx.getStatus() != Status.STATUS_ROLLEDBACK) {
-
- suspendTransaction(context);
+ // If it is not complete, suspend the transaction
+ if (context.currentTx != null) {
+ int status = context.currentTx.getStatus();
+ if (status != Status.STATUS_COMMITTED && status != Status.STATUS_ROLLEDBACK) {
+ suspendTransaction(context);
+ } else {
+ // transaction is complete, so there is no need to maintain a referecne to it
+ context.clientTx = null;
+ }
}
+ // Update the user transaction reference in the bean instance data
Object primaryKey = context.callContext.getPrimaryKey();
- StatefulInstanceManager instanceManager = (StatefulInstanceManager) context.context.get(StatefulInstanceManager.class);
- instanceManager.setAncillaryState(primaryKey, context.currentTx);
-
- } catch (org.apache.openejb.OpenEJBException e) {
+ StatefulInstanceManager instanceManager = ((StatefulContainer)container).getInstanceManager();
+ instanceManager.setBeanTransaction(primaryKey, context.currentTx);
+ } catch (OpenEJBException e) {
handleSystemException(e.getRootCause(), instance, context);
} catch (javax.transaction.SystemException e) {
handleSystemException(e, instance, context);
@@ -95,12 +95,10 @@
}
public void handleApplicationException(Throwable appException, TransactionContext context) throws ApplicationException {
-
throw new ApplicationException(appException);
}
- public void handleSystemException(Throwable sysException, Object instance, TransactionContext context) throws org.apache.openejb.ApplicationException, org.apache.openejb.SystemException {
-
+ public void handleSystemException(Throwable sysException, Object instance, TransactionContext context) throws ApplicationException, SystemException {
logSystemException(sysException);
if (context.currentTx != null) markTxRollbackOnly(context.currentTx);
@@ -108,25 +106,6 @@
discardBeanInstance(instance, context.callContext);
throwExceptionToServer(sysException);
-
- }
-
- protected void throwExceptionToServer(Throwable sysException) throws ApplicationException {
-
- RemoteException re = new RemoteException("The bean encountered a non-application exception.", sysException);
-
- throw new InvalidateReferenceException(re);
-
- }
-
- protected void throwTxExceptionToServer(Throwable sysException) throws ApplicationException {
- /* Throw javax.transaction.TransactionRolledbackException to remote client */
-
- String message = "The transaction was rolled back because the bean encountered a non-application exception :" + sysException.getClass().getName() + " : " + sysException.getMessage();
- javax.transaction.TransactionRolledbackException txException = new javax.transaction.TransactionRolledbackException(message);
-
- throw new InvalidateReferenceException(txException);
-
}
}
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java?view=diff&rev=495458&r1=495457&r2=495458
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulContainer.java Thu Jan 11 17:09:42 2007
@@ -21,6 +21,7 @@
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.ProxyInfo;
import org.apache.openejb.ApplicationException;
+import org.apache.openejb.RpcContainer;
import org.apache.openejb.core.Operation;
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.CoreDeploymentInfo;
@@ -33,25 +34,30 @@
import javax.ejb.SessionBean;
import javax.transaction.TransactionManager;
+import javax.transaction.TransactionRequiredException;
import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
+import java.rmi.dgc.VMID;
import java.util.HashMap;
import java.util.Map;
/**
* @org.apache.xbean.XBean element="statefulContainer"
*/
-public class StatefulContainer implements org.apache.openejb.RpcContainer, TransactionContainer {
+public class StatefulContainer implements RpcContainer, TransactionContainer {
+ private static final Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
- private StatefulInstanceManager instanceManager;
+ private final Object containerID;
+ private final TransactionManager transactionManager;
+ private final SecurityService securityService;
+ private final StatefulInstanceManager instanceManager;
+
+ /**
+ * Index used for getDeployments() and getDeploymentInfo(deploymentId).
+ */
+ protected final Map<Object, DeploymentInfo> deploymentsById = new HashMap<Object, DeploymentInfo>();
- private HashMap<String,CoreDeploymentInfo> deploymentRegistry = new HashMap<String,CoreDeploymentInfo>();
-
- private Object containerID = null;
-
- final static protected Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
- private TransactionManager transactionManager;
- private SecurityService securityService;
public StatefulContainer(Object id, TransactionManager transactionManager, SecurityService securityService, Class passivator, int timeOut, int poolSize, int bulkPassivate) throws OpenEJBException {
this.containerID = id;
@@ -59,11 +65,6 @@
this.securityService = securityService;
instanceManager = new StatefulInstanceManager(transactionManager, securityService, passivator, timeOut, poolSize, bulkPassivate);
-
- for (CoreDeploymentInfo deploymentInfo : deploymentRegistry.values()) {
- Map<Method, MethodType> methods = getLifecycelMethodsOfInterface(deploymentInfo);
- deploymentInfo.setContainerData(new Data(new Index(methods)));
- }
}
private class Data {
@@ -79,7 +80,7 @@
}
private Map<Method, MethodType> getLifecycelMethodsOfInterface(CoreDeploymentInfo deploymentInfo) {
- Map<Method, MethodType> methods = new HashMap();
+ Map<Method, MethodType> methods = new HashMap<Method, MethodType>();
Method preDestroy = deploymentInfo.getPreDestroy();
if (preDestroy != null){
@@ -165,15 +166,7 @@
}
private static enum MethodType {
- CREATE, REMOVE, BUSINESS;
- }
-
- public DeploymentInfo [] deployments() {
- return (DeploymentInfo []) deploymentRegistry.values().toArray(new DeploymentInfo[deploymentRegistry.size()]);
- }
-
- public DeploymentInfo getDeploymentInfo(Object deploymentID) {
- return (DeploymentInfo) deploymentRegistry.get(deploymentID);
+ CREATE, REMOVE, BUSINESS
}
public int getContainerType() {
@@ -184,72 +177,148 @@
return containerID;
}
- public void deploy(Object deploymentID, DeploymentInfo deploymentInfo) throws OpenEJBException {
- deploy(deploymentID, (CoreDeploymentInfo)deploymentInfo);
+ public StatefulInstanceManager getInstanceManager() {
+ return instanceManager;
+ }
+
+ public synchronized DeploymentInfo[] deployments() {
+ return deploymentsById.values().toArray(new DeploymentInfo[deploymentsById.size()]);
}
- private void deploy(Object deploymentID, CoreDeploymentInfo deploymentInfo) throws OpenEJBException {
+ public synchronized DeploymentInfo getDeploymentInfo(Object deploymentID) {
+ return deploymentsById.get(deploymentID);
+ }
+
+ public void deploy(Object deploymentId, DeploymentInfo deploymentInfo) throws OpenEJBException {
+ deploy(deploymentId, (CoreDeploymentInfo)deploymentInfo);
+ }
+
+ private synchronized void deploy(Object deploymentId, CoreDeploymentInfo deploymentInfo) {
Map<Method, MethodType> methods = getLifecycelMethodsOfInterface(deploymentInfo);
- deploymentInfo.setContainerData(new Data(new Index(methods)));
+ deploymentInfo.setContainerData(new Data(new Index<Method,MethodType>(methods)));
- HashMap registry = (HashMap) deploymentRegistry.clone();
- registry.put(deploymentID, deploymentInfo);
- deploymentRegistry = registry;
- CoreDeploymentInfo di = (CoreDeploymentInfo) deploymentInfo;
- di.setContainer(this);
+ deploymentsById.put(deploymentId, deploymentInfo);
+ deploymentInfo.setContainer(this);
}
- public Object invoke(Object deployID, Method callMethod, Object [] args, Object primKey, Object securityIdentity) throws org.apache.openejb.OpenEJBException {
+ public Object invoke(Object deployID, Method callMethod, Object [] args, Object primKey, Object securityIdentity) throws OpenEJBException {
CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) this.getDeploymentInfo(deployID);
- ThreadContext callContext = new ThreadContext(deployInfo, primKey, securityIdentity);
- ThreadContext oldCallContext = ThreadContext.enter(callContext);
+
+ Data data = (Data) deployInfo.getContainerData();
+ MethodType methodType = data.getMethodIndex().get(callMethod);
+ methodType = (methodType != null) ? methodType : MethodType.BUSINESS;
+
+ switch (methodType) {
+ case CREATE:
+ ProxyInfo proxyInfo = createEJBObject(deployInfo, callMethod, args, securityIdentity);
+ return proxyInfo;
+ case REMOVE:
+ removeEJBObject(deployInfo, primKey, callMethod, args, securityIdentity);
+ return null;
+ default:
+ Object value = businessMethod(deployInfo, primKey, callMethod, args, securityIdentity);
+ return value;
+ }
+ }
+
+ protected ProxyInfo createEJBObject(CoreDeploymentInfo deploymentInfo, Method callMethod, Object [] args, Object securityIdentity) throws OpenEJBException {
+ // generate a new primary key
+ Object primaryKey = newPrimaryKey();
+
+ ThreadContext createContext = new ThreadContext(deploymentInfo, primaryKey, securityIdentity);
+ createContext.setCurrentOperation(Operation.OP_CREATE);
+ ThreadContext oldCallContext = ThreadContext.enter(createContext);
try {
- boolean authorized = getSecurityService().isCallerAuthorized(securityIdentity, deployInfo.getAuthorizedRoles(callMethod));
+ checkAuthorization(deploymentInfo, callMethod, securityIdentity);
+
+ // allocate a new instance
+ Object bean = instanceManager.newInstance(primaryKey, deploymentInfo.getBeanClass());
- if (!authorized){
- throw new ApplicationException(new RemoteException("Unauthorized Access by Principal Denied"));
+ // Invoke postConstructs or create(...)
+ if (bean instanceof SessionBean) {
+ Method runMethod = deploymentInfo.getMatchingBeanMethod(callMethod);
+ _invoke(callMethod, runMethod, args, bean, createContext);
+ } else {
+ Method postConstruct = deploymentInfo.getPostConstruct();
+ if (postConstruct != null){
+ _invoke(callMethod, postConstruct, args, bean, createContext);
+ }
}
- Data data = (Data) deployInfo.getContainerData();
- MethodType methodType = data.getMethodIndex().get(callMethod);
- methodType = (methodType != null) ? methodType : MethodType.BUSINESS;
-
- switch (methodType){
- case CREATE: return createEJBObject(callContext.getDeploymentInfo(), callMethod, args, callContext.getSecurityIdentity());
- case REMOVE: removeEJBObject(callMethod, args, callContext); return null;
+
+ instanceManager.poolInstance(primaryKey, bean);
+
+ Class callingClass = callMethod.getDeclaringClass();
+ Class objectInterface = deploymentInfo.getObjectInterface(callingClass);
+ return new ProxyInfo(deploymentInfo, primaryKey, objectInterface, this);
+ } finally {
+ ThreadContext.exit(oldCallContext);
+ }
+ }
+
+ protected Object newPrimaryKey() {
+ return new VMID();
+ }
+
+ protected void removeEJBObject(CoreDeploymentInfo deploymentInfo, Object primKey, Method callMethod, Object[] args, Object securityIdentity) throws OpenEJBException {
+ ThreadContext callContext = new ThreadContext(deploymentInfo, primKey, securityIdentity);
+ ThreadContext oldCallContext = ThreadContext.enter(callContext);
+ try {
+ checkAuthorization(deploymentInfo, callMethod, securityIdentity);
+ try {
+ Object bean = instanceManager.obtainInstance(primKey, callContext);
+ if (bean != null) {
+ callContext.setCurrentOperation(Operation.OP_REMOVE);
+ Method preDestroy = callContext.getDeploymentInfo().getPreDestroy();
+ if (preDestroy != null) {
+ _invoke(callMethod, preDestroy, null, bean, callContext);
+ }
+ }
+ } finally {
+ instanceManager.freeInstance(callContext.getPrimaryKey());
}
+ } finally {
+ ThreadContext.exit(oldCallContext);
+ }
+ }
+
+ private Object businessMethod(CoreDeploymentInfo deploymentInfo, Object primKey, Method callMethod, Object[] args, Object securityIdentity) throws OpenEJBException {
+ ThreadContext callContext = new ThreadContext(deploymentInfo, primKey, securityIdentity);
+ ThreadContext oldCallContext = ThreadContext.enter(callContext);
+ try {
+ checkAuthorization(deploymentInfo, callMethod, securityIdentity);
Object bean = instanceManager.obtainInstance(primKey, callContext);
callContext.setCurrentOperation(Operation.OP_BUSINESS);
Object returnValue = null;
- Method runMethod = deployInfo.getMatchingBeanMethod(callMethod);
+ Method runMethod = deploymentInfo.getMatchingBeanMethod(callMethod);
returnValue = _invoke(callMethod, runMethod, args, bean, callContext);
instanceManager.poolInstance(primKey, bean);
return returnValue;
-
} finally {
ThreadContext.exit(oldCallContext);
}
}
- private SecurityService getSecurityService() {
- return securityService;
+ private void checkAuthorization(CoreDeploymentInfo deployInfo, Method callMethod, Object securityIdentity) throws ApplicationException {
+ boolean authorized = securityService.isCallerAuthorized(securityIdentity, deployInfo.getAuthorizedRoles(callMethod));
+ if (!authorized) {
+ throw new ApplicationException(new RemoteException("Unauthorized Access by Principal Denied"));
+ }
}
- protected Object _invoke(Method callMethod, Method runMethod, Object [] args, Object bean, ThreadContext callContext)
- throws org.apache.openejb.OpenEJBException {
+ protected Object _invoke(Method callMethod, Method runMethod, Object [] args, Object bean, ThreadContext callContext) throws OpenEJBException {
TransactionPolicy txPolicy = callContext.getDeploymentInfo().getTransactionPolicy(callMethod);
- TransactionContext txContext = new TransactionContext(callContext, getTransactionManager());
- txContext.context.put(StatefulInstanceManager.class, instanceManager);
+ TransactionContext txContext = new TransactionContext(callContext, transactionManager);
try {
txPolicy.beforeInvoke(bean, txContext);
- } catch (org.apache.openejb.ApplicationException e) {
- if (e.getRootCause() instanceof javax.transaction.TransactionRequiredException ||
- e.getRootCause() instanceof java.rmi.RemoteException) {
+ } catch (ApplicationException e) {
+ if (e.getRootCause() instanceof TransactionRequiredException ||
+ e.getRootCause() instanceof RemoteException) {
instanceManager.poolInstance(callContext.getPrimaryKey(), bean);
}
@@ -259,7 +328,7 @@
Object returnValue = null;
try {
returnValue = runMethod.invoke(bean, args);
- } catch (java.lang.reflect.InvocationTargetException ite) {// handle enterprise bean exception
+ } catch (InvocationTargetException ite) {// handle enterprise bean exception
if (ite.getTargetException() instanceof RuntimeException) {
/* System Exception ****************************/
@@ -288,69 +357,6 @@
}
return returnValue;
- }
-
- private TransactionManager getTransactionManager() {
- return transactionManager;
- }
-
- public StatefulInstanceManager getInstanceManager() {
- return instanceManager;
- }
-
- protected void removeEJBObject(Method callMethod, Object [] args, ThreadContext callContext)
- throws org.apache.openejb.OpenEJBException {
-
- try {
- Object bean = instanceManager.obtainInstance(callContext.getPrimaryKey(), callContext);
- if (bean != null) {
- callContext.setCurrentOperation(Operation.OP_REMOVE);
- Method preDestroy = callContext.getDeploymentInfo().getPreDestroy();
- if (preDestroy != null) {
- _invoke(callMethod, preDestroy, null, bean, callContext);
- }
- }
- } finally {
- instanceManager.freeInstance(callContext.getPrimaryKey());
- }
-
- }
-
- protected ProxyInfo createEJBObject(CoreDeploymentInfo deploymentInfo, Method callMethod, Object [] args, Object securityIdentity) throws OpenEJBException {
- // generate a new primary key
- Object primaryKey = newPrimaryKey();
-
- ThreadContext createContext = new ThreadContext(deploymentInfo, primaryKey, securityIdentity);
- createContext.setCurrentOperation(Operation.OP_CREATE);
- ThreadContext oldContext = ThreadContext.enter(createContext);
- try {
- // allocate a new instance
- Object bean = instanceManager.newInstance(primaryKey, deploymentInfo.getBeanClass());
-
- // Invoke postConstructs or create(...)
- if (bean instanceof SessionBean) {
- Method runMethod = deploymentInfo.getMatchingBeanMethod(callMethod);
- _invoke(callMethod, runMethod, args, bean, createContext);
- } else {
- Method postConstruct = deploymentInfo.getPostConstruct();
- if (postConstruct != null){
- _invoke(callMethod, postConstruct, args, bean, createContext);
- }
- }
-
-
- instanceManager.poolInstance(primaryKey, bean);
-
- Class callingClass = callMethod.getDeclaringClass();
- Class objectInterface = deploymentInfo.getObjectInterface(callingClass);
- return new ProxyInfo(deploymentInfo, primaryKey, objectInterface, this);
- } finally {
- ThreadContext.exit(oldContext);
- }
- }
-
- protected Object newPrimaryKey() {
- return new java.rmi.dgc.VMID();
}
public void discardInstance(Object bean, ThreadContext threadContext) {
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java?view=diff&rev=495458&r1=495457&r2=495458
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateful/StatefulInstanceManager.java Thu Jan 11 17:09:42 2007
@@ -16,58 +16,57 @@
*/
package org.apache.openejb.core.stateful;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.rmi.NoSuchObjectException;
+import java.rmi.RemoteException;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import javax.ejb.EJBException;
+import javax.ejb.SessionContext;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionRolledbackException;
+
import org.apache.openejb.ApplicationException;
+import org.apache.openejb.Injection;
import org.apache.openejb.InvalidateReferenceException;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.SystemException;
-import org.apache.openejb.Injection;
import org.apache.openejb.core.CoreDeploymentInfo;
import org.apache.openejb.core.Operation;
import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.core.ivm.IntraVmCopyMonitor;
import org.apache.openejb.spi.SecurityService;
import org.apache.openejb.util.Logger;
-import org.apache.openejb.util.SafeToolkit;
import org.apache.xbean.recipe.ObjectRecipe;
-import org.apache.xbean.recipe.StaticRecipe;
import org.apache.xbean.recipe.Option;
-
-import javax.ejb.EJBException;
-import javax.ejb.SessionContext;
-import javax.transaction.Status;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import javax.transaction.TransactionRolledbackException;
-import javax.naming.Context;
-import javax.naming.NamingException;
-import java.rmi.RemoteException;
-import java.rmi.NoSuchObjectException;
-import java.util.Hashtable;
-import java.util.LinkedList;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
+import org.apache.xbean.recipe.StaticRecipe;
public class StatefulInstanceManager {
+ public static final Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
- private long timeOut = 0;
+ private final long timeOut;
- private Hashtable beanIndex = new Hashtable();
+ private final Hashtable<Object, BeanEntry> beanIndex = new Hashtable<Object, BeanEntry>();
- private BeanEntryQue lruQue;// que of beans for LRU algorithm
+ // queue of beans for LRU algorithm
+ private final BeanEntryQueue lruQueue;
- private PassivationStrategy passivator;
+ private final PassivationStrategy passivator;
- private int bulkPassivationSize = 100;
+ private final int bulkPassivationSize;
- private SafeToolkit toolkit = SafeToolkit.getToolkit("StatefulInstanceManager");
- private TransactionManager transactionManager;
- private SecurityService securityService;
+ private final TransactionManager transactionManager;
+ private final SecurityService securityService;
public StatefulInstanceManager(TransactionManager transactionManager, SecurityService securityService, Class passivatorClass, int timeout, int poolSize, int bulkPassivate) throws OpenEJBException {
this.transactionManager = transactionManager;
this.securityService = securityService;
- this.lruQue = new BeanEntryQue(poolSize);
- if (poolSize == 0){
+ this.lruQueue = new BeanEntryQueue(poolSize);
+ if (poolSize == 0) {
this.bulkPassivationSize = 1;
} else {
this.bulkPassivationSize = Math.min(bulkPassivate, poolSize);
@@ -80,30 +79,24 @@
} catch (Exception e) {
throw new OpenEJBException("Could not create the passivator " + passivatorClass.getName(), e);
}
-
}
- public Object getAncillaryState(Object primaryKey) throws OpenEJBException {
- return this.getBeanEntry(primaryKey).ancillaryState;
+ public Transaction getBeanTransaction(Object primaryKey) throws OpenEJBException {
+ BeanEntry entry = getBeanEntry(primaryKey);
+ return entry.beanTransaction;
}
- public void setAncillaryState(Object primaryKey, Object ancillaryState) throws OpenEJBException {
+ public void setBeanTransaction(Object primaryKey, Transaction beanTransaction) throws OpenEJBException {
BeanEntry entry = getBeanEntry(primaryKey);
- entry.ancillaryState = ancillaryState;
- if (ancillaryState instanceof javax.transaction.Transaction){
- entry.transaction = (javax.transaction.Transaction) ancillaryState;
- }
-
+ entry.beanTransaction = beanTransaction;
}
public Object newInstance(Object primaryKey, Class beanClass) throws OpenEJBException {
Object bean = null;
-
ThreadContext threadContext = ThreadContext.getThreadContext();
Operation currentOperation = threadContext.getCurrentOperation();
threadContext.setCurrentOperation(Operation.OP_SET_CONTEXT);
-
try {
ObjectRecipe objectRecipe = new ObjectRecipe(beanClass);
objectRecipe.allow(Option.FIELD_INJECTION);
@@ -119,7 +112,7 @@
Object object = ctx.lookup("java:comp/env/" + jndiName);
objectRecipe.setProperty(injection.getName(), new StaticRecipe(object));
} catch (NamingException e) {
- logger.warning("Injection data not found in enc: jndiName='"+injection.getJndiName()+"', target="+injection.getTarget()+"/"+injection.getName());
+ logger.warning("Injection data not found in enc: jndiName='" + injection.getJndiName() + "', target=" + injection.getTarget() + "/" + injection.getName());
}
}
@@ -140,15 +133,15 @@
threadContext.setCurrentOperation(currentOperation);
}
- BeanEntry entry = new BeanEntry(bean, primaryKey, null, timeOut);
-
+ // add to index
+ BeanEntry entry = new BeanEntry(bean, primaryKey, timeOut);
beanIndex.put(primaryKey, entry);
- return entry.bean;
+ return bean;
}
private SessionContext createSessionContext() {
- return (SessionContext) new StatefulContext(transactionManager, securityService);
+ return new StatefulContext(transactionManager, securityService);
}
public Object obtainInstance(Object primaryKey, ThreadContext callContext) throws OpenEJBException {
@@ -156,103 +149,95 @@
throw new SystemException(new NullPointerException("Cannot obtain an instance of the stateful session bean with a null session id"));
}
- BeanEntry entry = (BeanEntry) beanIndex.get(primaryKey);
- if (entry == null) {
+ // look for entry in index
+ BeanEntry entry = beanIndex.get(primaryKey);
- entry = activate(primaryKey);
- if (entry != null) {
-
- if (entry.isTimedOut()) {
- /* Since the bean instance hasn't had its ejbActivate() method called yet,
- it is still considered to be passivated at this point. Instances that timeout
- while passivated must be evicted WITHOUT having their ejbRemove()
- method invoked. Section 6.6 of EJB 1.1 specification.
- */
- throw new InvalidateReferenceException(new NoSuchObjectException("Timed Out"));
- }
-
- Operation currentOperation = callContext.getCurrentOperation();
- callContext.setCurrentOperation(Operation.OP_ACTIVATE);
+ // if we didn't find the bean in the index, try to activate it
+ if (entry == null) {
+ Object bean = activateInstance(primaryKey, callContext);
+ return bean;
+ }
- try {
- Method postActivate = callContext.getDeploymentInfo().getPostActivate();
- if (postActivate != null){
- try {
- postActivate.invoke(entry.bean);
- } catch (InvocationTargetException e) {
- throw e.getTargetException();
- }
- }
- } catch (Throwable callbackException) {
- /*
- In the event of an exception, OpenEJB is required to log the exception, evict the instance,
- and mark the transaction for rollback. If there is a transaction to rollback, then the a
- javax.transaction.TransactionRolledbackException must be throw to the client. Otherwise a
- java.rmi.RemoteException is thrown to the client.
- See EJB 1.1 specification, section 12.3.2
- */
- handleCallbackException(callbackException, entry.bean, callContext, "ejbActivate");
- } finally {
- callContext.setCurrentOperation(currentOperation);
- }
+ // if the bean is already in a transaction, just return it
+ if (entry.beanTransaction != null) {
+ return entry.bean;
+ }
- beanIndex.put(primaryKey, entry);
- return entry.bean;
- } else {
- throw new InvalidateReferenceException(new NoSuchObjectException("Not Found"));
+ // remove from the queue so it is not passivated while in use
+ BeanEntry queueEntry = lruQueue.remove(entry);
+ if (queueEntry != null) {
+ // if bean is timed out, destroy it
+ if (entry.isTimedOut()) {
+ entry = beanIndex.remove(entry.primaryKey);
+ handleTimeout(entry, callContext);
+ throw new InvalidateReferenceException(new NoSuchObjectException("Stateful SessionBean has timed-out"));
+ }
+ return entry.bean;
+ } else {
+ // if it is not in the queue, the bean is already being invoked
+ // the only reentrant/concurrent operations allowed are Session synchronization callbacks
+ Operation currentOperation = callContext.getCurrentOperation();
+ if (currentOperation != Operation.OP_AFTER_COMPLETION && currentOperation != Operation.OP_BEFORE_COMPLETION) {
+ throw new ApplicationException(new RemoteException("Concurrent calls not allowed"));
}
- } else {// bean has been created and is pooled
- if (entry.transaction != null) {
- try {
- if (entry.transaction.getStatus() == Status.STATUS_ACTIVE) {
+ return entry.bean;
+ }
+ }
-// if(entry.transaction.equals(OpenEJB.getTransactionManager().getTransaction()))
- return entry.bean;
-// else
-// throw new ApplicationException(new javax.transaction.InvalidTransactionException());
- } else {
+ private Object activateInstance(Object primaryKey, ThreadContext callContext) throws SystemException, ApplicationException {
+ // attempt to active a passivated entity
+ BeanEntry entry = activate(primaryKey);
+ if (entry == null) {
+ throw new InvalidateReferenceException(new NoSuchObjectException("Not Found"));
+ }
- entry.transaction = null;
- return entry.bean;
- }
- } catch (javax.transaction.SystemException se) {
- throw new SystemException(se);
- } catch (IllegalStateException ise) {
- throw new SystemException(ise);
- } catch (SecurityException lse) {
- throw new SystemException(lse);
- }
- } else {// bean is pooled in the "method ready" pool.
+ if (entry.isTimedOut()) {
+ // Since the bean instance hasn't had its ejbActivate() method called yet,
+ // it is still considered to be passivated at this point. Instances that timeout
+ // while passivated must be evicted WITHOUT having their ejbRemove()
+ // method invoked. Section 6.6 of EJB 1.1 specification.
+ throw new InvalidateReferenceException(new NoSuchObjectException("Timed Out"));
+ }
- BeanEntry queEntry = lruQue.remove(entry);// remove from Que so its not passivated while in use
- if (queEntry != null) {
- if (entry.isTimedOut()) {
- entry = (BeanEntry) beanIndex.remove(entry.primaryKey);// remove frm index
- handleTimeout(entry, callContext);
- throw new InvalidateReferenceException(new NoSuchObjectException("Stateful SessionBean has timed-out"));
- }
- return entry.bean;
- } else {
- Operation currentOperation = callContext.getCurrentOperation();
- if (currentOperation == Operation.OP_AFTER_COMPLETION || currentOperation == Operation.OP_BEFORE_COMPLETION) {
- return entry.bean;
- } else {
- throw new ApplicationException(new RemoteException("Concurrent calls not allowed"));
- }
+ // call the activate method
+ Operation currentOperation = callContext.getCurrentOperation();
+ callContext.setCurrentOperation(Operation.OP_ACTIVATE);
+ try {
+ Method postActivate = callContext.getDeploymentInfo().getPostActivate();
+ if (postActivate != null) {
+ try {
+ postActivate.invoke(entry.bean);
+ } catch (InvocationTargetException e) {
+ throw e.getTargetException();
}
}
+ } catch (Throwable callbackException) {
+ /*
+ In the event of an exception, OpenEJB is required to log the exception, evict the instance,
+ and mark the transaction for rollback. If there is a transaction to rollback, then the a
+ javax.transaction.TransactionRolledbackException must be throw to the client. Otherwise a
+ java.rmi.RemoteException is thrown to the client.
+ See EJB 1.1 specification, section 12.3.2
+ */
+ handleCallbackException(callbackException, entry.bean, callContext, "ejbActivate");
+ } finally {
+ callContext.setCurrentOperation(currentOperation);
}
+
+ // add it to the index
+ beanIndex.put(primaryKey, entry);
+
+ return entry.bean;
}
protected void handleTimeout(BeanEntry entry, ThreadContext threadContext) {
-
Operation currentOperation = threadContext.getCurrentOperation();
threadContext.setCurrentOperation(Operation.OP_REMOVE);
try {
Method preDestroy = threadContext.getDeploymentInfo().getPreDestroy();
- if (preDestroy != null){
+ if (preDestroy != null) {
try {
preDestroy.invoke(entry.bean);
} catch (InvocationTargetException e) {
@@ -278,49 +263,45 @@
}
public void poolInstance(Object primaryKey, Object bean) throws OpenEJBException {
- if (primaryKey == null || bean == null){
+ if (primaryKey == null || bean == null) {
throw new SystemException("Invalid arguments");
}
- BeanEntry entry = (BeanEntry) beanIndex.get(primaryKey);
+ BeanEntry entry = beanIndex.get(primaryKey);
if (entry == null) {
entry = activate(primaryKey);
if (entry == null) {
throw new SystemException("Invalid primaryKey:" + primaryKey);
}
- } else if (entry.bean != bean){
+ } else if (entry.bean != bean) {
throw new SystemException("Invalid ID for bean");
}
- if (entry.transaction != null && entry.transaction == entry.ancillaryState) {
- return;// don't put in LRU (method ready) pool.
- } else {
+ if (entry.beanTransaction == null) {
try {
- entry.transaction = getTransactionManager().getTransaction();
+ entry.beanTransaction = transactionManager.getTransaction();
} catch (javax.transaction.SystemException se) {
throw new SystemException("TransactionManager failure");
}
- if (entry.transaction == null) {// only put in LRU if no current transaction
- lruQue.add(entry);// add it to end of Que; the most reciently used bean
+ // only put in LRU if no current transaction
+ if (entry.beanTransaction == null) {
+ // add it to end of Queue; the most reciently used bean
+ lruQueue.add(entry);
}
}
}
- private TransactionManager getTransactionManager() {
- return transactionManager;
- }
-
public Object freeInstance(Object primaryKey) throws SystemException {
BeanEntry entry = null;
- entry = (BeanEntry) beanIndex.remove(primaryKey);// remove frm index
+ entry = beanIndex.remove(primaryKey);// remove frm index
if (entry == null) {
entry = activate(primaryKey);
} else {
- lruQue.remove(entry);
+ lruQueue.remove(entry);
}
- if (entry == null){
+ if (entry == null) {
return null;
}
@@ -329,15 +310,15 @@
protected void passivate() throws SystemException {
final ThreadContext threadContext = ThreadContext.getThreadContext();
- Hashtable stateTable = new Hashtable(bulkPassivationSize);
+ Hashtable<Object, BeanEntry> stateTable = new Hashtable<Object, BeanEntry>(bulkPassivationSize);
BeanEntry currentEntry;
final Operation currentOperation = threadContext.getCurrentOperation();
Method prePassivate = threadContext.getDeploymentInfo().getPrePassivate();
try {
for (int i = 0; i < bulkPassivationSize; ++i) {
- currentEntry = lruQue.first();
- if (currentEntry == null){
+ currentEntry = lruQueue.first();
+ if (currentEntry == null) {
break;
}
beanIndex.remove(currentEntry.primaryKey);
@@ -346,7 +327,7 @@
} else {
threadContext.setCurrentOperation(Operation.OP_PASSIVATE);
try {
- if (prePassivate != null){
+ if (prePassivate != null) {
// TODO Are all beans in the stateTable the same type?
try {
prePassivate.invoke(currentEntry.bean);
@@ -391,10 +372,10 @@
protected InvalidateReferenceException destroy(BeanEntry entry, Exception t) throws SystemException {
beanIndex.remove(entry.primaryKey);// remove frm index
- lruQue.remove(entry);// remove from que
- if (entry.transaction != null) {
+ lruQueue.remove(entry);// remove from queue
+ if (entry.beanTransaction != null) {
try {
- entry.transaction.setRollbackOnly();
+ entry.beanTransaction.setRollbackOnly();
} catch (javax.transaction.SystemException se) {
throw new SystemException(se);
} catch (IllegalStateException ise) {
@@ -403,9 +384,9 @@
throw new SystemException("Container not authorized to rollback tx", lse);
}
return new InvalidateReferenceException(new TransactionRolledbackException(t.getMessage()));
- } else if (t instanceof RemoteException)
+ } else if (t instanceof RemoteException) {
return new InvalidateReferenceException(t);
- else {
+ } else {
EJBException e = (EJBException) t;
return new InvalidateReferenceException(new RemoteException(e.getMessage(), e.getCausedByException()));
}
@@ -416,33 +397,33 @@
if (primaryKey == null) {
throw new SystemException(new NullPointerException("The primary key is null. Cannot get the bean entry"));
}
- BeanEntry entry = (BeanEntry) beanIndex.get(primaryKey);
+ BeanEntry entry = beanIndex.get(primaryKey);
if (entry == null) {
Object bean = this.obtainInstance(primaryKey, ThreadContext.getThreadContext());
this.poolInstance(primaryKey, bean);
- entry = (BeanEntry) beanIndex.get(primaryKey);
+ entry = beanIndex.get(primaryKey);
}
return entry;
}
- class BeanEntryQue {
- private final LinkedList list;
+ class BeanEntryQueue {
+ private final LinkedList<BeanEntry> list;
private final int capacity;
- protected BeanEntryQue(int preferedCapacity) {
+ protected BeanEntryQueue(int preferedCapacity) {
capacity = preferedCapacity;
- list = new LinkedList();
+ list = new LinkedList<BeanEntry>();
}
protected synchronized BeanEntry first() {
- return (BeanEntry) list.removeFirst();
+ return list.removeFirst();
}
protected synchronized void add(BeanEntry entry) throws SystemException {
entry.resetTimeOut();
list.addLast(entry);
- entry.inQue = true;
+ entry.inQueue = true;
if (list.size() >= capacity) {// is the LRU QUE full?
passivate();
@@ -450,10 +431,11 @@
}
protected synchronized BeanEntry remove(BeanEntry entry) {
- if (!entry.inQue)
+ if (!entry.inQueue) {
return null;
- if (list.remove(entry) == true) {
- entry.inQue = false;
+ }
+ if (list.remove(entry)) {
+ entry.inQueue = false;
return entry;
} else {
@@ -462,7 +444,6 @@
}
}
- public Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
protected void handleCallbackException(Throwable e, Object instance, ThreadContext callContext, String callBack) throws ApplicationException, SystemException {
@@ -475,11 +456,13 @@
/* [2] If the instance is in a transaction, mark the transaction for rollback. */
Transaction transaction = null;
try {
- transaction = getTransactionManager().getTransaction();
+ transaction = transactionManager.getTransaction();
} catch (Throwable t) {
logger.error("Could not retreive the current transaction from the transaction manager while handling a callback exception from the " + callBack + " method of bean " + callContext.getPrimaryKey());
}
- if (transaction != null) markTxRollbackOnly(transaction);
+ if (transaction != null) {
+ markTxRollbackOnly(transaction);
+ }
/* [3] Discard the instance */
freeInstance(callContext.getPrimaryKey());
@@ -495,7 +478,9 @@
protected void markTxRollbackOnly(Transaction tx) throws SystemException {
try {
- if (tx != null) tx.setRollbackOnly();
+ if (tx != null) {
+ tx.setRollbackOnly();
+ }
} catch (javax.transaction.SystemException se) {
throw new SystemException(se);
}
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/transaction/TransactionContext.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/transaction/TransactionContext.java?view=diff&rev=495458&r1=495457&r2=495458
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/transaction/TransactionContext.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/transaction/TransactionContext.java Thu Jan 11 17:09:42 2007
@@ -21,15 +21,10 @@
import org.apache.openejb.core.ThreadContext;
-import java.util.Map;
-import java.util.HashMap;
-
public class TransactionContext {
-
public Transaction clientTx;
public Transaction currentTx;
public ThreadContext callContext;
- public final Map context = new HashMap();
private final TransactionManager transactionManager;