User: mulder
Date: 00/07/03 17:18:11
Modified: src/main/org/jboss/ejb/plugins TxInterceptor.java
Log:
Update TxManager to use new MetaData and actually work (for both EJB
methods and Home methods). Required changes to file manager, container
factory, and container to actually load the metadata and make it
accessible.
Revision Changes Path
1.7 +155 -75 jboss/src/main/org/jboss/ejb/plugins/TxInterceptor.java
Index: TxInterceptor.java
===================================================================
RCS file:
/products/cvs/ejboss/jboss/src/main/org/jboss/ejb/plugins/TxInterceptor.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- TxInterceptor.java 2000/06/16 13:10:23 1.6
+++ TxInterceptor.java 2000/07/04 00:18:11 1.7
@@ -9,9 +9,10 @@
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.rmi.ServerException;
-import java.util.Map;
-import java.util.HashMap;
+import java.util.*;
+import javax.swing.tree.*;
+
import javax.transaction.Status;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
@@ -25,39 +26,36 @@
import org.jboss.ejb.EnterpriseContext;
import org.jboss.ejb.MethodInvocation;
import org.jboss.logging.Logger;
+import org.jboss.metadata.*;
+import org.jboss.metadata.ejbjar.EJBMethod;
/**
- * <description>
- *
+ * <description>
+ *
* @see <related>
* @author Rickard �berg ([EMAIL PROTECTED])
- * @version $Revision: 1.6 $
+ * @version $Revision: 1.7 $
*/
public class TxInterceptor
extends AbstractInterceptor
{
- // Constants -----------------------------------------------------
- public static final int TX_NOT_SUPPORTED = 0;
- public static final int TX_REQUIRED = 1;
- public static final int TX_SUPPORTS = 2;
- public static final int TX_REQUIRES_NEW = 3;
- public static final int TX_MANDATORY = 4;
- public static final int TX_NEVER = 5;
-
+
// Attributes ----------------------------------------------------
private TransactionManager tm;
private HashMap methodTx = new HashMap();
-
+
protected Container container;
-
+ private RunInvoke invoker = new RunInvoke();
+ private RunInvokeHome invokeHomer = new RunInvokeHome();
+
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
-
+
// Public --------------------------------------------------------
- public void setContainer(Container container)
- {
- this.container = container;
+ public void setContainer(Container container)
+ {
+ this.container = container;
}
public Container getContainer()
@@ -71,46 +69,79 @@
{
// Store TM reference locally
tm = getContainer().getTransactionManager();
-
+
// Find out method->tx-type mappings from meta-info
// EnterpriseBean eb = getContainer.getMetaData();
// eb.getBeanContext()
}
-
+
public Object invokeHome(MethodInvocation mi)
throws Exception
{
// TODO
- return getNext().invokeHome(mi);
+// return getNext().invokeHome(mi);
+ invokeHomer.mi = mi;
+ return runWithTransactions(invokeHomer, mi);
}
/**
* This method does invocation interpositioning of tx management
*
- * @param id
- * @param m
- * @param args
- * @return
- * @exception Exception
+ * @param id
+ * @param m
+ * @param args
+ * @return
+ * @exception Exception
*/
- public Object invoke(MethodInvocation mi)
- throws Exception
- {
+ public Object invoke(MethodInvocation mi) throws Exception {
+ invoker.mi = mi;
+ return runWithTransactions(invoker, mi);
+ }
+
+ private void printMethod(Method m, byte type) {
+ String name;
+ switch(type) {
+ case EJBMethod.TX_MANDATORY:
+ name = "TX_MANDATORY";
+ break;
+ case EJBMethod.TX_NEVER:
+ name = "TX_NEVER";
+ break;
+ case EJBMethod.TX_NOT_SUPPORTED:
+ name = "TX_NOT_SUPPORTED";
+ break;
+ case EJBMethod.TX_REQUIRED:
+ name = "TX_REQUIRED";
+ break;
+ case EJBMethod.TX_REQUIRES_NEW:
+ name = "TX_REQUIRES_NEW";
+ break;
+ case EJBMethod.TX_SUPPORTS:
+ name = "TX_SUPPORTS";
+ break;
+ default:
+ name = "TX_UNKNOWN";
+ }
+ Logger.debug(name+" for "+m.getName());
+ }
+
+ private Object runWithTransactions(Doable runner, MethodInvocation mi) throws
Exception {
Transaction current = mi.getTransaction();
-
- switch (getTransactionMethod(mi.getMethod()))
+
+ byte transType = getTransactionMethod(mi.getMethod(), runner);
+ printMethod(mi.getMethod(), transType);
+ switch (transType)
{
- case TX_NOT_SUPPORTED:
+ case EJBMethod.TX_NOT_SUPPORTED:
{
-//DEBUG Logger.debug("TX_NOT_SUPPORTED");
if (current.getStatus() != Status.STATUS_NO_TRANSACTION)
{
// Suspend tx
getContainer().getTransactionManager().suspend();
-
+
try
{
- return getNext().invoke(mi);
+ return runner.run();
} finally
{
// Resume tx
@@ -118,28 +149,28 @@
}
} else
{
- return getNext().invoke(mi);
+ return runner.run();
}
}
-
- case TX_REQUIRED:
+
+ case EJBMethod.TX_REQUIRED:
{
-//DEBUG Logger.debug("TX_REQUIRED");
Transaction tx = current;
-
+
if (current.getStatus() == Status.STATUS_NO_TRANSACTION)
{
// No tx running
// Create tx
//DEBUG Logger.debug("Begin tx");
getContainer().getTransactionManager().begin();
-
mi.setTransaction(getContainer().getTransactionManager().getTransaction());
- }
-
+ tx = getContainer().getTransactionManager().getTransaction();
+ mi.setTransaction(tx);
+ }
+
// Continue invocation
try
{
- return getNext().invoke(mi);
+ return runner.run();
} catch (RemoteException e)
{
if (!tx.equals(current))
@@ -167,7 +198,7 @@
{
tx.rollback();
}
- else if (current.getStatus() == Status.STATUS_NO_TRANSACTION &&
+ else if (current.getStatus() == Status.STATUS_NO_TRANSACTION &&
tx.getStatus() == Status.STATUS_ACTIVE)
{
// Commit tx
@@ -176,34 +207,34 @@
// b) app. exception was thrown
tx.commit();
}
+ if(!tx.equals(current))
+ mi.setTransaction(current);
}
}
-
- case TX_SUPPORTS:
+
+ case EJBMethod.TX_SUPPORTS:
{
-//DEBUG Logger.debug("TX_SUPPORTS");
-
+
// This mode doesn't really do anything
// If tx started -> do nothing
// If tx not started -> do nothing
-
+
// Continue invocation
- return getNext().invoke(mi);
+ return runner.run();
}
-
- case TX_REQUIRES_NEW:
+
+ case EJBMethod.TX_REQUIRES_NEW:
{
- Logger.debug("TX_REQUIRES_NEW");
-
+
// Always begin new tx
- Logger.debug("Begin tx");
+// Logger.debug("Begin tx");
getContainer().getTransactionManager().begin();
mi.setTransaction(getContainer().getTransactionManager().getTransaction());
-
+
// Continue invocation
try
{
- return getNext().invoke(mi);
+ return runner.run();
} catch (RemoteException e)
{
getContainer().getTransactionManager().rollback();
@@ -232,41 +263,90 @@
}
}
}
-
- case TX_MANDATORY:
+
+ case EJBMethod.TX_MANDATORY:
{
-//DEBUG Logger.debug("TX_MANDATORY");
if (current.getStatus() == Status.STATUS_NO_TRANSACTION)
{
throw new TransactionRequiredException();
} else
{
- return getNext().invoke(mi);
+ return runner.run();
}
}
-
- case TX_NEVER:
+
+ case EJBMethod.TX_NEVER:
{
-//DEBUG Logger.debug("TX_NEVER");
if (current.getStatus() == Status.STATUS_ACTIVE)
{
throw new RemoteException("Transaction not allowed");
} else
{
- return getNext().invoke(mi);
+ return runner.run();
}
}
}
-
+
return null;
}
-
+
// Protected ----------------------------------------------------
-
+
// This should be cached, since this method is called very often
- protected int getTransactionMethod(Method m)
- {
- return TX_SUPPORTS; // TODO: find out transaction method
- }
- // Inner classes -------------------------------------------------
+ protected byte getTransactionMethod(Method m, Doable d) {
+ Byte b = (Byte)methodTx.get(m);
+ if(b != null) return b.byteValue();
+
+ try {
+ BeanMetaData bmd = container.getBeanMetaData();
+//System.out.println("Found metadata for bean '"+bmd.getName()+"'");
+ try {
+ MethodMetaData mmd;
+ if(d == invoker)
+ mmd = bmd.getMethod(m.getName(), m.getParameterTypes());
+ else
+ mmd = bmd.getHomeMethod(m.getName(), m.getParameterTypes());
+//System.out.println("Found metadata for method '"+mmd.getName()+"'");
+ byte result =
((Byte)mmd.getProperty("transactionAttribute")).byteValue();
+ methodTx.put(m, new Byte(result));
+ return result;
+ } catch(IllegalArgumentException e2) {
+ try {
+ MethodMetaData mmd;
+ if(d == invoker)
+ mmd = bmd.getMethod("*", new Class[0]);
+ else
+ mmd = bmd.getHomeMethod("*", new Class[0]);
+//System.out.println("Found metadata for '*'");
+ byte result =
((Byte)mmd.getProperty("transactionAttribute")).byteValue();
+ methodTx.put(m, new Byte(result));
+ return result;
+ } catch(IllegalArgumentException e3) {
+//System.out.println("Couldn't find method metadata for "+m+" in "+bmd.getName());
+ }
+ }
+ } catch(IllegalArgumentException e) {
+ System.out.println("Couldn't find bean
'"+container.getMetaData().getEjbName()+"'");
+ }
+ methodTx.put(m, new Byte(EJBMethod.TX_SUPPORTS));
+ return EJBMethod.TX_SUPPORTS;
+ }
+ // Inner classes -------------------------------------------------
+ interface Doable {
+ public Object run() throws Exception;
+ }
+
+ class RunInvoke implements Doable {
+ MethodInvocation mi;
+ public Object run() throws Exception {
+ return getNext().invoke(mi);
+ }
+ }
+
+ class RunInvokeHome implements Doable {
+ MethodInvocation mi;
+ public Object run() throws Exception {
+ return getNext().invokeHome(mi);
+ }
+ }
}