7 Replies Latest reply on May 18, 2007 4:42 PM by jhalliday

    JTA + JBoss Cache + Distributed Transactions

    nanreh

      Hi there,

      I'm in the process of learning as much as I can about JBoss Transactions. I hope to use it to do distributed transactions across a three or four JBoss Cache nodes which are all stand-alone Java SE applications.

      I've run through all of the samples in the trail_map project and they all run just fine for me. The documentation in trail_map says:

      "Using JTA to create a distributed transaction need the creation of an ORB instance as done by a JTS application (see JTS versions of the banking application), the difference is in the interface used to demarcate and control transactions."

      I would like to use JTA to manage transactions in my code and I've implemented a TransactionManagerLookup for my JBoss Cache that looks like this:

      package org.defy.tx;
      import javax.transaction.TransactionManager;
      
      import org.jboss.cache.transaction.TransactionManagerLookup;
      
      public class CustomTransactionManagerLookup implements TransactionManagerLookup {
       public TransactionManager getTransactionManager() throws Exception {
       javax.transaction.TransactionManager transactionManager =
       com.arjuna.ats.jta.TransactionManager.transactionManager();
       return transactionManager;
       }
      }
      


      I went ahead and copied the ORB initialization code from the JTS "remotebank" sample and put together a simple program that creates a JBoss Cache and tries to modify it within a transaction.

      package org.defy.tx;
      
      import javax.transaction.UserTransaction;
      
      import org.apache.log4j.PropertyConfigurator;
      import org.jboss.cache.Cache;
      import org.jboss.cache.CacheFactory;
      import org.jboss.cache.DefaultCacheFactory;
      import org.jboss.cache.Fqn;
      import org.jboss.cache.Node;
      
      import com.arjuna.orbportability.OA;
      import com.arjuna.orbportability.ORB;
      import com.arjuna.orbportability.RootOA;
      
      public class Main {
      
       public static void main (String[] args) {
      
       initOrb(args);
      
       // Local
       //System.setProperty("com.arjuna.ats.jta.jtaTMImplementation","com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple");
       //System.setProperty("com.arjuna.ats.jta.jtaUTImplementation","com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple");
      
       // Distributed
       System.setProperty("com.arjuna.ats.jta.jtaTMImplementation","com.arjuna.ats.internal.jta.transaction.jts.TransactionManagerImple");
       System.setProperty("com.arjuna.ats.jta.jtaUTImplementation","com.arjuna.ats.internal.jta.transaction.jts.UserTransactionImple");
      
       CacheFactory factory = DefaultCacheFactory.getInstance();
       Cache cache = factory.createCache("cache-configuration.xml");
      
       runTx(cache);
       }
      
      
       private static void runTx(Cache cache) {
       UserTransaction tx = com.arjuna.ats.jta.UserTransaction.userTransaction();
       System.out.println(tx);
       try {
      
       tx.begin();
      
       Fqn peterGriffinFqn = Fqn.fromString("/griffin/peter");
       // let's get a hold of the root node.
       Node rootNode = cache.getRoot();
       // and create a child
       Node peterGriffin = rootNode.addChild(peterGriffinFqn);
       // let's store some data in the node
       peterGriffin.put("isCartoonCharacter", Boolean.TRUE);
       peterGriffin.put("favouriteDrink", "Beer");
      
       System.out.println("Begin tx.");
       tx.commit();
       System.out.println("Commit tx.");
       }
       catch(Exception e) {
       e.printStackTrace();
       try {
       System.out.println("Rollback tx.");
       tx.rollback();
       } catch(Exception re) {
       re.printStackTrace();
       }
       }
       }
      
       private static void initOrb(String[] args) {
       // Define an ORB suitable for use by the JBoss Transactions product ORB portability layer.
       ORB myORB = null;
       // Define an object adapter suitable for use by the JBoss Transactions product ORB portability layer.
       RootOA myOA = null;
       try
       {
       // Initialize the ORB reference using the JBoss Transactions product ORB portability layer.
       myORB = ORB.getInstance("sample");
       // Initialize the object adapter reference using the JBoss Transactions product ORB portability layer.
       myOA = OA.getRootOA(myORB);
       // Initialize the ORB using the JBoss Transactions product ORB portability layer.
       myORB.initORB(args, null);
       // Initialize the object adapter reference using the JBoss Transactions product ORB portability layer.
       myOA.initOA();
       }
       catch (Exception e)
       {
       // The ORB has not been correctly configured!
       // Display as much help as possible to the user track down the configuration problem
       System.err.println("Trailmap Error: ORB Initialisation failed: " + e);
       e.printStackTrace();
       System.exit(0);
       }
       };
      }
      



      When I set things to run under under a local transaction everything works fine. When I switch to distributed transactions I get the following error.

      2007-05-17 23:52:06,593 DEBUG [org.jboss.cache.interceptors.TxInterceptor] - <Running beforeCompletion on gtx GlobalTransaction:<null>:1>
      2007-05-17 23:52:06,609 DEBUG [org.jboss.cache.interceptors.TxInterceptor] - <Setting up transactional context.>
      2007-05-17 23:52:06,609 DEBUG [org.jboss.cache.interceptors.TxInterceptor] - <Setting tx as TransactionImple < jts, -3f57fefe:ab1:464d4d16:3
       > and gtx as GlobalTransaction:<null>:1>
      [17-05-2007 23:52:06:609] jacorb.orb.giop:INFO: ClientConnectionManager: found conn to target 192.168.1.2:2736
      [17-05-2007 23:52:06:625] jacorb.poa:INFO: oid:
      04 15 0C 23 4B 15 3C 21 2B 36 ...#K.<!+6
      object is activated
      2007-05-17 23:52:06,640 WARN [com.arjuna.ats.jts.logging.loggerI18N] - <[com.arjuna.ats.internal.jts.orbspecific.jacorb.recoverycoordinators
      .JacOrbRCManager_4] [com.arjuna.ats.internal.jts.orbspecific.jacorb.recoverycoordinators.JacOrbRCManager_4] - RCManager could not find file
      in object store during setup.>
      2007-05-17 23:52:06,640 WARN [com.arjuna.ats.jts.logging.loggerI18N] - <[com.arjuna.ats.internal.jts.orbspecific.jacorb.recoverycoordinators
      .JacOrbRCManager_3] [com.arjuna.ats.internal.jts.orbspecific.jacorb.recoverycoordinators.JacOrbRCManager_3] - RCManager could not find file
      in object store.>
      2007-05-17 23:52:06,656 WARN [com.arjuna.ats.jts.logging.loggerI18N] - <[com.arjuna.ats.internal.jts.orbspecific.coordinator.rccreate] Creat
      ion of RecoveryCoordinator for -3f57fefe:ab1:464d4d16:3 threw: org.omg.CORBA.BAD_OPERATION: RecoveryCoordinator [com.arjuna.ats.internal.jts
      .orbspecific.coordinator.rcnotcreated] not created! vmcid: 0x0 minor code: 0 completed: No>
      [17-05-2007 23:52:06:656] jacorb.poa.controlle:INFO: rid: 6 opname: register_resource invocation: system exception was thrown (org.omg.CORBA
      .BAD_OPERATION: RecoveryCoordinator [com.arjuna.ats.internal.jts.orbspecific.coordinator.rcnotcreated] not created! vmcid: 0x0 minor code:
       0 completed: No)
      2007-05-17 23:52:06,671 WARN [com.arjuna.ats.jts.logging.loggerI18N] - <[com.arjuna.ats.internal.jts.orbspecific.interposition.resources.arj
      una.generror] ServerTopLevelAction.registerResource caught exception: org.omg.CORBA.BAD_OPERATION: Server-side Exception: RecoveryCoordinato
      r [com.arjuna.ats.internal.jts.orbspecific.coordinator.rcnotcreated] not created! vmcid: 0x0 minor code: 0 completed: No>
      org.omg.CORBA.BAD_OPERATION: Server-side Exception: RecoveryCoordinator [com.arjuna.ats.internal.jts.orbspecific.coordinator.rcnotcreated] n
      ot created! vmcid: 0x0 minor code: 0 completed: No
       at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
       at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
       at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
       at java.lang.reflect.Constructor.newInstance(Unknown Source)
       at org.jacorb.orb.SystemExceptionHelper.read(SystemExceptionHelper.java:173)
       at org.jacorb.orb.ReplyReceiver.getReply(ReplyReceiver.java:326)
       at org.jacorb.orb.Delegate.invoke_internal(Delegate.java:963)
       at org.jacorb.orb.Delegate.invoke(Delegate.java:857)
       at org.omg.CORBA.portable.ObjectImpl._invoke(Unknown Source)
       at org.omg.CosTransactions._CoordinatorStub.register_resource(_CoordinatorStub.java:760)
       at com.arjuna.ats.internal.jts.orbspecific.interposition.resources.arjuna.ServerTopLevelAction.registerResource(ServerTopLevelAction
      .java:673)
       at com.arjuna.ats.internal.jts.orbspecific.interposition.resources.arjuna.ServerTopLevelAction.<init>(ServerTopLevelAction.java:130)
      
       at com.arjuna.ats.internal.jts.interposition.resources.arjuna.Interposition.createHierarchy(Interposition.java:174)
       at com.arjuna.ats.internal.jts.interposition.resources.arjuna.Interposition.setupHierarchy(Interposition.java:115)
       at com.arjuna.ats.internal.jts.interposition.resources.arjuna.Interposition.create(Interposition.java:74)
       at com.arjuna.ats.internal.jts.interposition.resources.arjuna.InterpositionCreator.recreateLocal(InterpositionCreator.java:48)
       at com.arjuna.ats.internal.jts.interposition.FactoryElement.recreateLocal(FactoryList.java:72)
       at com.arjuna.ats.internal.jts.interposition.FactoryList.recreateLocal(FactoryList.java:119)
       at com.arjuna.ats.internal.jts.orbspecific.TransactionFactoryImple.recreateLocal(TransactionFactoryImple.java:246)
       at com.arjuna.ats.internal.jts.context.ContextManager.createHierarchy(ContextManager.java:790)
       at com.arjuna.ats.internal.jts.context.ContextManager.currentPIContext(ContextManager.java:682)
       at com.arjuna.ats.internal.jts.context.ContextManager.current(ContextManager.java:212)
       at com.arjuna.ats.internal.jts.context.ContextManager.associate(ContextManager.java:363)
       at com.arjuna.ats.internal.jts.OTSImpleManager.current(OTSImpleManager.java:91)
       at com.arjuna.ats.internal.jta.transaction.jts.TransactionImple.getTransaction(TransactionImple.java:1173)
       at com.arjuna.ats.internal.jta.transaction.jts.TransactionManagerImple.getTransaction(TransactionManagerImple.java:74)
       at org.jboss.cache.interceptors.TxInterceptor.runPreparePhase(TxInterceptor.java:826)
       at org.jboss.cache.interceptors.TxInterceptor$LocalSynchronizationHandler.beforeCompletion(TxInterceptor.java:1109)
       at org.jboss.cache.interceptors.OrderedSynchronizationHandler.beforeCompletion(OrderedSynchronizationHandler.java:74)
       at com.arjuna.ats.internal.jta.resources.jts.orbspecific.SynchronizationImple.before_completion(SynchronizationImple.java:128)
       at org.omg.CosTransactions.SynchronizationPOA._invoke(SynchronizationPOA.java:42)
       at org.jacorb.poa.RequestProcessor.invokeOperation(RequestProcessor.java:299)
       at org.jacorb.poa.RequestProcessor.process(RequestProcessor.java:593)
       at org.jacorb.poa.RequestProcessor.run(RequestProcessor.java:735)
      2007-05-17 23:52:06,671 WARN [com.arjuna.ats.jts.logging.loggerI18N] - <[com.arjuna.ats.internal.jts.orbspecific.interposition.resources.arj
      una.ipfailed] ServerTopLevelAction - could not register interposed hierarchy!>
      2007-05-17 23:52:06,671 WARN [com.arjuna.ats.jts.logging.loggerI18N] - <[com.arjuna.ats.internal.jts.interposition.resources.arjuna.ipfail]
      Interposition.removeHeirarchy - could not find -3f57fefe:ab1:464d4d16:3 to remove.>
      


      Please let me know if you have any suggestions on how I might get past this issue. I've tried making sense of this stack trace and the WARN log records right before it but I feel I need an expert opinion to help get me moving again.

      I'm using:
      * JBOSSTS_4_2_3_GA
      * jacorb_2_2_1_patch
      * JBossCache-2.0.0.CR1
      * JDK5
      * All of the ext libs that shipped with the above distributions.

      Thanks in advance,
      Frank

        • 1. Re: JTA + JBoss Cache + Distributed Transactions
          jhalliday

          Hi Frank

          Sorry to hear you are having problems. Did you remember to start the RecoveryManager?

          java com.arjuna.ats.arjuna.recovery.RecoveryManager -test

          Jonathan.

          • 2. Re: JTA + JBoss Cache + Distributed Transactions
            nanreh

            Thanks Jonathan.

            Yes, I did remember to have the RecoveryManager working--it was started in a second shell. There were no errors or other messages in that shell and I'm confident that it's started correctly because the trailMap JTS example with distributed transactions works fine.

            thanks...
            Frank

            • 3. Re: JTA + JBoss Cache + Distributed Transactions
              jhalliday

              Send me your cache config file and jbossjts-properties.xml file please, I'll try to recreate the problem.

              • 4. Re: JTA + JBoss Cache + Distributed Transactions
                nanreh

                Thanks Jonathan, I really appreciate this. Here's the configuration I'm using that runs the JTA, JTS local, and JTS distributed trail_map examples without any problems.

                jbossjts-properties.xml - This is basically the default file that ships with JBoss Transactions 4.2.3. I edit it only to set the system properties that let me choose between local and distributed transactions. I also set the object store dir to point to a directory that exists and is writeable.

                <?xml version="1.0" encoding="UTF-8"?>
                <transaction-service>
                 <properties depends="common" name="arjuna">
                 <!--
                 Transaction Reaper Timeout (default is 120000 microseconds).
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.coordinator.txReaperTimeout" value="120000"/>
                 <!--
                 Transaction Reaper Mode, can be: NORMAL or DYNAMIC (default is NORMAL).
                 -->
                 <property name="com.arjuna.ats.arjuna.coordinator.txReaperMode" value="NORMAL"/>
                 <!--
                 (default is NO)
                 -->
                 <property name="com.arjuna.ats.arjuna.coordinator.asyncCommit" value="NO"/>
                 <!--
                 (default is NO)
                 -->
                 <property name="com.arjuna.ats.arjuna.coordinator.asyncPrepare" value="NO"/>
                 <!--
                 (default is YES)
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.coordinator.commitOnePhase" value="YES"/>
                 <!--
                 (default is defaultStore)
                 -->
                 <property name="com.arjuna.ats.arjuna.objectstore.localOSRoot" value="defaultStore"/>
                 <!--
                 default is under user.home - must be writeable!)
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.objectstore.objectStoreDir" value="C:\tmp"/>
                 <!--
                 (default is ON)
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.objectstore.objectStoreSync" value="ON"/>
                 <!--
                 (default is ShadowNoFileLockStore)
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.objectstore.objectStoreType" value="ShadowNoFileLockStore"/>
                 <!--
                 (default is 255)
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.objectstore.hashedDirectories" value="255"/>
                 <!--
                 (default is ON)
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.objectstore.transactionSync" value="ON"/>
                 <!--
                 (Must be unique across all Arjuna instances.)
                 -->
                 <property name="com.arjuna.ats.arjuna.xa.nodeIdentifier" value="1"/>
                 <!-- property
                 name="com.arjuna.ats.arjuna.coordinator.actionStore"
                 value="HashedActionStore"
                 value="JDBCActionStore"
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.objectstore.jdbcTxDbAccess"
                 value="JDBCAccess"
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.objectstore.objectStoreType"
                 value="ShadowNoFileLockStore"
                 value="JDBCStore"
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.objectstore.jdbcUserDbAccess"
                 value="JDBCAccess"
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.objectstore.jdbcPoolSizeInitial"
                 value="1"
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.objectstore.jdbcPoolSizeMaximum"
                 value="1"
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.objectstore.jdbcPoolPutConnections"
                 value="false"
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.internal.arjuna.objectstore.cacheStore.size"
                 value=""
                 -->
                 <!-- property
                 name="com.arjuna.ats.arjuna.internal.arjuna.objectstore.cacheStore.period"
                 value=""
                 -->
                 <!--
                 The location for creating temporary files, e.g., Uids.
                 Default is under user.home.
                 IMPORTANT: make sure the directory is lockable, e.g., /tmp on Unix
                 may not be!
                 -->
                 <!--
                 <property
                 name="com.arjuna.ats.arjuna.common.varDir"
                 value="var"/>
                 -->
                 </properties>
                 <properties name="common">
                 <!-- CLF 2.0 properties -->
                 <property name="com.arjuna.common.util.logging.DebugLevel"
                 type="System" value="0x00000000"/>
                 <property name="com.arjuna.common.util.logging.FacilityLevel"
                 type="System" value="0xffffffff"/>
                 <property name="com.arjuna.common.util.logging.VisibilityLevel"
                 type="System" value="0xffffffff"/>
                 <property name="com.arjuna.common.util.logger" type="System" value="log4j"/>
                 </properties>
                 <properties depends="arjuna" name="txoj">
                 <!--
                 (default is LockStore of installation - must be writeable!)
                 -->
                 <!--
                 <property
                 name="com.arjuna.ats.txoj.lockstore.lockStoreDir"
                 value="LockStore"/>
                 -->
                 <!--
                 (default is BasicLockStore)
                 -->
                 <property name="com.arjuna.ats.txoj.lockstore.lockStoreType" value="BasicLockStore"/>
                 <!--
                 (default is NO)
                 -->
                 <property name="com.arjuna.ats.txoj.lockstore.multipleLockStore" value="NO"/>
                 <!--
                 (default is YES)
                 -->
                 <property name="com.arjuna.ats.txoj.lockstore.singleLockStore" value="YES"/>
                 <!--
                 (default is YES)
                 -->
                 <property
                 name="com.arjuna.ats.txoj.lockstore.allowNestedLocking" value="YES"/>
                 </properties>
                 <properties depends="jts" name="jta">
                 <!--
                 Support subtransactions in the JTA layer?
                 Default is NO.
                 -->
                 <property name="com.arjuna.ats.jta.supportSubtransactions" value="NO"/>
                
                 <!-- distributed transaction setting -->
                 <property name="com.arjuna.ats.jta.jtaTMImplementation" value="com.arjuna.ats.internal.jta.transaction.jts.TransactionManagerImple"/>
                 <property name="com.arjuna.ats.jta.jtaUTImplementation" value="com.arjuna.ats.internal.jta.transaction.jts.UserTransactionImple"/>
                
                
                 <!-- local JTA transaction setting -->
                 <!--
                 <property name="com.arjuna.ats.jta.jtaTMImplementation" value="com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple"/>
                 <property name="com.arjuna.ats.jta.jtaUTImplementation" value="com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple"/>
                 -->
                
                 </properties>
                 <properties depends="jta" name="jdbc">
                 <!--
                 property name="com.arjuna.ats.jdbc.isolationLevel" value="TRANSACTION_SERIALIZABLE"/>
                 -->
                 </properties>
                 <properties depends="common" name="orbportability">
                 <property name="com.arjuna.orbportability.bindMechanism" value="CONFIGURATION_FILE"/>
                 <!--
                 The location of initial references file (default is user.home)
                 -->
                 <!--
                 <property
                 name="com.arjuna.orbportability.initialReferencesRoot"
                 value=""/>
                 -->
                 <!--
                 The name of the initial references file (default is CosServices.cfg)
                 -->
                 <property name="com.arjuna.orbportability.initialReferencesFile" value="CosServices.cfg"/>
                 <!--
                 When reading and writing IORs, they can be read/written in this
                 directory. (default is serviceName)
                 -->
                 <!--
                 <property
                 name="com.arjuna.orbportability.fileDir"
                 value=""/>
                 -->
                 <!--
                 Default resolution service for the Transaction Manager Server.
                 ORB specific.
                 -->
                 <!--
                 <property
                 name="com.arjuna.orbportability.resolveService"
                 value=""/>
                 -->
                 <!--
                 Event handlers.
                 -->
                 <!--
                 <property
                 name="com.arjuna.orbportability.eventHandler_0"
                 value=""/>
                 <property
                 name="com.arjuna.orbportability.eventHandler_1"
                 value=""/>
                 -->
                 <!--
                 The ORB implementation class - this defaults to the class which
                 implements support for the first supported ORB in your classpath.
                 -->
                 <!--
                 <property
                 name="com.arjuna.orbportability.orbImplementation"
                 value=""/>
                 -->
                 <!--
                 The OA implementation class - this also defaults to the class which
                 implements support for the first supported ORB in your classpath
                 -->
                 <!--
                 <property
                 name="com.arjuna.orbportability.oaImplementation"
                 value=""/>
                 -->
                 <!--
                 This class handles context propagation issues, and should never
                 be commented out or removed.
                 -->
                 <property name="com.arjuna.orbportability.orb.PreInit1" value="com.arjuna.ats.internal.jts.context.ContextPropagationManager"/>
                 <!--
                 This property ensures the JTS knows which ORB to use and should never
                 be commented out or removed
                 -->
                 <property name="com.arjuna.orbportability.orb.PostInit1" value="com.arjuna.ats.jts.utils.ORBSetup"/>
                 <!--
                 This property ensures the crash recovery is initialised correctly and
                 should never be commented out or removed
                 -->
                 <property name="com.arjuna.orbportability.orb.PostInit2" value="com.arjuna.ats.internal.jts.recovery.RecoveryInit"/>
                 <!--
                 This property ensures the JTS knows which ORB to use and should never
                 be commented out or removed
                 -->
                 <property name="com.arjuna.orbportability.orb.PostSet1" value="com.arjuna.ats.jts.utils.ORBSetup"/>
                 <!--
                 This property ensures the JTS knows which ORB to use and should never
                 be commented out or removed
                 -->
                 <property name="com.arjuna.orbportability.orb.PostSet2" value="com.arjuna.ats.internal.jts.recovery.RecoveryInit"/>
                 <!--
                 This property controls the port on which the Recovery ORB listens
                 -->
                 <property name="com.arjuna.ats.jts.recoveryManagerPort" value="4711"/>
                 </properties>
                 <properties depends="orbportability,arjuna" name="jts">
                 <!--
                 (default is NO)
                 -->
                 <property name="com.arjuna.ats.jts.transactionManager" value="NO"/>
                 <!--
                 (default is NO)
                 -->
                 <property name="com.arjuna.ats.jts.needTranContext" value="NO"/>
                 <!--
                 (default is NO)
                 -->
                 <property name="com.arjuna.ats.jts.alwaysPropagateContext" value="NO"/>
                 <!--
                 (default is NO)
                 -->
                 <property name="com.arjuna.ats.jts.checkedTransactions" value="NO"/>
                 <!--
                 (default is YES)
                 -->
                 <property name="com.arjuna.ats.jts.supportSubtransactions" value="YES"/>
                 <!--
                 (default is YES)
                 -->
                 <property name="com.arjuna.ats.jts.supportRollbackSync" value="YES"/>
                 <!--
                 (default is NO)
                 -->
                 <property
                 name="com.arjuna.ats.jts.supportInterposedSynchronization" value="NO"/>
                 <!--
                 Timeout in seconds to use for top-level transaction if 0 specified.
                 (default is no timeout)
                 -->
                 <!---
                 <property
                 name="com.arjuna.ats.jts.defaultTimeout"
                 value=""/>
                 -->
                 <!--
                 Propagate the context? (default is INTERPOSITION)
                 -->
                 <property name="com.arjuna.ats.jts.contextPropMode" value="INTERPOSITION"/>
                 </properties>
                 <properties depends="arjuna,txoj,jts" name="recoverymanager">
                 <!--
                 Properties used only by the RecoveryManager.
                 -->
                 <!--
                 Periodic recovery settings.
                 Time values in this section are in seconds.
                 -->
                 <!--
                 Interval in seconds between initiating the periodic recovery modules.
                 Default is 120 seconds.
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.periodicRecoveryPeriod" value="120"/>
                 <!--
                 Interval in seconds between first and second pass of periodic recovery.
                 Default is 10 seconds.
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryBackoffPeriod" value="10"/>
                 <!--
                 Periodic recovery modules to use. Invoked in sort-order of names.
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryExtension1" value="com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryExtension2" value="com.arjuna.ats.internal.txoj.recovery.TORecoveryModule"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryExtension3" value="com.arjuna.ats.internal.jts.recovery.transactions.TopLevelTransactionRecoveryModule"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryExtension4" value="com.arjuna.ats.internal.jts.recovery.transactions.ServerTransactionRecoveryModule"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryExtension5" value="com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryExtension6" value="com.arjuna.ats.internal.jta.recovery.jts.XARecoveryModule"/>
                 <!--
                 Recovery Activator to use.
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.recoveryActivator_1" value="com.arjuna.ats.internal.jts.orbspecific.recovery.RecoveryEnablement"/>
                 <!--
                 Expired entry removal
                 -->
                 <!--
                 Expiry scanners to use (order of invocation is random).
                 Names must begin with "com.arjuna.ats.arjuna.recovery.expiryScanner"
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.expiryScannerTransactionStatusManager" value="com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.expiryScannerContact" value="com.arjuna.ats.internal.jts.recovery.contact.ExpiredContactScanner"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.expiryScannerTopLevelTran" value="com.arjuna.ats.internal.jts.recovery.transactions.ExpiredToplevelScanner"/>
                 <property
                 name="com.arjuna.ats.arjuna.recovery.expiryScannerServerTran" value="com.arjuna.ats.internal.jts.recovery.transactions.ExpiredServerScanner"/>
                 <!--
                 Interval, in hours, between running the expiry scanners.
                 This can be quite long. The absolute value determines the interval -
                 if the value is negative, the scan will NOT be run until after one
                 interval has elapsed. If positive the first scan will be immediately
                 after startup. Zero will prevent any scanning.
                 Default = 12 = run immediately, then every 12 hours.
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.expiryScanInterval" value="12"/>
                 <!--
                 Age, in hours, for removal of transaction status manager item.
                 This should be longer than any ts-using process will remain running.
                 Zero = Never removed. Default is 12.
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.transactionStatusManagerExpiryTime" value="12"/>
                 <!--
                 Use this to fix the port on which the TransactionStatusManager listens,
                 The default behaviour is to use any free port.
                 -->
                 <property
                 name="com.arjuna.ats.arjuna.recovery.transactionStatusManagerPort" value="0"/>
                 </properties>
                </transaction-service>
                



                cache-configuration.xml - I'm using the sample cache configuration file from the JBoss Cache User's Guide with only one edit to provide my own TransactionManagerLookupClass. This configuration works fine in my test program--replication and transactions happen as expected except for the error when I select distributed transactions programmatically in the main() of my test program.

                <?xml version="1.0" encoding="UTF-8"?>
                
                <!-- ===================================================================== -->
                <!-- -->
                <!-- Sample JBoss Cache Service Configuration -->
                <!-- -->
                <!-- ===================================================================== -->
                
                <server>
                 <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
                
                 <!-- ==================================================================== -->
                 <!-- Defines JBoss Cache configuration -->
                 <!-- ==================================================================== -->
                
                 <mbean code="org.jboss.cache.CacheImpl" name="jboss.cache:service=Cache">
                 <depends>jboss:service=Naming</depends>
                 <depends>jboss:service=TransactionManager</depends>
                
                 <!-- Configure the TransactionManager -->
                 <!--
                 <attribute name="TransactionManagerLookupClass">org.jboss.cache.transaction.GenericTransactionManagerLookup</attribute>
                 -->
                 <!-- Use our custom TxManagerLookup class -->
                 <attribute name="TransactionManagerLookupClass">org.defy.tx.CustomTxManagerLookup</attribute>
                
                 <!--
                 Node locking level : SERIALIZABLE
                 REPEATABLE_READ (default)
                 READ_COMMITTED
                 READ_UNCOMMITTED
                 NONE
                 -->
                 <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
                
                 <!-- Lock parent before doing node additions/removes -->
                 <attribute name="LockParentForChildInsertRemove">true</attribute>
                
                 <!--
                 Valid modes are LOCAL
                 REPL_ASYNC
                 REPL_SYNC
                 INVALIDATION_ASYNC
                 INVALIDATION_SYNC
                 -->
                 <attribute name="CacheMode">REPL_SYNC</attribute>
                
                 <!-- Name of cluster. Needs to be the same for all JBoss Cache nodes in a
                 cluster in order to find each other. -->
                
                 <attribute name="ClusterName">ACS_CLUSTER</attribute>
                
                 <!--Uncomment next three statements to enable JGroups multiplexer.
                 This configuration is dependent on the JGroups multiplexer being
                 registered in an MBean server such as JBossAS. -->
                 <!--
                 <depends>jgroups.mux:name=Multiplexer</depends>
                 <attribute name="MultiplexerService">jgroups.mux:name=Multiplexer</attribute>
                 <attribute name="MultiplexerStack">fc-fast-minimalthreads</attribute>
                 -->
                
                 <!-- JGroups protocol stack properties.
                 ClusterConfig isn't used if the multiplexer is enabled and successfully initialized.
                 -->
                 <attribute name="ClusterConfig">
                 <config>
                 <!-- UDP: if you have a multihomed machine,
                 set the bind_addr attribute to the appropriate NIC IP address -->
                 <!-- UDP: On Windows machines, because of the media sense feature
                 being broken with multicast (even after disabling media sense)
                 set the loopback attribute to true -->
                 <UDP mcast_addr="228.1.2.3" mcast_port="48866"
                 ip_ttl="64" ip_mcast="true"
                 mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
                 ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
                 loopback="true"/>
                 <PING timeout="2000" num_initial_members="3"
                 up_thread="false" down_thread="false"/>
                 <MERGE2 min_interval="10000" max_interval="20000"/>
                 <FD shun="true" up_thread="true" down_thread="true"/>
                 <VERIFY_SUSPECT timeout="1500"
                 up_thread="false" down_thread="false"/>
                 <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
                 max_xmit_size="8192" up_thread="false" down_thread="false"/>
                 <UNICAST timeout="600,1200,2400" down_thread="false"/>
                 <pbcast.STABLE desired_avg_gossip="20000"
                 up_thread="false" down_thread="false"/>
                 <FRAG frag_size="8192"
                 down_thread="false" up_thread="false"/>
                 <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
                 shun="true" print_local_addr="true"/>
                 <pbcast.STATE_TRANSFER up_thread="false" down_thread="false"/>
                 </config>
                 </attribute>
                
                
                 <!--
                 The max amount of time (in milliseconds) we wait until the
                 initial state (ie. the contents of the cache) are retrieved from
                 existing members in a clustered environment
                 -->
                 <attribute name="InitialStateRetrievalTimeout">20000</attribute>
                
                 <!--
                 Number of milliseconds to wait until all responses for a
                 synchronous call have been received.
                 -->
                 <attribute name="SyncReplTimeout">20000</attribute>
                
                 <!-- Max number of milliseconds to wait for a lock acquisition -->
                 <attribute name="LockAcquisitionTimeout">15000</attribute>
                
                 <!-- Specific eviction policy configurations. This is LRU -->
                 <attribute name="EvictionPolicyConfig">
                 <config>
                 <attribute name="wakeUpIntervalSeconds">5</attribute>
                 <!-- This defaults to 200000 if not specified -->
                 <attribute name="eventQueueSize">200000</attribute>
                 <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
                
                 <!-- Cache wide default -->
                 <region name="/_default_">
                 <attribute name="maxNodes">5000</attribute>
                 <attribute name="timeToLiveSeconds">1000</attribute>
                 </region>
                 <region name="/org/jboss/data">
                 <attribute name="maxNodes">5000</attribute>
                 <attribute name="timeToLiveSeconds">1000</attribute>
                 </region>
                 <region name="/org/jboss/test/data">
                 <attribute name="maxNodes">5</attribute>
                 <attribute name="timeToLiveSeconds">4</attribute>
                 </region>
                 <region name="/test">
                 <attribute name="maxNodes">10000</attribute>
                 <attribute name="timeToLiveSeconds">4</attribute>
                 </region>
                 <region name="/maxAgeTest">
                 <attribute name="maxNodes">10000</attribute>
                 <attribute name="timeToLiveSeconds">8</attribute>
                 <attribute name="maxAgeSeconds">10</attribute>
                 </region>
                 </config>
                 </attribute>
                 </mbean>
                </server>
                


                Thanks again and let me know if anything jumps out at you as wrong.

                Frank

                • 5. Re: JTA + JBoss Cache + Distributed Transactions
                  jhalliday

                  I can reproduce the same error when the RecoveryManager is not running or when it is using a different objectStoreDir. Since you say it's running, the latter seems more likely. Ensure the RecoveryManager process and the Main one are reading the same jbossjts-properties file and that the ObjectStore path given in it is absolute not relative. The config file is found via the classpath, so the easiest way to do this is to ensure you start both processes using the same classpath value.

                  • 6. Re: JTA + JBoss Cache + Distributed Transactions
                    nanreh

                    Thank you, that was the problem. My test program now works as expected.

                    I really appreciate you setting this up on your end and trying it out--it was a great help.

                    Have a nice weekend,
                    Frank

                    • 7. Re: JTA + JBoss Cache + Distributed Transactions
                      jhalliday

                      The RecoveryManager writes its IOR into the objectStoreDir, from which the application reads it. If they use different stores the app can't find the RM and behaves as though it's not running. The error is difficult to diagnose the first time you see it - I got caught out by it myself in the past. I'm glad things are working for you now.