A Patch for JBAS-1509
h2-matsuno Feb 21, 2006 9:14 AMI 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:sebastien.alborini@m4x.org">Sebastien Alborini</a> * @author <a href="mailto:akkerman@cs.nyu.edu">Anatoly Akkerman</a> * @author <a href="mailto:osh@sparre.dk">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:Scott.Stark@jboss.org">Scott Stark</a> * @author <a href="mailto:criege@riege.com">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:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:criege@riege.com">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:sebastien.alborini@m4x.org">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)>