I made a patch for JBAS-1509 to JBoss3.2.7. http://jira.jboss.com/jira/browse/JBAS-1509
It was already backport to JBoss3.2.8, I know, but I need this new feature on 3.2.7. The patch is as follows. This is a diff between 3.2.7 and 3.2.8RC1. It works well in our system. Use at your own risk, and I hope this has been helpful. | diff -ur jboss-3.2.7-src/server/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java jboss-3.2.8RC1-src/server/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java | --- jboss-3.2.7-src/server/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java 2004-10-19 00:40:47.000000000 +0900 | +++ jboss-3.2.8RC1-src/server/src/main/org/jboss/ejb/plugins/TxInterceptorCMT.java 2005-12-07 11:23:18.000000000 +0900 | @@ -1,8 +1,23 @@ | /* | - * JBoss, the OpenSource J2EE webOS | + * JBoss, Home of Professional Open Source | + * Copyright 2005, JBoss Inc., and individual contributors as indicated | + * by the @authors tag. See the copyright.txt in the distribution for a | + * full listing of individual contributors. | * | - * Distributable under LGPL license. | - * See terms of license at gnu.org. | + * This is free software; you can redistribute it and/or modify it | + * under the terms of the GNU Lesser General Public License as | + * published by the Free Software Foundation; either version 2.1 of | + * the License, or (at your option) any later version. | + * | + * This software is distributed in the hope that it will be useful, | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | + * Lesser General Public License for more details. | + * | + * You should have received a copy of the GNU Lesser General Public | + * License along with this software; if not, write to the Free | + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | */ | package org.jboss.ejb.plugins; | | @@ -32,7 +47,6 @@ | import javax.transaction.TransactionRolledbackException; | import java.lang.reflect.Method; | import java.rmi.RemoteException; | -import java.util.HashMap; | import java.util.Map; | import java.util.Random; | import java.util.Iterator; | @@ -46,7 +60,7 @@ | * @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a> | * @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a> | * @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a> | - * @version $Revision: 1.27.2.16 $ | + * @version $Revision: 1.27.2.19 $ | */ | public class TxInterceptorCMT extends AbstractTxInterceptor implements XmlLoadable | { | @@ -56,6 +70,12 @@ | /** A cache mapping methods to transaction attributes. */ | private ConcurrentReaderHashMap methodTx = new ConcurrentReaderHashMap(); | | + /** | + * Whether an exception should be thrown if the transaction is not | + * active, even though the application doesn't throw an exception | + */ | + private boolean exceptionRollback = true; | + | // Static -------------------------------------------------------- | | // Constructors -------------------------------------------------- | @@ -64,6 +84,15 @@ | | // Interceptor implementation -------------------------------------- | | + public void create() throws Exception | + { | + super.create(); | + BeanMetaData bmd = getContainer().getBeanMetaData(); | + exceptionRollback = bmd.getExceptionRollback(); | + if (exceptionRollback == false) | + exceptionRollback = bmd.getApplicationMetaData().getExceptionRollback(); | + } | + | | public static int MAX_RETRIES = 5; | public static Random random = new Random(); | @@ -291,6 +320,7 @@ | case MetaData.TX_REQUIRED: | { | int oldTimeout = 0; | + Transaction theTransaction = oldTransaction; | if (oldTransaction == null) | { // No tx running | // Create tx | @@ -303,6 +333,7 @@ | | // Let the method invocation know | invocation.setTransaction(newTransaction); | + theTransaction = newTransaction; | } | else | { | @@ -314,7 +345,9 @@ | // Continue invocation | try | { | - return invokeNext(invocation, oldTransaction != null); | + Object result = invokeNext(invocation, oldTransaction != null); | + checkTransactionStatus(theTransaction, type); | + return result; | } | finally | { | @@ -340,7 +373,10 @@ | | try | { | - return invokeNext(invocation, oldTransaction != null); | + Object result = invokeNext(invocation, oldTransaction != null); | + if (oldTransaction != null) | + checkTransactionStatus(oldTransaction, type); | + return result; | } | finally | { | @@ -363,7 +399,9 @@ | // Continue invocation | try | { | - return invokeNext(invocation, false); | + Object result = invokeNext(invocation, false); | + checkTransactionStatus(newTransaction, type); | + return result; | } | finally | { | @@ -392,8 +430,11 @@ | tm.resume(oldTransaction); | try | { | - return invokeNext(invocation, true); | - } finally | + Object result = invokeNext(invocation, true); | + checkTransactionStatus(oldTransaction, type); | + return result; | + } | + finally | { | tm.suspend(); | } | @@ -553,6 +594,40 @@ | } | } | | + /** | + * The application has not thrown an exception, but... | + * When exception-on-rollback is true, | + * check whether the transaction is not active. | + * If it did not throw an exception anyway. | + * | + * @param tx the transaction | + * @param type the invocation type | + * @throws TransactionRolledbackException if transaction is no longer active | + */ | + protected void checkTransactionStatus(Transaction tx, InvocationType type) | + throws TransactionRolledbackException | + { | + if (exceptionRollback) | + { | + if (log.isTraceEnabled()) | + log.trace("No exception from ejb, checking transaction status: " + tx); | + int status = Status.STATUS_UNKNOWN; | + try | + { | + status = tx.getStatus(); | + } | + catch (Throwable t) | + { | + log.debug("Ignored error trying to retrieve transaction status", t); | + } | + if (status != Status.STATUS_ACTIVE) | + { | + Exception e = new Exception("Transaction cannot be committed (probably transaction timeout): " + tx); | + throwJBossException(e, type); | + } | + } | + } | + | // Inner classes ------------------------------------------------- | | // Monitorable implementation ------------------------------------ | diff -ur jboss-3.2.7-src/server/src/main/org/jboss/metadata/ApplicationMetaData.java jboss-3.2.8RC1-src/server/src/main/org/jboss/metadata/ApplicationMetaData.java | --- jboss-3.2.7-src/server/src/main/org/jboss/metadata/ApplicationMetaData.java 2003-05-03 08:40:33.000000000 +0900 | +++ jboss-3.2.8RC1-src/server/src/main/org/jboss/metadata/ApplicationMetaData.java 2005-12-07 11:23:18.000000000 +0900 | @@ -1,10 +1,24 @@ | /* | - * JBoss, the OpenSource J2EE webOS | + * JBoss, Home of Professional Open Source | + * Copyright 2005, JBoss Inc., and individual contributors as indicated | + * by the @authors tag. See the copyright.txt in the distribution for a | + * full listing of individual contributors. | * | - * Distributable under LGPL license. | - * See terms of license at gnu.org. | + * This is free software; you can redistribute it and/or modify it | + * under the terms of the GNU Lesser General Public License as | + * published by the Free Software Foundation; either version 2.1 of | + * the License, or (at your option) any later version. | + * | + * This software is distributed in the hope that it will be useful, | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | + * Lesser General Public License for more details. | + * | + * You should have received a copy of the GNU Lesser General Public | + * License along with this software; if not, write to the Free | + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | */ | - | package org.jboss.metadata; | | import java.net.URL; | @@ -27,7 +41,7 @@ | * @author <a href="mailto:[EMAIL PROTECTED]">Scott Stark</a> | * @author <a href="mailto:[EMAIL PROTECTED]">Christian Riege</a> | * | - * @version $Revision: 1.29.2.3 $ | + * @version $Revision: 1.29.2.5 $ | */ | public class ApplicationMetaData | extends MetaData | @@ -60,6 +74,8 @@ | /** The unauthenticated-principal value assigned to the application */ | private String unauthenticatedPrincipal; | private boolean enforceEjbRestrictions; | + /** Whether to throw an exception on a rollback if there is no exception */ | + private boolean exceptionRollback = false; | | public ApplicationMetaData(URL u) | { | @@ -187,6 +203,11 @@ | return enforceEjbRestrictions; | } | | + public boolean getExceptionRollback() | + { | + return exceptionRollback; | + } | + | /** | * Import data provided by ejb-jar.xml | * | @@ -587,6 +608,9 @@ | jmxName = getElementContent(jmxNameElement); | } | | + // Throw an exception when marked rollback with no exception thrown | + exceptionRollback = MetaData.getOptionalChildBooleanContent(element, "exception-on-rollback", false); | + | // Get the security domain name | Element securityDomainElement = getOptionalChild(element, | "security-domain"); | diff -ur jboss-3.2.7-src/server/src/main/org/jboss/metadata/BeanMetaData.java jboss-3.2.8RC1-src/server/src/main/org/jboss/metadata/BeanMetaData.java | --- jboss-3.2.7-src/server/src/main/org/jboss/metadata/BeanMetaData.java 2005-01-27 16:12:17.000000000 +0900 | +++ jboss-3.2.8RC1-src/server/src/main/org/jboss/metadata/BeanMetaData.java 2005-12-07 11:23:18.000000000 +0900 | @@ -1,10 +1,24 @@ | /* | - * JBoss, the OpenSource J2EE webOS | + * JBoss, Home of Professional Open Source | + * Copyright 2005, JBoss Inc., and individual contributors as indicated | + * by the @authors tag. See the copyright.txt in the distribution for a | + * full listing of individual contributors. | * | - * Distributable under LGPL license. | - * See terms of license at gnu.org. | + * This is free software; you can redistribute it and/or modify it | + * under the terms of the GNU Lesser General Public License as | + * published by the Free Software Foundation; either version 2.1 of | + * the License, or (at your option) any later version. | + * | + * This software is distributed in the hope that it will be useful, | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | + * Lesser General Public License for more details. | + * | + * You should have received a copy of the GNU Lesser General Public | + * License along with this software; if not, write to the Free | + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | */ | - | package org.jboss.metadata; | | import java.lang.reflect.Method; | @@ -38,7 +52,7 @@ | * @author <a href="mailto:[EMAIL PROTECTED]">Bill Burke</a> | * @author <a href="mailto:[EMAIL PROTECTED]">Christian Riege</a> | * | - * @version $Revision: 1.41.2.15 $ | + * @version $Revision: 1.41.2.17 $ | */ | public abstract class BeanMetaData | extends MetaData | @@ -130,6 +144,9 @@ | /** Any object names for services the bean depends on */ | private Collection depends = new LinkedList(); | | + /** Whether to throw an exception on a rollback if there is no exception */ | + private boolean exceptionRollback = false; | + | // Static -------------------------------------------------------- | | // Constructors -------------------------------------------------- | @@ -586,6 +603,11 @@ | return callByValue; | } | | + public boolean getExceptionRollback() | + { | + return exceptionRollback; | + } | + | public void importEjbJarXml(Element element) | throws DeploymentException | { | @@ -722,6 +744,9 @@ | securityProxy = getElementContent(getOptionalChild(element, | "security-proxy"), securityProxy); | | + // Throw an exception when marked rollback with no exception thrown | + exceptionRollback = MetaData.getOptionalChildBooleanContent(element, "exception-on-rollback", false); | + | // update the resource references (optional) | Iterator iterator = getChildrenByTagName(element, "resource-ref"); | while (iterator.hasNext()) { | diff -ur jboss-3.2.7-src/server/src/main/org/jboss/metadata/MetaData.java jboss-3.2.8RC1-src/server/src/main/org/jboss/metadata/MetaData.java | --- jboss-3.2.7-src/server/src/main/org/jboss/metadata/MetaData.java 2004-08-12 01:10:58.000000000 +0900 | +++ jboss-3.2.8RC1-src/server/src/main/org/jboss/metadata/MetaData.java 2005-12-07 11:23:18.000000000 +0900 | @@ -1,8 +1,23 @@ | /* | - * JBoss, the OpenSource J2EE webOS | + * JBoss, Home of Professional Open Source | + * Copyright 2005, JBoss Inc., and individual contributors as indicated | + * by the @authors tag. See the copyright.txt in the distribution for a | + * full listing of individual contributors. | * | - * Distributable under LGPL license. | - * See terms of license at gnu.org. | + * This is free software; you can redistribute it and/or modify it | + * under the terms of the GNU Lesser General Public License as | + * published by the Free Software Foundation; either version 2.1 of | + * the License, or (at your option) any later version. | + * | + * This software is distributed in the hope that it will be useful, | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | + * Lesser General Public License for more details. | + * | + * You should have received a copy of the GNU Lesser General Public | + * License along with this software; if not, write to the Free | + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. | */ | package org.jboss.metadata; | | @@ -21,7 +36,7 @@ | * An abstract base class for metadata containers. | * | * @author <a href="mailto:[EMAIL PROTECTED]">Sebastien Alborini</a> | - * @version $Revision: 1.21.2.7 $ | + * @version $Revision: 1.21.2.9 $ | */ | public abstract class MetaData | implements Cloneable, XmlLoadable | @@ -276,6 +291,21 @@ | return false; | } | | + public static boolean getOptionalChildBooleanContent(Element element, | + String name, boolean defaultValue) | + throws DeploymentException | + { | + Element child = getOptionalChild(element, name); | + boolean flag = defaultValue; | + if(child != null) | + { | + String value = getElementContent(child).toLowerCase(); | + flag = value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"); | + } | + | + return flag; | + } | + | // Constructors -------------------------------------------------- | | // Public -------------------------------------------------------- | diff -ur jboss-3.2.7-src/server/src/resources/org/jboss/metadata/jboss_3_2.dtd jboss-3.2.8RC1-src/server/src/resources/org/jboss/metadata/jboss_3_2.dtd | --- jboss-3.2.7-src/server/src/resources/org/jboss/metadata/jboss_3_2.dtd 2005-01-28 15:45:26.000000000 +0900 | +++ jboss-3.2.8RC1-src/server/src/resources/org/jboss/metadata/jboss_3_2.dtd 2005-12-07 11:23:18.000000000 +0900 | @@ -7,8 +7,8 @@ | "-//JBoss//DTD JBOSS 3.2//EN" | "http://www.jboss.org/j2ee/dtd/jboss_3_2.dtd"> | | -$Id: jboss_3_2.dtd,v 1.1.2.29 2005/01/28 05:48:31 starksm Exp $ | -$Revision: 1.1.2.29 $ | +$Id: jboss_3_2.dtd,v 1.1.2.34 2005/12/07 02:23:18 adrian Exp $ | +$Revision: 1.1.2.34 $ | | Overview of the architecture of jboss.xml | | @@ -24,8 +24,8 @@ | <ejb-name /> | <jndi-name /> | <local-jndi-name /> | - <read-only> | <call-by-value/> | + <read-only> | <configuration-name> | <security-proxy> | <ejb-ref> | @@ -91,8 +91,12 @@ | | <container-configuration> | <container-name /> | + <call-logging /> | + <invoker-proxy-binding-name /> | + <sync-on-commit-only /> | + <insert-after-ejb-post-create /> | + <call-ejb-store-on-clean /> | <container-interceptors /> | - <client-interceptors /> | <instance-pool /> | <instance-cache /> | <persistence-manager /> | @@ -102,7 +106,9 @@ | <container-pool-conf /> | <commit-option /> | <optiond-refresh-rate /> | - <security-domain/> | + <security-domain /> | + <cluster-config /> | + <depends /> | </container-configuration> | | </container-configurations> | @@ -123,7 +129,7 @@ | | --> | <!ELEMENT jboss (loader-repository?, jmx-name?, enforce-ejb-restrictions?, | - security-domain?, unauthenticated-principal? , enterprise-beans?, | + security-domain?, unauthenticated-principal? , exception-on-rollback?, enterprise-beans?, | resource-managers?, invoker-proxy-bindings?, container-configurations?)> | | <!-- The loader-repository specifies the name of the UnifiedLoaderRepository | @@ -351,7 +357,8 @@ | Used in: enterprise-beans | --> | <!ELEMENT entity (ejb-name , jndi-name? , local-jndi-name? , call-by-value?, read-only? , | - configuration-name? , invoker-bindings?, security-proxy? , ejb-ref* , ejb-local-ref* , resource-ref* , | + exception-on-rollback?, configuration-name? , invoker-bindings?, security-proxy? , | + ejb-ref* , ejb-local-ref* , resource-ref* , | resource-env-ref* , method-attributes? , clustered? , cluster-config?, | cache-invalidation? , cache-invalidation-config?, depends*)> | | @@ -364,8 +371,9 @@ | | Used in: enterprise-beans | --> | -<!ELEMENT session (ejb-name , jndi-name? , local-jndi-name?, call-by-value?, configuration-name?, | - invoker-bindings?, security-proxy? , ejb-ref* , ejb-local-ref* , resource-ref* , resource-env-ref* , clustered? , | +<!ELEMENT session (ejb-name , jndi-name? , local-jndi-name?, call-by-value?, | + exception-on-rollback?, configuration-name?, invoker-bindings?, security-proxy? , | + ejb-ref* , ejb-local-ref* , resource-ref* , resource-env-ref* , clustered? , | cluster-config?, method-attributes?, depends*)> | | <!-- | @@ -377,9 +385,9 @@ | | Used in: enterprise-beans | --> | -<!ELEMENT message-driven (ejb-name , destination-jndi-name , | +<!ELEMENT message-driven (ejb-name , destination-jndi-name , local-jndi-name?, | mdb-user?, mdb-passwd? , mdb-client-id? , mdb-subscription-id? , | - configuration-name? , invoker-bindings?, | + exception-on-rollback?, configuration-name? , invoker-bindings?, | security-proxy? , ejb-ref* , ejb-local-ref* , resource-ref* , resource-env-ref*, depends*)> | | <!-- | @@ -430,6 +438,21 @@ | <!ELEMENT read-only (#PCDATA)> | | <!-- | + Whether to throw an exception if the CMT controlled | + transaction is no longer active (e.g. marked rollback) | + but the application has not itself thrown an exception. | + If the bean specifies false, it uses the | + jboss/exception-on-rollback config. | + Defaults to false. | + It must be one of the following : | + <exception-on-rollback>true</exception-on-rollback> | + <exception-on-rollback>false</exception-on-rollback> | + | + Used in: jboss, session, entity and message-driven | +--> | +<!ELEMENT exception-on-rollback (#PCDATA)> | + | +<!-- | The configuration-name element gives the name of the container | configuration for this bean. It must match one of the container-name | tags in the container-configurations section, or one of the standard | @@ -851,7 +874,8 @@ | <!ELEMENT insert-after-ejb-post-create (#PCDATA)> | | <!-- The call-ejb-store-for-clean says whether ejbStore should be called on clean instances | - at synchronization time. By the spec it should be true. | + at synchronization time. By the spec it should be true. But users wanted it to be false. | + False is the default, meaning ejbStore is called only on dirty instances. | --> | <!ELEMENT call-ejb-store-on-clean (#PCDATA)> | View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3925334#3925334 Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3925334 ------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Do you grep through log files for problems? Stop! Download the new AJAX search engine that makes searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642 _______________________________________________ JBoss-user mailing list JBoss-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jboss-user