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 2006/11/30 18:37:38 UTC
svn commit: r481006 - in
/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb:
./ core/ core/mdb/
Author: dain
Date: Thu Nov 30 09:37:34 2006
New Revision: 481006
URL: http://svn.apache.org/viewvc?view=rev&rev=481006
Log:
Coppied and updated MDB container from openejb2
Added:
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/
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
Modified:
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java
incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java?view=diff&rev=481006&r1=481005&r2=481006
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java Thu Nov 30 09:37:34 2006
@@ -71,6 +71,10 @@
Class getInterface(InterfaceType interfaceType);
+ Class getMdbInterface();
+
+ ClassLoader getClassLoader();
+
public interface BusinessLocalHome extends javax.ejb.EJBLocalHome {
Object create();
}
Modified: incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java
URL: http://svn.apache.org/viewvc/incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java?view=diff&rev=481006&r1=481005&r2=481006
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java (original)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java Thu Nov 30 09:37:34 2006
@@ -31,6 +31,7 @@
import javax.ejb.SessionSynchronization;
import javax.ejb.EnterpriseBean;
import javax.ejb.SessionBean;
+import javax.ejb.MessageDrivenBean;
import org.apache.openejb.Container;
import org.apache.openejb.RpcContainer;
@@ -74,6 +75,7 @@
private Class pkClass;
private Class businessLocal;
private Class businessRemote;
+ private Class mdbInterface;
private Method postConstruct;
private Method preDestroy;
@@ -171,6 +173,22 @@
}
}
+ public CoreDeploymentInfo(DeploymentContext context, Class beanClass, Class mdbInterface) throws SystemException {
+ this.context = context;
+ this.beanClass = beanClass;
+ this.mdbInterface = mdbInterface;
+ this.componentType = BeanType.MESSAGE_DRIVEN;
+
+ if (MessageDrivenBean.class.isAssignableFrom(beanClass)){
+ try {
+ this.preDestroy = MessageDrivenBean.class.getMethod("ejbRemove");
+ } catch (NoSuchMethodException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ createMethodMap();
+ }
+
public Object getContainerData() {
return containerData;
}
@@ -285,6 +303,10 @@
return businessRemote;
}
+ public Class getMdbInterface() {
+ return mdbInterface;
+ }
+
public Class getPrimaryKeyClass() {
return pkClass;
}
@@ -337,6 +359,10 @@
return context.getJndiContext();
}
+ public ClassLoader getClassLoader() {
+ return context.getClassLoader();
+ }
+
public boolean isReentrant() {
return isReentrant;
}
@@ -593,6 +619,9 @@
throw new org.apache.openejb.SystemException(nsme);
}
+ if (mdbInterface != null) {
+ mapObjectInterface(mdbInterface);
+ }
}
private void mapHomeInterface(Class intrface) {
Added: 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=auto&rev=481006
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointFactory.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointFactory.java Thu Nov 30 09:37:34 2006
@@ -0,0 +1,52 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.core.mdb;
+
+import org.apache.openejb.DeploymentInfo;
+
+import javax.resource.spi.UnavailableException;
+import javax.resource.spi.endpoint.MessageEndpoint;
+import javax.resource.spi.endpoint.MessageEndpointFactory;
+import javax.transaction.xa.XAResource;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+public class EndpointFactory implements MessageEndpointFactory {
+ private final MdbContainer mdbContainer;
+ private final DeploymentInfo deploymentInfo;
+ private final ClassLoader classLoader;
+ private final Class[] interfaces;
+
+ public EndpointFactory(MdbContainer mdbContainer, DeploymentInfo mdbDeploymentInfo) {
+ this.mdbContainer = mdbContainer;
+ this.deploymentInfo = mdbDeploymentInfo;
+ this.classLoader = mdbDeploymentInfo.getClassLoader();
+ interfaces = new Class[]{mdbDeploymentInfo.getMdbInterface(), MessageEndpoint.class};
+ }
+
+ public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException {
+ EndpointHandler endpointHandler = new EndpointHandler(mdbContainer, deploymentInfo, null, xaResource);
+ MessageEndpoint messageEndpoint = (MessageEndpoint) Proxy.newProxyInstance(classLoader, interfaces, endpointHandler);
+ return messageEndpoint;
+ }
+
+ public boolean isDeliveryTransacted(Method method) throws NoSuchMethodException {
+ byte transactionAttribute = deploymentInfo.getTransactionAttribute(method);
+ return DeploymentInfo.TX_REQUIRED == transactionAttribute;
+ }
+}
Added: 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=auto&rev=481006
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointHandler.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/EndpointHandler.java Thu Nov 30 09:37:34 2006
@@ -0,0 +1,248 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.core.mdb;
+
+import org.apache.openejb.DeploymentInfo;
+
+import javax.ejb.EJBException;
+import javax.resource.ResourceException;
+import javax.transaction.xa.XAResource;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+/**
+ * Container for the local interface of a Message Driven Bean.
+ * This container owns implementations of EJBLocalHome and EJBLocalObject
+ * that can be used by a client in the same classloader as the server.
+ * <p/>
+ * The implementation of the interfaces is generated using cglib FastClass
+ * proxies to avoid the overhead of native Java reflection.
+ * <p/>
+ * <p/>
+ * <p/>
+ * <p/>
+ * The J2EE connector and EJB specifications are not clear on what happens when beforeDelivery or
+ * afterDelivery throw an exception, so here is what we have decided:
+ * <p/>
+ * Exception from beforeDelivery:
+ * if container started TX, roll it back
+ * reset class loader to adapter classloader
+ * reset state to STATE_NONE
+ * <p/>
+ * Exception from delivery method:
+ * if container started TX, roll it back
+ * reset class loader to adapter classloader
+ * if state was STATE_BEFORE_CALLED, set state to STATE_ERROR so after can still be called
+ * <p/>
+ * Exception from afterDelivery:
+ * if container started TX, roll it back
+ * reset class loader to adapter classloader
+ * reset state to STATE_NONE
+ * <p/>
+ * One subtle side effect of this is if the adapter ignores an exception from beforeDelivery and
+ * continues with delivery and afterDelivery, the delivery will be treated as a single standalone
+ * delivery and the afterDelivery will throw an IllegalStateException.
+ *
+ * @version $Revision: 451417 $ $Date: 2006-09-29 13:13:22 -0700 (Fri, 29 Sep 2006) $
+ */
+public class EndpointHandler implements InvocationHandler {
+ private static enum State {
+ NONE, BEFORE_CALLED, METHOD_CALLED
+ }
+
+ private final MdbContainer container;
+ private final DeploymentInfo deployment;
+ private final Object instance;
+
+ private boolean released = false;
+ private State state = State.NONE;
+ private ClassLoader adapterClassLoader;
+
+ public EndpointHandler(MdbContainer container, DeploymentInfo deployment, Object instance, XAResource xaResource) {
+ this.container = container;
+ this.deployment = deployment;
+ this.instance = instance;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ String methodName = method.getName();
+ Class<?>[] parameterTypes = method.getParameterTypes();
+
+ if (method.getDeclaringClass() == Object.class) {
+ if ("toString".equals(methodName) && parameterTypes.length == 0) {
+ return toString();
+ } else if ("equals".equals(methodName) && parameterTypes.length == 1) {
+ return equals(args[0]);
+ } else if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
+ return hashCode();
+ } else {
+ throw new UnsupportedOperationException("Unkown method: " + method);
+ }
+ }
+
+ if ("beforeDelivery".equals(methodName) && Arrays.deepEquals(new Class[] {Method.class}, parameterTypes)) {
+ beforeDelivery((Method) args[0]);
+ return null;
+ } else if ("afterDelivery".equals(methodName) && parameterTypes.length == 0) {
+ afterDelivery();
+ return null;
+ } else if ("release".equals(methodName) && parameterTypes.length == 0) {
+ release();
+ return null;
+ } else {
+ Object value = deliverMessage(method, args);
+ return value;
+ }
+
+ }
+
+ public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
+ // verify current state
+ if (released) throw new IllegalStateException("Proxy has been released");
+ switch (state) {
+ case BEFORE_CALLED:
+ throw new IllegalStateException("beforeDelivery can not be called again until message is delivered and afterDelivery is called");
+ case METHOD_CALLED:
+ throw new IllegalStateException("The last message delivery must be completed with an afterDeliver before beforeDeliver can be called again");
+ }
+
+ // call afterDelivery on the container
+ installAppClassLoader();
+ try {
+ container.beforeDelivery(deployment.getDeploymentID(), instance, method);
+ } catch (NoSuchMethodException e) {
+ restoreAdapterClassLoader();
+ throw e;
+ } catch (ResourceException e) {
+ restoreAdapterClassLoader();
+ throw e;
+ } catch (Throwable throwable) {
+ restoreAdapterClassLoader();
+ throw new ResourceException(throwable);
+ }
+
+ // before completed successfully we are now ready to invoke bean
+ state = State.BEFORE_CALLED;
+ }
+
+ public Object deliverMessage(Method method, Object[] args) throws Throwable {
+ // verify current state
+ if (released) throw new IllegalStateException("Proxy has been released");
+ switch (state) {
+ case BEFORE_CALLED:
+ state = State.METHOD_CALLED;
+ case METHOD_CALLED:
+ throw new IllegalStateException("The last message delivery must be completed with an afterDeliver before another message can be delivered");
+ }
+
+
+ // if beforeDelivery was not called, call it now
+ if (state == State.NONE) {
+ try {
+ container.beforeDelivery(deployment.getDeploymentID(), instance, method);
+ } catch (Throwable throwable) {
+ if (throwable instanceof EJBException) {
+ throw (EJBException) throwable;
+ }
+ throw (EJBException) new EJBException().initCause(throwable);
+ }
+ }
+
+ boolean exceptionThrown = false;
+ try {
+ Object value = container.invoke(instance, method, args);
+ return value;
+ } catch (Throwable throwable) {
+ exceptionThrown = true;
+ throw throwable;
+ } finally {
+ // if the adapter is not using before/after, we must call afterDelivery to clean up
+ if (state == State.NONE) {
+ try {
+ container.afterDelivery(instance);
+ } catch (Throwable throwable) {
+ // if bean threw an exception, do not override that exception
+ if (!exceptionThrown) {
+ EJBException ejbException;
+ if (throwable instanceof EJBException) {
+ ejbException = (EJBException) throwable;
+ } else {
+ ejbException = new EJBException();
+ ejbException.initCause(throwable);
+ }
+ throw ejbException;
+ }
+ }
+ }
+ }
+ }
+
+ public void afterDelivery() throws ResourceException {
+ // verify current state
+ if (released) throw new IllegalStateException("Proxy has been released");
+ switch (state) {
+ case BEFORE_CALLED:
+ throw new IllegalStateException("Exactally one message must be delivered between beforeDelivery and afterDelivery");
+ case NONE:
+ throw new IllegalStateException("afterDelivery may only be called if message delivery began with a beforeDelivery call");
+ }
+
+
+ // call afterDelivery on the container
+ try {
+ container.afterDelivery(instance);
+ } catch (ResourceException e) {
+ throw e;
+ } catch (Throwable throwable) {
+ throw new ResourceException(throwable);
+ } finally {
+ // we are now in the default NONE state
+ state = State.NONE;
+ restoreAdapterClassLoader();
+ }
+ }
+
+ public void release() {
+ if (released) return;
+ released = true;
+
+ // notify the container
+ try {
+ container.release(instance);
+ } finally {
+ restoreAdapterClassLoader();
+ }
+ }
+
+ private void installAppClassLoader() {
+ Thread currentThread = Thread.currentThread();
+
+ adapterClassLoader = currentThread.getContextClassLoader();
+ if (adapterClassLoader != deployment.getClassLoader()) {
+ currentThread.setContextClassLoader(deployment.getClassLoader());
+ }
+ }
+
+ private void restoreAdapterClassLoader() {
+ if (adapterClassLoader != deployment.getClassLoader()) {
+ Thread.currentThread().setContextClassLoader(adapterClassLoader);
+ }
+ adapterClassLoader = null;
+ }
+}
Added: 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=auto&rev=481006
==============================================================================
--- incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java (added)
+++ incubator/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/mdb/MdbContainer.java Thu Nov 30 09:37:34 2006
@@ -0,0 +1,209 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.core.mdb;
+
+import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.DeploymentInfo;
+import org.apache.openejb.Container;
+import org.apache.openejb.core.ThreadContext;
+import org.apache.openejb.core.CoreDeploymentInfo;
+import org.apache.openejb.core.transaction.TransactionContext;
+import org.apache.openejb.core.transaction.TransactionPolicy;
+import org.apache.log4j.Logger;
+
+import javax.transaction.TransactionManager;
+import java.lang.reflect.Method;
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MdbContainer implements Container {
+ private static final Logger logger = Logger.getLogger("OpenEJB");
+ private static final Object[] NO_ARGS = new Object[0];
+
+ private final Object containerID;
+ private final TransactionManager transactionManager;
+
+ private final Map<Object, DeploymentInfo> deploymentRegistry = new HashMap<Object, DeploymentInfo>();
+
+ public MdbContainer(Object containerID, TransactionManager transactionManager) {
+ this.containerID = containerID;
+ this.transactionManager = transactionManager;
+ }
+
+ public synchronized DeploymentInfo [] deployments() {
+ return deploymentRegistry.values().toArray(new DeploymentInfo[deploymentRegistry.size()]);
+ }
+
+ public synchronized DeploymentInfo getDeploymentInfo(Object deploymentID) {
+ return deploymentRegistry.get(deploymentID);
+ }
+
+ public int getContainerType() {
+ return Container.MESSAGE_DRIVEN;
+ }
+
+ public Object getContainerID() {
+ return containerID;
+ }
+
+ public synchronized void deploy(Object deploymentID, DeploymentInfo info) throws OpenEJBException {
+ deploymentRegistry.put(deploymentID, info);
+ CoreDeploymentInfo di = (CoreDeploymentInfo) info;
+ di.setContainer(this);
+ }
+
+ public synchronized void undeploy(Object deploymentID) throws OpenEJBException {
+ CoreDeploymentInfo di = (CoreDeploymentInfo) deploymentRegistry.remove(deploymentID);
+ di.setContainer(null);
+ }
+
+ public void beforeDelivery(Object deployId, Object instance, Method method) throws Throwable {
+ // get the target deployment (MDB)
+ CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) getDeploymentInfo(deployId);
+
+ // obtain the context objects
+ ThreadContext callContext = ThreadContext.getThreadContext();
+ MdbCallContext mdbCallContext = new MdbCallContext();
+
+ // create the tx data
+ mdbCallContext.txPolicy = deployInfo.getTransactionPolicy(method);
+ mdbCallContext.txContext = new TransactionContext(callContext, transactionManager);
+
+ // call the tx before method
+ mdbCallContext.txPolicy.beforeInvoke(instance, mdbCallContext.txContext);
+
+ // save the tx data into the thread context
+ callContext.setDeploymentInfo(deployInfo);
+ callContext.setUnspecified(mdbCallContext);
+ }
+
+ public Object invoke(Object instance, Method method, Object... args) throws Throwable {
+ if (args == null) {
+ args = NO_ARGS;
+ }
+
+ Object returnValue = null;
+ Throwable exception = null;
+ try {
+ // get the context data
+ ThreadContext callContext = ThreadContext.getThreadContext();
+ CoreDeploymentInfo deployInfo = callContext.getDeploymentInfo();
+
+ if (logger.isInfoEnabled()) {
+ logger.info("invoking method " + method.getName() + " on " + deployInfo.getDeploymentID());
+ }
+
+ // determine the target method on the bean instance class
+ Method targetMethod = deployInfo.getMatchingBeanMethod(method);
+
+ // ivoke the target method
+ returnValue = _invoke(instance, targetMethod, args, (MdbCallContext) callContext.getUnspecified());
+ return returnValue;
+ } catch (org.apache.openejb.ApplicationException ae) {
+ // Application exceptions must be reported dirctly to the client. They
+ // do not impact the viability of the proxy.
+ exception = (ae.getRootCause() != null) ? ae.getRootCause() : ae;
+ throw exception;
+ } catch (org.apache.openejb.SystemException se) {
+ // A system exception would be highly unusual and would indicate a sever
+ // problem with the container system.
+ exception = (se.getRootCause() != null) ? se.getRootCause() : se;
+ logger.error("The container received an unexpected exception: ", exception);
+ throw new RemoteException("Container has suffered a SystemException", exception);
+ } catch (org.apache.openejb.OpenEJBException oe) {
+ // This is a normal container exception thrown while processing the request
+ exception = (oe.getRootCause() != null) ? oe.getRootCause() : oe;
+ logger.warn("The container received an unexpected exception: ", exception);
+ throw new RemoteException("Unknown Container Exception", oe.getRootCause());
+ } finally {
+ // Log the invocation results
+ if (logger.isDebugEnabled()) {
+ if (exception == null) {
+ logger.debug("finished invoking method " + method.getName() + ". Return value:" + returnValue);
+ } else {
+ logger.debug("finished invoking method " + method.getName() + " with exception " + exception);
+ }
+ } else if (logger.isInfoEnabled()) {
+ if (exception == null) {
+ logger.debug("finished invoking method " + method.getName());
+ } else {
+ logger.debug("finished invoking method " + method.getName() + " with exception " + exception);
+ }
+ }
+ }
+ }
+
+ private Object _invoke(Object instance, Method runMethod, Object [] args, MdbCallContext mdbCallContext) throws OpenEJBException {
+ try {
+ Object returnValue = runMethod.invoke(instance, args);
+ return returnValue;
+ } catch (java.lang.reflect.InvocationTargetException ite) {// handle exceptions thrown by enterprise bean
+ if (ite.getTargetException() instanceof RuntimeException) {
+ //
+ /// System Exception ****************************
+ mdbCallContext.txPolicy.handleSystemException(ite.getTargetException(), instance, mdbCallContext.txContext);
+ } else {
+ //
+ // Application Exception ***********************
+ mdbCallContext.txPolicy.handleApplicationException(ite.getTargetException(), mdbCallContext.txContext);
+ }
+ } catch (Throwable re) {// handle reflection exception
+ // Any exception thrown by reflection; not by the enterprise bean. Possible
+ // Exceptions are:
+ // IllegalAccessException - if the underlying method is inaccessible.
+ // IllegalArgumentException - if the number of actual and formal parameters differ, or if an unwrapping conversion fails.
+ // NullPointerException - if the specified object is null and the method is an instance method.
+ // ExceptionInInitializerError - if the initialization provoked by this method fails.
+ mdbCallContext.txPolicy.handleSystemException(re, instance, mdbCallContext.txContext);
+ }
+ throw new AssertionError("Should not get here");
+ }
+
+
+ public void afterDelivery(Object instance) throws Throwable {
+ // get the mdb call context
+ ThreadContext callContext = ThreadContext.getThreadContext();
+ MdbCallContext mdbCallContext = (MdbCallContext) callContext.getUnspecified();
+ ThreadContext.setThreadContext(null);
+
+ // invoke the tx after method
+ mdbCallContext.txPolicy.afterInvoke(instance, mdbCallContext.txContext);
+ }
+
+ public void release(Object instance) {
+ // get the mdb call context
+ ThreadContext callContext = ThreadContext.getThreadContext();
+ MdbCallContext mdbCallContext = (MdbCallContext) callContext.getUnspecified();
+ ThreadContext.setThreadContext(null);
+
+ // if we have an mdb call context we need to invoke the after invoke method
+ if (mdbCallContext != null) {
+ try {
+ mdbCallContext.txPolicy.afterInvoke(instance, mdbCallContext.txContext);
+ } catch (Exception e) {
+ logger.error("error while releasing message endpoint", e);
+ }
+ }
+ }
+
+ private static class MdbCallContext {
+ private TransactionPolicy txPolicy;
+ private TransactionContext txContext;
+ }
+}