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/03/14 21:04:14 UTC
svn commit: r518297 - in
/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb:
EndpointFactory.java EndpointHandler.java MdbContainer.java
MdbInstanceFactory.java
Author: dain
Date: Wed Mar 14 13:04:13 2007
New Revision: 518297
URL: http://svn.apache.org/viewvc?view=rev&rev=518297
Log:
Added support for generalized invoke on MdbContainer so EJB timers can work
MdbContainer now actually frees instances when release is called
Deployment specific MdbContainer data is now stored in deployment.containerData
Modified:
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointFactory.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointHandler.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceFactory.java
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointFactory.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointFactory.java?view=diff&rev=518297&r1=518296&r2=518297
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointFactory.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointFactory.java Wed Mar 14 13:04:13 2007
@@ -18,6 +18,7 @@
package org.apache.openejb.core.mdb;
import org.apache.openejb.DeploymentInfo;
+import org.apache.openejb.core.CoreDeploymentInfo;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.ActivationSpec;
@@ -30,12 +31,12 @@
public class EndpointFactory implements MessageEndpointFactory {
private final ActivationSpec activationSpec;
private final MdbContainer container;
- private final DeploymentInfo deploymentInfo;
+ private final CoreDeploymentInfo deploymentInfo;
private final MdbInstanceFactory instanceFactory;
private final ClassLoader classLoader;
private final Class[] interfaces;
- public EndpointFactory(ActivationSpec activationSpec, MdbContainer container, DeploymentInfo deploymentInfo, MdbInstanceFactory instanceFactory) {
+ public EndpointFactory(ActivationSpec activationSpec, MdbContainer container, CoreDeploymentInfo deploymentInfo, MdbInstanceFactory instanceFactory) {
this.activationSpec = activationSpec;
this.container = container;
this.deploymentInfo = deploymentInfo;
@@ -46,6 +47,10 @@
public ActivationSpec getActivationSpec() {
return activationSpec;
+ }
+
+ public MdbInstanceFactory getInstanceFactory() {
+ return instanceFactory;
}
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException {
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointHandler.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointHandler.java?view=diff&rev=518297&r1=518296&r2=518297
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointHandler.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointHandler.java Wed Mar 14 13:04:13 2007
@@ -18,8 +18,8 @@
package org.apache.openejb.core.mdb;
import org.apache.openejb.ApplicationException;
-import org.apache.openejb.DeploymentInfo;
import org.apache.openejb.SystemException;
+import org.apache.openejb.core.CoreDeploymentInfo;
import javax.ejb.EJBException;
import javax.resource.spi.ApplicationServerInternalException;
@@ -63,19 +63,19 @@
}
private final MdbContainer container;
- private final DeploymentInfo deployment;
+ private final CoreDeploymentInfo deployment;
private final MdbInstanceFactory instanceFactory;
private final XAResource xaResource;
private State state = State.NONE;
private Object instance;
- public EndpointHandler(MdbContainer container, DeploymentInfo deployment, MdbInstanceFactory instanceFactory, XAResource xaResource) throws UnavailableException {
+ public EndpointHandler(MdbContainer container, CoreDeploymentInfo deployment, MdbInstanceFactory instanceFactory, XAResource xaResource) throws UnavailableException {
this.container = container;
this.deployment = deployment;
this.instanceFactory = instanceFactory;
this.xaResource = xaResource;
- instance = instanceFactory.createInstance();
+ instance = instanceFactory.createInstance(false);
}
// private static void logTx() {
@@ -186,7 +186,7 @@
// call beforeDelivery on the container
try {
- container.beforeDelivery(deployment.getDeploymentID(), instance, method, xaResource);
+ container.beforeDelivery(deployment, instance, method, xaResource);
} catch (SystemException se) {
Throwable throwable = (se.getRootCause() != null) ? se.getRootCause() : se;
throw new ApplicationServerInternalException(throwable);
@@ -306,9 +306,9 @@
// notify the container
try {
- container.release(instance);
+ container.release(deployment, instance);
} finally {
- instanceFactory.freeInstance(instance);
+ instanceFactory.freeInstance(instance, false);
instance = null;
}
}
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java?view=diff&rev=518297&r1=518296&r2=518297
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java Wed Mar 14 13:04:13 2007
@@ -39,11 +39,13 @@
import javax.transaction.xa.XAResource;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ActivationSpec;
+import javax.resource.spi.UnavailableException;
import javax.resource.ResourceException;
import java.lang.reflect.Method;
-import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
public class MdbContainer implements RpcContainer, TransactionContainer {
private static final Logger logger = Logger.getInstance("OpenEJB", "org.apache.openejb.util.resources");
@@ -57,8 +59,7 @@
private final Class activationSpecClass;
private final int instanceLimit;
- private final Map<Object, DeploymentInfo> deployments = new HashMap<Object, DeploymentInfo>();
- private final Map<Object, EndpointFactory> endpointFactories = new HashMap<Object, EndpointFactory>();
+ private final ConcurrentMap<Object, CoreDeploymentInfo> deployments = new ConcurrentHashMap<Object, CoreDeploymentInfo>();
public MdbContainer(Object containerID, TransactionManager transactionManager, SecurityService securityService, ResourceAdapter resourceAdapter, Class messageListenerInterface, Class activationSpecClass, int instanceLimit) {
this.containerID = containerID;
@@ -70,11 +71,11 @@
this.instanceLimit = instanceLimit;
}
- public synchronized DeploymentInfo [] deployments() {
+ public DeploymentInfo [] deployments() {
return deployments.values().toArray(new DeploymentInfo[deployments.size()]);
}
- public synchronized DeploymentInfo getDeploymentInfo(Object deploymentID) {
+ public DeploymentInfo getDeploymentInfo(Object deploymentID) {
return deployments.get(deploymentID);
}
@@ -86,7 +87,8 @@
return containerID;
}
- public void deploy(DeploymentInfo deploymentInfo) throws OpenEJBException {
+ public void deploy(DeploymentInfo info) throws OpenEJBException {
+ CoreDeploymentInfo deploymentInfo = (CoreDeploymentInfo) info;
Object deploymentId = deploymentInfo.getDeploymentID();
if (!deploymentInfo.getMdbInterface().equals(messageListenerInterface)) {
throw new OpenEJBException("Deployment '" + deploymentId + "' has message listener interface " +
@@ -98,31 +100,26 @@
ActivationSpec activationSpec = createActivationSpec(deploymentInfo);
// create the message endpoint
- MdbInstanceFactory instanceFactory = new MdbInstanceFactory((CoreDeploymentInfo) deploymentInfo, transactionManager, securityService, instanceLimit);
+ MdbInstanceFactory instanceFactory = new MdbInstanceFactory(deploymentInfo, transactionManager, securityService, instanceLimit);
EndpointFactory endpointFactory = new EndpointFactory(activationSpec, this, deploymentInfo, instanceFactory);
// update the data structures
// this must be done before activating the endpoint since the ra may immedately begin delivering messages
- synchronized (this) {
- deploymentInfo.setContainer(this);
- deployments.put(deploymentId, deploymentInfo);
- endpointFactories.put(deploymentId, endpointFactory);
- }
+ deploymentInfo.setContainer(this);
+ deploymentInfo.setContainerData(endpointFactory);
+ deployments.put(deploymentId, deploymentInfo);
// activate the endpoint
try {
resourceAdapter.endpointActivation(endpointFactory, activationSpec);
} catch (ResourceException e) {
// activation failed... clean up
- synchronized (this) {
- deploymentInfo.setContainer(null);
- deployments.remove(deploymentId);
- endpointFactories.remove(deploymentId);
- }
+ deploymentInfo.setContainer(null);
+ deploymentInfo.setContainerData(null);
+ deployments.remove(deploymentId);
throw new OpenEJBException(e);
}
-
}
private ActivationSpec createActivationSpec(DeploymentInfo deploymentInfo)throws OpenEJBException {
@@ -151,36 +148,67 @@
}
}
- public void undeploy(DeploymentInfo deploymentInfo) throws OpenEJBException {
- Object deploymentId = deploymentInfo.getDeploymentID();
- undeploy(deploymentId);
- }
+ public void undeploy(DeploymentInfo info) throws OpenEJBException {
+ if (!(info instanceof CoreDeploymentInfo)) {
+ return;
+ }
- public void undeploy(Object deploymentId) throws OpenEJBException {
+ CoreDeploymentInfo deploymentInfo = (CoreDeploymentInfo) info;
try {
- EndpointFactory endpointFactory;
- synchronized (this) {
- endpointFactory = endpointFactories.get(deploymentId);
- }
+ EndpointFactory endpointFactory = (EndpointFactory) deploymentInfo.getContainerData();
if (endpointFactory != null) {
resourceAdapter.endpointDeactivation(endpointFactory, endpointFactory.getActivationSpec());
}
} finally {
- synchronized (this) {
- endpointFactories.remove(deploymentId);
- DeploymentInfo deploymentInfo = deployments.remove(deploymentId);
- if (deploymentInfo != null) {
- deploymentInfo.setContainer(null);
- }
- }
+ deploymentInfo.setContainer(null);
+ deploymentInfo.setContainerData(null);
+ deployments.remove(deploymentInfo.getDeploymentID());
}
}
- public void beforeDelivery(Object deployId, Object instance, Method method, XAResource xaResource) throws SystemException {
+ public Object invoke(Object deploymentId, Method method, Object[] args, Object primKey, Object securityIdentity) throws OpenEJBException {
// get the target deployment (MDB)
- CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) getDeploymentInfo(deployId);
- if (deployInfo == null) throw new SystemException("Unknown deployment " + deployId);
+ CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) getDeploymentInfo(deploymentId);
+ if (deployInfo == null) throw new SystemException("Unknown deployment " + deploymentId);
+
+ // create instance
+ Object instance = null;
+ try {
+ EndpointFactory endpointFactory = (EndpointFactory) deployInfo.getContainerData();
+ instance = endpointFactory.getInstanceFactory().createInstance(true);
+ } catch (UnavailableException e) {
+ throw new SystemException("Unable to create new MDB instance: ", e);
+ }
+
+ try {
+ // before
+ beforeDelivery(deployInfo, instance, method, null);
+ boolean exceptionThrown = false;
+ try {
+ // deliver the message
+ return invoke(instance, method, args);
+ } catch (OpenEJBException e) {
+ exceptionThrown = true;
+ throw e;
+ } finally {
+ try {
+ // after
+ afterDelivery(instance);
+ } catch (SystemException e) {
+ if (!exceptionThrown) {
+ //noinspection ThrowFromFinallyBlock
+ throw e;
+ }
+ logger.error("Unexpected exception from afterDelivery");
+ }
+ }
+ } finally {
+ release(deployInfo, instance);
+ }
+ }
+
+ public void beforeDelivery(CoreDeploymentInfo deployInfo, Object instance, Method method, XAResource xaResource) throws SystemException {
// intialize call context
ThreadContext callContext = new ThreadContext(deployInfo, null, null);
ThreadContext oldContext = ThreadContext.enter(callContext);
@@ -198,39 +226,26 @@
// call the tx before method
try {
mdbCallContext.txPolicy.beforeInvoke(instance, mdbCallContext.txContext);
- enlistResource(xaResource);
+
+ // enrole the xaresource in the transaction
+ if (xaResource != null) {
+ Transaction transaction = transactionManager.getTransaction();
+ if (transaction != null) {
+ transaction.enlistResource(xaResource);
+ }
+ }
} catch (ApplicationException e) {
ThreadContext.exit(oldContext);
throw new SystemException("Should never get an Application exception", e);
} catch (SystemException e) {
ThreadContext.exit(oldContext);
throw e;
- }
- }
-
- private void enlistResource(XAResource xaResource) throws SystemException {
- if (xaResource == null) return;
-
- try {
- Transaction transaction = transactionManager.getTransaction();
- if (transaction != null) {
- transaction.enlistResource(xaResource);
- }
} catch (Exception e) {
+ ThreadContext.exit(oldContext);
throw new SystemException("Unable to enlist xa resource in the transaction", e);
}
}
- public Object invoke(Object deploymentId, Method method, Object[] args, Object primKey, Object securityIdentity) throws OpenEJBException {
- // this method can only be used for ejbTimeout
- DeploymentInfo deploymentInfo = deployments.get(deploymentId);
- if (!method.equals(deploymentInfo.getEjbTimeout())) {
- throw new OpenEJBException("RpcContainer invoke method of MdbContainer can only be used to ejbTimeout invocations");
- }
- // todo create an instance and invoke the method and destroy instance
- return null;
- }
-
public Object invoke(Object instance, Method method, Object... args) throws SystemException, ApplicationException {
if (args == null) {
args = NO_ARGS;
@@ -332,23 +347,30 @@
}
}
- public void release(Object instance) {
+ public void release(CoreDeploymentInfo deployInfo, Object instance) {
// get the mdb call context
ThreadContext callContext = ThreadContext.getThreadContext();
- MdbCallContext mdbCallContext = callContext.get(MdbCallContext.class);
+ if (callContext == null) {
+ callContext = new ThreadContext(deployInfo, null, null);
+ ThreadContext.enter(callContext);
+
+ }
// if we have an mdb call context we need to invoke the after invoke method
+ MdbCallContext mdbCallContext = callContext.get(MdbCallContext.class);
if (mdbCallContext != null) {
try {
mdbCallContext.txPolicy.afterInvoke(instance, mdbCallContext.txContext);
} catch (Exception e) {
logger.error("error while releasing message endpoint", e);
} finally {
+ EndpointFactory endpointFactory = (EndpointFactory) deployInfo.getContainerData();
+ endpointFactory.getInstanceFactory().freeInstance(instance, false);
ThreadContext.exit(mdbCallContext.oldCallContext);
}
}
- }
+ }
private static class MdbCallContext {
private Method deliveryMethod;
@@ -358,6 +380,5 @@
}
public void discardInstance(Object instance, ThreadContext context) {
- // TODO Auto-generated method stub
}
}
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceFactory.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceFactory.java?view=diff&rev=518297&r1=518296&r2=518297
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceFactory.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbInstanceFactory.java Wed Mar 14 13:04:13 2007
@@ -31,7 +31,6 @@
import org.apache.xbean.recipe.ConstructionException;
import javax.ejb.MessageDrivenBean;
-import javax.ejb.SessionBean;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.resource.spi.UnavailableException;
@@ -96,15 +95,18 @@
* @return a new message driven bean instance
* @throws UnavailableException if the instance limit has been exceeded or
* if an exception occurs while creating the bean instance
+ * @param ignoreInstanceCount
*/
- public Object createInstance() throws UnavailableException {
- synchronized (this) {
- // check the instance limit
- if (instanceLimit > 0 && instanceCount >= instanceLimit) {
- throw new UnavailableException("Only " + instanceLimit + " instances can be created");
+ public Object createInstance(boolean ignoreInstanceCount) throws UnavailableException {
+ if (!ignoreInstanceCount) {
+ synchronized (this) {
+ // check the instance limit
+ if (instanceLimit > 0 && instanceCount >= instanceLimit) {
+ throw new UnavailableException("Only " + instanceLimit + " instances can be created");
+ }
+ // increment the instance count
+ instanceCount++;
}
- // increment the instance count
- instanceCount++;
}
try {
@@ -112,8 +114,10 @@
return bean;
} catch (UnavailableException e) {
// decrement the instance count
- synchronized (this) {
- instanceCount--;
+ if (!ignoreInstanceCount) {
+ synchronized (this) {
+ instanceCount--;
+ }
}
throw e;
@@ -125,13 +129,16 @@
* callbacks and decrements the instance count. This method should not be used to disposed of beans that have
* thrown a system exception. Instead the discardInstance method should be called.
* @param bean the bean instance to free
+ * @param ignoredInstanceCount
*/
- public void freeInstance(Object bean) {
+ public void freeInstance(Object bean, boolean ignoredInstanceCount) {
if (bean == null) throw new NullPointerException("bean is null");
// decrement the instance count
- synchronized (this) {
- instanceCount--;
+ if (!ignoredInstanceCount) {
+ synchronized (this) {
+ instanceCount--;
+ }
}
ThreadContext callContext = ThreadContext.getThreadContext();