[jboss-cvs] JBossAS SVN: r81364 - in branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428: cluster/src/main/org/jboss/invocation/jrmp/interfaces and 7 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Nov 20 09:49:58 EST 2008


Author: galder.zamarreno at jboss.com
Date: 2008-11-20 09:49:58 -0500 (Thu, 20 Nov 2008)
New Revision: 81364

Added:
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java
Modified:
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/build.xml
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/local.properties
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHaTransactionSticky.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaFailureType.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaInfrastructure.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaTransactionalMockUtils.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaMockUtils.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaTransactionStickyUnitTestCase.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/ejb/test/UserTransactionStickyUnitTestCase.java
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/cluster/invokerha/ejb/META-INF/jboss.xml
   branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/test-configs/ustxsticky/conf/jboss-service.xml
Log:
[JBPAPP-1428] Move transaction sticky logic from proxy to interceptors to make a clearer separation of concerns and so that we don't have to take all invocation
returns and put them in sticky target map in case they're tpc, which can become a bottleneck.

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/build.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/build.xml	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/build.xml	2008-11-20 14:49:58 UTC (rev 81364)
@@ -283,6 +283,7 @@
         <include name="org/jboss/invocation/unified/interfaces/**"/>
         <include name="org/jboss/invocation/InvokerProxyHA**"/>
         <include name="org/jboss/ha/**/*Stub.class"/>
+        <include name="org/jboss/proxy/*"/>         
         <include name="org/jboss/ha/framework/test/ExplicitFailoverClientInterceptor.class"/>
       </fileset>
     </jar>

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -29,6 +29,8 @@
 import java.rmi.RemoteException;
 import java.rmi.ServerException;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Map;
 import java.util.WeakHashMap;
 
 import javax.transaction.SystemException;
@@ -66,7 +68,7 @@
     */ 
    private static final long serialVersionUID = -967671822225981666L;
    private static final Logger log = Logger.getLogger(JRMPInvokerProxyHA.class);
-   public static final WeakHashMap txFailoverAuthorizations = new WeakHashMap();
+   public static final Map txFailoverAuthorizations = Collections.synchronizedMap(new WeakHashMap());
 
    protected LoadBalancePolicy loadBalancePolicy;
    protected String proxyFamilyName = null;
@@ -134,34 +136,16 @@
       Object tpc = getTransactionPropagationContext();
       if (tpc != null)
       {
-         synchronized (tpc)
+         if (trace)
          {
-            if (trace)
-            {
-               log.trace("Checking tx failover authorisation map with tpc " + tpc);
-            }
-            
-            /* If the map contains the tpc, then we can't allow a failover */
-            boolean failoverAuthorised = ! txFailoverAuthorizations.containsKey(tpc);
-            
-            if (failoverAuthorised)
-            {
-               if (trace) 
-               {
-                  log.trace("Failover authorised, so we remove the sticky target associated with tpc " + tpc);
-               }
-               
-               txFailoverAuthorizations.put(tpc, null);
-               invocation.getTransientPayload().put("TX_STICKY_TARGET", null);
-            }
-            
-            return failoverAuthorised;     
+            log.trace("Checking tx failover authorisation map with tpc " + tpc);
          }
+         
+         /* If the map contains the tpc, then we can't allow a failover */
+         return ! txFailoverAuthorizations.containsKey(tpc);            
       }
-      else
-      {
-         return true;
-      }
+
+      return true;
    }
    
    public void invocationHasReachedAServer (Invocation invocation)
@@ -169,22 +153,7 @@
       Object tpc = getTransactionPropagationContext();
       if (tpc != null)
       {
-         synchronized (tpc)
-         {
-            if (trace)
-            {
-               log.trace("After reaching the server, transaction propagation context (tpc) is " + tpc);
-            }
-            
-            Object stickyTarget = invocation.getTransientValue("TX_STICKY_TARGET");
-            
-            if (trace && stickyTarget != null)
-            {
-               log.trace("Remember transaction bound target[" + stickyTarget + "] for tpc[" + tpc + "]");
-            }
-            
-            txFailoverAuthorizations.put(tpc, stickyTarget);
-         }
+         txFailoverAuthorizations.put(tpc, null);
       }
    }
 
@@ -201,9 +170,6 @@
       int failoverCounter = 0;
       invocation.setValue ("FAILOVER_COUNTER", new Integer(failoverCounter), PayloadKey.AS_IS);
       
-      // If transaction sticky, put chosen target
-      putIfExistsTransactionTarget(invocation, getTransactionPropagationContext());
-
       // We are going to go through a Remote invocation, switch to a Marshalled Invocation
       MarshalledInvocation mi = new MarshalledInvocation(invocation);
 
@@ -405,45 +371,6 @@
       return tpc;
    }
 
-   /**
-    * Called at the beginning of the invocation to check whether the current tpc
-    * is already present in the tx failover map. If it is, get the chosen 
-    * target associated to it and add it to the invocation transient payload so 
-    * that the load balance policy can choose the right target.
-    */
-   protected void putIfExistsTransactionTarget(Invocation invocation, Object tpc) throws Exception
-   {
-      if (tpc != null)
-      {
-         synchronized (tpc)
-         {
-            if (trace)
-            {
-               log.trace("In the proxy, transaction propagation context (tpc) is " + tpc);
-            }
-
-            Object stickyTarget = txFailoverAuthorizations.get(tpc);
-               
-            if (stickyTarget != null)
-            {
-               if (familyClusterInfo.getTargets().contains(stickyTarget))
-               {
-                  if (trace) 
-                  {
-                     log.trace("Put transaction bound target into transient payload: " + stickyTarget);                  
-                  }
-                  
-                  invocation.getTransientPayload().put("TX_STICKY_TARGET", stickyTarget);                  
-               }
-               else
-               {
-                  throw new ServerException("Transaction sticky target is no longer available, so invocation needs to be halted");
-               }
-            }
-         }
-      }
-   }     
-   
    // Private -------------------------------------------------------
 
    // Inner classes -------------------------------------------------

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -104,50 +104,26 @@
    public boolean txContextAllowsFailover(Invocation invocation)
    {
       Object tpc = getTransactionPropagationContext();
-      if(tpc != null)
+      if (tpc != null)
       {
          if (trace)
          {
             log.trace("Checking tx failover authorisation map with tpc " + tpc);
          }
+         
+         /* If the map contains the tpc, then we can't allow a failover */
+         return ! txFailoverAuthorizations.containsKey(tpc);
+      }      
 
-         /* Synchronise on tpc because we're updating the map if it doesn't 
-          * contain tpc upon failover (putIfAbsent type of operation). This is 
-          * still needed even if the collection is synchronized. */
-         synchronized(tpc)
-         {
-            /* If the map contains the tpc, then we can't allow a failover */
-            boolean failoverAuthorised = ! txFailoverAuthorizations.containsKey(tpc);
-            
-            if (failoverAuthorised)
-            {
-               if (trace) 
-               {
-                  log.trace("Failover authorised, so we remove the sticky target associated with tpc " + tpc);
-               }
-               
-               invocation.getTransientPayload().put("TX_STICKY_TARGET", null);
-            }
-            
-            return failoverAuthorised;         
-         }
-      }
-      
-      return true;
+      return true;      
    }
 
-   public void invocationHasReachedAServer(Invocation invocation, Object response)
+   public void invocationHasReachedAServer(Invocation invocation)
    {
       Object tpc = getTransactionPropagationContext();
-      /* Idea here is you store the return value if there's no TPC, on the 
-       * chance it is a TPC.  This won't leak anything since it's a WeakHashMap. 
-       * When you do a txFailoverAuthorization.get() it's always passing a TPC 
-       * as the key, so you won't accidentally find some random object you put 
-       * in the map.*/
-      Object key = (tpc == null) ? response : tpc;
-      if(key != null)
+      if(tpc != null)
       {
-         rememberTransactionTarget(invocation, key);
+         txFailoverAuthorizations.put(tpc, null);
       }
    }
 
@@ -204,9 +180,6 @@
       int failoverCounter = 0;
       invocation.setValue("FAILOVER_COUNTER", new Integer(failoverCounter), PayloadKey.AS_IS);
 
-      // If transaction sticky, put chosen target
-      putIfExistsTransactionTarget(invocation, getTransactionPropagationContext());      
-      
       Object response = null;
       Exception lastException = null;
 
@@ -281,7 +254,7 @@
                   }
                   else
                   {
-                     invocationHasReachedAServer(invocation, null);
+                     invocationHasReachedAServer(invocation);
                      throw new ServerException("Clustering error", gcex);
                   }
                }
@@ -311,7 +284,7 @@
             }
             
             response = haResponse.response;
-            invocationHasReachedAServer(invocation, response);
+            invocationHasReachedAServer(invocation);
             return response;
 
          }
@@ -365,7 +338,7 @@
             }
             else
             {
-               invocationHasReachedAServer(invocation, null);
+               invocationHasReachedAServer(invocation);
                throw new ServerException("Clustering error", gcex);
             }
          }
@@ -541,62 +514,5 @@
          log.trace("Using tpc factory " + tpcFactory);
       }      
       return (tpcFactory == null) ? null : tpcFactory.getTransactionPropagationContext();
-   }
-   
-   /**
-    * Called at the beginning of the invocation to check whether the current tpc
-    * is already present in the tx failover map. If it is, get the chosen 
-    * target associated to it and add it to the invocation transient payload so 
-    * that the load balance policy can choose the right target  as long as the 
-    * target is available in the cluster family. Otherwise, invocation needs to 
-    * be halted because a previous invocation within the transaction succeeded 
-    * (tx sticky target was set), so we can't failover to a different node.
-    */
-   protected void putIfExistsTransactionTarget(Invocation invocation, Object tpc) throws Exception
-   {
-      if (tpc != null)
-      {
-         if (trace)
-         {
-            log.trace("In the proxy, transaction propagation context (tpc) is " + tpc);
-            log.trace("Contains key returns " + txFailoverAuthorizations.containsKey(tpc));
-         }
-
-         Object stickyTarget = txFailoverAuthorizations.get(tpc);
-            
-         if (stickyTarget != null)
-         {
-            if (familyClusterInfo.getTargets().contains(stickyTarget))
-            {
-               if (trace) 
-               {
-                  log.trace("Put transaction bound target into transient payload: " + stickyTarget);                  
-               }
-               
-               invocation.getTransientPayload().put("TX_STICKY_TARGET", stickyTarget);                  
-            }
-            else
-            {
-               throw new ServerException("Transaction sticky target is no longer available, so invocation needs to be halted");
-            }
-         }
-      }
-   }
-   
-   protected void rememberTransactionTarget(Invocation invocation, Object target)
-   {
-      if (trace)
-      {
-         log.trace("After reaching the server, transaction propagation context (tpc) is " + target);
-      }
-      
-      Object stickyTarget = invocation.getTransientValue("TX_STICKY_TARGET");
-      
-      if (trace && stickyTarget != null)
-      {
-         log.trace("Remember transaction bound target [" + stickyTarget + "] for tpc " + target);
-      }
-      
-      txFailoverAuthorizations.put(target, stickyTarget);
-   }   
+   } 
 }
\ No newline at end of file

Added: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -0,0 +1,197 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.proxy;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.jboss.ha.framework.interfaces.ClusteringTargetsRepository;
+import org.jboss.ha.framework.interfaces.FamilyClusterInfo;
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.InvocationContext;
+import org.jboss.invocation.Invoker;
+import org.jboss.invocation.ServiceUnavailableException;
+import org.jboss.invocation.unified.interfaces.UnifiedInvokerHAProxy;
+import org.jboss.logging.Logger;
+import org.jboss.tm.TransactionPropagationContextFactory;
+import org.jboss.tm.TransactionPropagationContextUtil;
+
+/**
+ * Parent transaction sticky interceptor that encapsulates sticky target map 
+ * and exposes operations on this map.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public abstract class AbstractTransactionStickyInterceptor extends Interceptor
+{
+   private static final Map txStickyTargets = Collections.synchronizedMap(new WeakHashMap());
+   
+   private FamilyClusterInfo familyClusterInfo;
+   
+   protected final Logger log = Logger.getLogger(getClass());
+   
+   protected static boolean trace = false;
+   
+   public AbstractTransactionStickyInterceptor()
+   {
+      trace = log.isTraceEnabled();
+   }
+   
+   /**
+    * Called at the beginning of the invocation to check whether the current tpc
+    * is already present in the tx sticky target. If it is, get the chosen 
+    * target associated to it and add it to the invocation transient payload so 
+    * that the load balance policy can choose the right target  as long as the 
+    * target is available in the cluster family. Otherwise, invocation needs to 
+    * be halted because a previous invocation within the transaction succeeded 
+    * (tx sticky target was set), so we can't failover to a different node.
+    * 
+    * @param invocation Invocation object where transaction sticky will be set 
+    * if present.
+    */
+   protected void putIfExistsTransactionTarget(Invocation invocation) throws Exception
+   {
+      Object tpc = getTransactionPropagationContext();
+      
+      if (tpc != null)
+      {
+         if (trace)
+         {
+            log.trace("In the proxy, transaction propagation context (tpc) is " + tpc);
+            log.trace("Contains key returns " + txStickyTargets.containsKey(tpc));
+         }
+
+         Object stickyTarget = txStickyTargets.get(tpc);
+            
+         if (stickyTarget != null)
+         {            
+            if (getFamilyClusterInfo(invocation).getTargets().contains(stickyTarget))
+            {
+               if (trace) 
+               {
+                  log.trace("Put transaction bound target into transient payload: " + stickyTarget);                  
+               }
+               
+               invocation.getTransientPayload().put("TX_STICKY_TARGET", stickyTarget);                  
+            }
+            else
+            {
+               throw new ServiceUnavailableException("Transaction sticky target is no longer available, so invocation needs to be halted");
+            }
+         }
+      }
+   }
+   
+   /**
+    * Method called to remember the sticky target associated with a transaction
+    * context. 
+    * 
+    * @param invocation Invocation object from which the TX_STICKY_TARGET 
+    * transient value comes from.
+    * @param tpc Transaction propagation context.
+    */
+   protected void rememberTransactionTarget(Invocation invocation, Object tpc)
+   {
+      if (trace)
+      {
+         log.trace("After reaching the server, transaction propagation context (tpc) is " + tpc);
+      }
+      
+      Object stickyTarget = invocation.getTransientValue("TX_STICKY_TARGET");
+      
+      if (stickyTarget != null)
+      {
+         if (trace)
+         {
+            log.trace("Remember transaction bound target [" + stickyTarget + "] for tpc " + tpc);
+         }
+
+         txStickyTargets.put(tpc, stickyTarget);
+         
+         /* Put it in invoker proxy txFailoverAuthorizations to avoid failover being
+          * allowed if the 1st EJB invocation within user trasnsaction fails with 
+          * GenericClusteringException.COMPLETED_NO */
+         UnifiedInvokerHAProxy.txFailoverAuthorizations.put(tpc, null);
+      }
+   }   
+
+   @Override
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      super.readExternal(in);
+      trace = log.isTraceEnabled();
+   }
+   
+   protected Object getTransactionPropagationContext()
+   {
+      TransactionPropagationContextFactory tpcFactory = TransactionPropagationContextUtil.getTPCFactoryClientSide();
+      if (trace)
+      {
+         log.trace("Using tpc factory " + tpcFactory);
+      }      
+      return (tpcFactory == null) ? null : tpcFactory.getTransactionPropagationContext();
+   }
+   
+   protected synchronized FamilyClusterInfo getFamilyClusterInfo(Invocation invocation) throws Exception
+   {
+      if (familyClusterInfo == null)
+      {
+         familyClusterInfo = ClusteringTargetsRepository.getFamilyClusterInfo(getProxyFamilyName(invocation));
+      }
+      
+      return familyClusterInfo;
+   }
+   
+   protected String getProxyFamilyName(Invocation invocation) throws Exception
+   {
+      InvocationContext ctx = invocation.invocationContext;
+      Invoker invoker = ctx.getInvoker();
+      
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      ObjectOutputStream oos = new ObjectOutputStream(baos);
+      ((Externalizable)invoker).writeExternal(oos);
+      oos.close();
+      byte[] bytes = baos.toByteArray();
+      
+      ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+      ObjectInputStream ois = new ObjectInputStream(bais);
+
+      /* version, uri and strictRMIException are UnifiedInvokerHAProxy specific */
+      ois.readInt(); // int version
+      ois.readUTF(); // String uri
+      ois.readBoolean(); // boolean strictRMIException 
+      ois.readObject(); // Object targets  
+      ois.readObject(); // Object loadBalancePolicy
+      String proxyFamilyName = (String) ois.readObject();
+      ois.close();
+      
+      return proxyFamilyName;
+   }
+}

Added: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.proxy;
+
+import org.jboss.invocation.Invocation;
+
+/**
+ * The ClientUserTransactionStickyInterceptor should be used as an interceptor
+ * for the HA proxy in the ClientUserTransactionService. The aim of this 
+ * interceptor is twofold: First, when UserTransaction.begin() is called, the 
+ * result of the invocation, which is the transaction propagation context of 
+ * the transaction started, is stored together with the target server used, so 
+ * that future invocations can make use of the sticky target. Secondly, for the
+ * rest of UserTransaction invocations, i.e. commit(), getStatus()...etc, the 
+ * current tpc is retrieved and the sticky target is located and added to the 
+ * transient payload of the invocation.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class ClientUserTransactionStickyInterceptor extends AbstractTransactionStickyInterceptor
+{
+   @Override
+   public Object invoke(Invocation invocation) throws Throwable
+   {
+      putIfExistsTransactionTarget(invocation);
+      Object response = getNext().invoke(invocation); 
+      invocationHasReachedAServer(invocation, response);
+      return response;
+   }
+
+   public void invocationHasReachedAServer(Invocation invocation, Object response)
+   {
+      Object tpc = getTransactionPropagationContext();
+      if (tpc == null)
+      {
+         /* If tpc is null when invoking a UserTransaction operation, begin() 
+          * is being called, so we remember the target where the transaction 
+          * was started.
+          */
+         rememberTransactionTarget(invocation, response);
+      }
+   }
+}

Added: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.proxy;
+
+import org.jboss.invocation.Invocation;
+
+/**
+ * Transaction sticky interceptor targeted for Home and Bean invocations. This 
+ * interceptor will put, if exists, the transaction sticky target into the 
+ * transient payload in the invocation so that the transaction sticky load 
+ * balance policy can use it.  
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class TransactionStickyInterceptor extends AbstractTransactionStickyInterceptor
+{
+   @Override
+   public Object invoke(Invocation invocation) throws Throwable
+   {
+      putIfExistsTransactionTarget(invocation);
+      return getNext().invoke(invocation); 
+   }
+}

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/local.properties
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/local.properties	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/local.properties	2008-11-20 14:49:58 UTC (rev 81364)
@@ -34,12 +34,12 @@
 #
 # Now you can define MYTESTIP_1 and MYTESTIP_2 in your environment.
 #
-#node0=${env.MYTESTIP_1}
+node0=${env.MYTESTIP_1}
 #node0.http.url=http://192.168.1.103:8080
 #node0.jndiurl=jnp://192.168.1.103:1099
 #node0.hajndi.url=jnp://192.168.1.103:1100
 
-#node1=${env.MYTESTIP_2}
+node1=${env.MYTESTIP_2}
 #node1.http.url=http://192.168.1.113:8080
 #node1.jndiurl=jnp://192.168.1.113:1099
 #node1.hajndi.url=jnp://192.168.1.113:1100
@@ -57,4 +57,4 @@
 #org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
 #org.apache.commons.logging.simplelog.showdatetime=true
 #org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient=debug
-#org.apache.commons.logging.simplelog.log.httpclient.wire.header=error
\ No newline at end of file
+#org.apache.commons.logging.simplelog.log.httpclient.wire.header=error

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHa.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -65,6 +65,8 @@
    
    Invoker systemTimeProxy;
    
+   Invoker clientUserTransactionProxy;
+   
    Object prevChosenTargetDateTimeTeller;
    
    Object prevChosenTargetSystemTimeTeller;
@@ -87,9 +89,11 @@
       
       infrastructure.createDateTimeTeller();
       infrastructure.createSystemTimeTeller();
+      infrastructure.createClientUserTransactionService();
 
       infrastructure.deployDateTimeTeller();
       infrastructure.deploySystemTimeTeller();
+      infrastructure.deployClientUserTransactionService();
    }
 
    @Override
@@ -101,6 +105,7 @@
       
       infrastructure.undeployDateTimeTeller();
       infrastructure.undeploySystemTimeTeller();
+      infrastructure.undeployClientUserTransactionService();
       
       infrastructure.undeployServers();
    }
@@ -247,6 +252,7 @@
       /* Create a proxy instances retrieved from the first server */
       timeTellerProxy = infrastructure.createDateTimeTellerProxy(serverIndex, policyClass);
       systemTimeProxy = infrastructure.createSystemTimeTellerProxy(serverIndex, policyClass);
+      clientUserTransactionProxy = infrastructure.createClientUserTransactionProxy(serverIndex, policyClass);
       
       /* Initialise previous chosen targets. If not new proxies elected 
        * between transactions, this allows to carry on checking chosen 

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHaTransactionSticky.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHaTransactionSticky.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/AbstractInvokerHaTransactionSticky.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -21,14 +21,13 @@
  */
 package org.jboss.test.cluster.invokerha;
 
-import java.rmi.ServerException;
-import java.rmi.server.UID;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 import javax.transaction.Transaction;
+import javax.transaction.UserTransaction;
 
 import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
 import org.jboss.ha.framework.interfaces.TransactionStickyFirstAvailable;
@@ -36,9 +35,12 @@
 import org.jboss.ha.framework.interfaces.TransactionStickyRandomRobin;
 import org.jboss.ha.framework.interfaces.TransactionStickyRoundRobin;
 import org.jboss.invocation.Invocation;
+import org.jboss.invocation.Invoker;
 import org.jboss.invocation.InvokerProxyHA;
+import org.jboss.invocation.ServiceUnavailableException;
 import org.jboss.logging.Logger;
-import org.jboss.test.cluster.invokerha.InvokerHaTransactionalMockUtils.MockTransaction;
+import org.jboss.test.cluster.invokerha.InvokerHaTransactionalMockUtils.MockUserTransaction;
+import org.jboss.test.cluster.invokerha.InvokerHaTransactionalMockUtils.MockTransactionStickyInterceptor;;
 
 /**
  * AbstractInvokerHaTransactionSticky.
@@ -161,28 +163,24 @@
       
       try
       {
-         UID uid;
-         
          createNewProxies(0, policyClass, true);
 
-         /* Simulate client user transaction */
-         uid = new UID();         
-         transactionalMockUtils.getTpcf().setUid(uid);
+         UserTransaction ut = new MockUserTransaction(clientUserTransactionProxy, infrastructure);
+         ut.begin();
          performTransactionalStickyCalls(3, null, policyClass, newProxiesInBetweenTransactions);
+         ut.commit();
          /* either set would do because they should be the same */
          Set<Object> chosenTargetsTx1 = chosenTargets;
          
          if (newProxiesInBetweenTransactions)
          {
+            ut = new MockUserTransaction(clientUserTransactionProxy, infrastructure);
             createNewProxies(0, policyClass, false);
          }
          
-         /* Simulate transaction interceptor */
-         uid = new UID();
-         Transaction tx = new MockTransaction();
-         transactionalMockUtils.getTpcf().setUid(uid);
-         transactionalMockUtils.getTpci().setTransaction(tx);
-         performTransactionalStickyCalls(3, tx, policyClass, newProxiesInBetweenTransactions);
+         ut.begin();
+         performTransactionalStickyCalls(3, null, policyClass, newProxiesInBetweenTransactions);
+         ut.commit();
          /* either set would do because they should be the same */
          Set<Object> chosenTargetsTx2 = chosenTargets;
          
@@ -204,10 +202,11 @@
       
       try
       {
-         UID uid = new UID();
          createNewProxies(0, policyClass, true);
-         transactionalMockUtils.getTpcf().setUid(uid);
+         UserTransaction ut = new MockUserTransaction(clientUserTransactionProxy, infrastructure);
+         ut.begin();
          performTransactionalCallsWithNodeShutdown(null, policyClass);
+         ut.commit();
       }
       catch(Exception e)
       {
@@ -249,14 +248,14 @@
          /* create invocation to date time teller */
          inv = infrastructure.createDateTimeTellerInvocation(tx, null);
          /* invoke on proxy passing the invocation */
-         log.debug(timeTellerProxy.invoke(inv));
+         log.debug(invokeTimeTellerProxy(inv));
          /* assert post conditions after invocation */
          chosenTargetsDateTimeTeller = assertSuccessfulPostConditions(inv, chosenTargetsDateTimeTeller);
          
          /* create invocation to system time teller */
          inv = infrastructure.createSystemTimeTellerInvocation(tx, null);
          /* invoke on proxy passing the invocation */
-         log.debug(systemTimeProxy.invoke(inv));
+         log.debug(invokeSystemTimeProxy(inv));
          /* assert post conditions after invocation */
          chosenTargetsSystemTimeTeller = assertSuccessfulPostConditions(inv, chosenTargetsSystemTimeTeller);
       }
@@ -276,6 +275,8 @@
       assertTrue("transaction should have reached the server", invokerHaFactory.getTxFailoverAuthorizationsMap().containsKey(transactionalMockUtils.getTpcf().getUid()));
       /* add target to singleton set, there must only be one different target within a transaction */
       chosenTargets.add(chosenTarget);
+      log.debug("Chosen target in this invocation: " + chosenTarget);
+      log.debug("All chosen targets in this transaction: " + chosenTargets);
       assertEquals(1, chosenTargets.size());
       
       return chosenTargets;
@@ -291,7 +292,7 @@
       /* create invocation to date time teller */
       inv = infrastructure.createDateTimeTellerInvocation(tx, null);
       /* invoke on proxy passing the invocation */
-      log.debug(timeTellerProxy.invoke(inv));
+      log.debug(invokeTimeTellerProxy(inv));
       /* assert post conditions after invocation */
       chosenTargetsDateTimeTeller = assertSuccessfulPostConditions(inv, chosenTargetsDateTimeTeller);
       
@@ -301,13 +302,13 @@
       inv = infrastructure.createDateTimeTellerInvocation(tx, null);
       try
       {
-         log.debug(timeTellerProxy.invoke(inv));
+         log.debug(invokeTimeTellerProxy(inv));
          fail("Should have thrown an exception because sticky target is no longer available");
       }
       catch(Exception e)
       {
          log.debug("Expected exception", e);
-         assertTrue(e instanceof ServerException || e.getCause() instanceof ServerException);
+         assertTrue(e.getCause() instanceof ServiceUnavailableException);
       }
    }
    
@@ -356,15 +357,21 @@
       try 
       {
          /* fail in 1st call */
+         UserTransaction ut = new MockUserTransaction(clientUserTransactionProxy, infrastructure);
+         ut.begin();
          failureCall(failureType, true, policyClass, newProxiesInBetweenFailures);
+         ut.commit();
          
          if (newProxiesInBetweenFailures)
          {
+            ut = new MockUserTransaction(clientUserTransactionProxy, infrastructure);
             createNewProxies(0, policyClass, false);            
          }
          
          /* fail in Nth call */
+         ut.begin();
          failureCall(failureType, false, policyClass, newProxiesInBetweenFailures);
+         ut.commit();
       }
       catch(Exception e)
       {
@@ -377,38 +384,31 @@
    
    protected void failureCall(InvokerHaFailureType failureType, boolean injectFailureIn1stCall, Class<? extends LoadBalancePolicy> policyClass, boolean newProxiesInBetweenFailures) throws Exception
    {
-      UID uid;
       Invocation inv;
       
       if (injectFailureIn1stCall)
       {
-         uid = new UID();         
-         transactionalMockUtils.getTpcf().setUid(uid);
          /* When failure must happen in the very 1st call, we create a 1st 
           * invocation with the failure injected */
          inv = infrastructure.createDateTimeTellerInvocation(null, failureType);         
       }
       else
       {
-         uid = new UID();
-         Transaction tx = new MockTransaction();
-         transactionalMockUtils.getTpcf().setUid(uid);
-         transactionalMockUtils.getTpci().setTransaction(tx);
          /* When failure is not in first call, we do a call to each bean before 
           * injecting the faliure */
-         performTransactionalStickyCalls(1, tx, policyClass, newProxiesInBetweenFailures);
+         performTransactionalStickyCalls(1, null, policyClass, newProxiesInBetweenFailures);
          /* Now we create the invocation with the failure injected */
          inv = infrastructure.createDateTimeTellerInvocation(null, failureType);
       }
       
       try 
       {
-         log.debug(timeTellerProxy.invoke(inv));
+         log.debug(invokeTimeTellerProxy(inv));
          if (failureType.isRecoverable(injectFailureIn1stCall))
          {
             failureType.assertFailoverCounter(injectFailureIn1stCall, inv.getAsIsValue("FAILOVER_COUNTER"));
             inv = infrastructure.createDateTimeTellerInvocation(null, null);
-            log.debug(timeTellerProxy.invoke(inv));
+            log.debug(invokeTimeTellerProxy(inv));
          }
          else
          {
@@ -417,6 +417,7 @@
       }
       catch (Exception e)
       {
+         log.debug("Exception (could be expected) during failure call testing", e);
          if (failureType.isRecoverable(injectFailureIn1stCall))
          {
             fail("should have failed, failover is not allowed for " + failureType);
@@ -425,9 +426,31 @@
          {
             assertNull("transaction on the client side should be null", inv.getTransaction());
             failureType.assertFailoverCounter(injectFailureIn1stCall, inv.getAsIsValue("FAILOVER_COUNTER"));
-            failureType.assertException(e);                        
+            failureType.assertException(e.getCause());                        
          }
       }
    }
 
+   protected Object invokeTimeTellerProxy(Invocation inv) throws Exception
+   {
+      return invokeProxy(timeTellerProxy, "UnitTestPartition/DateTimeTellerMBean", inv);      
+   }
+   
+   protected Object invokeSystemTimeProxy(Invocation inv) throws Exception
+   {
+      return invokeProxy(systemTimeProxy, "UnitTestPartition/SystemTimeTellerMBean", inv);      
+   }
+   
+   protected Object invokeProxy(Invoker invoker, String proxyFamilyName, Invocation inv) throws Exception
+   {
+      try
+      {
+         return new MockTransactionStickyInterceptor(invoker, proxyFamilyName).invoke(inv);
+      }
+      catch(Throwable t)
+      {
+         throw new Exception("Throwable", t);
+      }
+            
+   }
 }

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaFailureType.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaFailureType.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaFailureType.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -53,14 +53,8 @@
             return false;
             
          case AFTER_SERVER_NOT_COMPLETED_BUT_SUCCESS_AFTER:
-            /* - if failure happens after reaching the server but didn't complete, and 
-             * it happens in the 1st transactional invocation, it's recoverable as 
-             * long as the failover call succeeds, otherwise (Nth invocation) it's 
-             * not recoverable. */
-            if (injectFailureIn1stCall)
-            {
-               return true;
-            }
+            /* it is not recoverable because UserTransaction.begin() already 
+             * reached a server.*/
             return false;
             
          case AFTER_SERVER_NOT_COMPLETED_BOTH_SERVERS:
@@ -116,7 +110,7 @@
       switch(this)
       {
          case BEFORE_SERVER:
-            TestCase.assertEquals(0, failoverCounter);
+            TestCase.assertNull(failoverCounter);
             break;
             
          case AFTER_SERVER_NOT_COMPLETED_BUT_SUCCESS_AFTER:
@@ -124,18 +118,10 @@
             break;
             
          case AFTER_SERVER_NOT_COMPLETED_BOTH_SERVERS:
-            if (injectFailureIn1stCall)
-            {
-               /* Two failovers were attempted before finally giving up */
-               TestCase.assertEquals(2, failoverCounter);
-            }
-            else
-            {
-               /* It's 1 because after several calls, the transaction has 
-                * already reached the server, so that's good enough not to 
-                * succeed */
-               TestCase.assertEquals(1, failoverCounter);
-            }
+            /* Only one attempted failover because it won't be available to 
+             * failover due to UserTransaction.begin() having already hit the 
+             * server and hence, txFailoverAuthorization maps contains that tpc. */ 
+            TestCase.assertEquals(1, failoverCounter);
             break;
             
          case AFTER_SERVER_COMPLETED:
@@ -146,23 +132,23 @@
       }
    }
    
-   public void assertException(Exception e)
+   public void assertException(Throwable t)
    {
       switch(this) 
       {
          case BEFORE_SERVER:
-            TestCase.assertTrue(e instanceof IllegalStateException);
+            TestCase.assertTrue(t instanceof IllegalStateException);
             break;
             
          case AFTER_SERVER_NOT_COMPLETED_BUT_SUCCESS_AFTER:
          case AFTER_SERVER_NOT_COMPLETED_BOTH_SERVERS:
-            TestCase.assertTrue(e instanceof ServiceUnavailableException);
-            TestCase.assertTrue(e.getCause() instanceof GenericClusteringException);
+            TestCase.assertTrue(t instanceof ServiceUnavailableException);
+            TestCase.assertTrue(t.getCause() instanceof GenericClusteringException);
             break;
             
          case AFTER_SERVER_COMPLETED:
-            TestCase.assertTrue(e instanceof ServerException);
-            TestCase.assertTrue(e.getCause() instanceof GenericClusteringException);
+            TestCase.assertTrue(t instanceof ServerException);
+            TestCase.assertTrue(t.getCause() instanceof GenericClusteringException);
             break;
       }
    }

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaInfrastructure.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaInfrastructure.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaInfrastructure.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -23,6 +23,7 @@
 
 import java.io.Serializable;
 import java.lang.management.ManagementFactory;
+import java.rmi.server.UID;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -70,10 +71,14 @@
    
    private final ObjectName systemTimeTellerON;
    
+   private final ObjectName clientUserTransactionServiceON;
+   
    private final Integer dateTimeTellerONHashCode;
    
    private final Integer systemTimeTellerONHashCode;
    
+   private final Integer clientUserTransactionServiceONHashCode;
+   
    private final int serverCount;
    
    private List<? extends InvokerHA> replicants;
@@ -96,8 +101,10 @@
          /* initialise ObjectNames and hashcodes */
          dateTimeTellerON = new ObjectName("com.acme.mbeans:type=DateTimeTeller");
          systemTimeTellerON = new ObjectName("com.acme.mbeans:type=SystemTimeTeller");
+         clientUserTransactionServiceON = new ObjectName("com.acme.mbeans:type=ClientUserTransactionService");
          dateTimeTellerONHashCode = new Integer(dateTimeTellerON.hashCode());
          systemTimeTellerONHashCode = new Integer(systemTimeTellerON.hashCode());
+         clientUserTransactionServiceONHashCode = new Integer(clientUserTransactionServiceON.hashCode());
    
          /* create a list of object names for the invoker endpoints */
          invokerONs = new ArrayList<ObjectName>(this.serverCount);
@@ -120,6 +127,7 @@
    {
       Registry.bind(dateTimeTellerONHashCode, dateTimeTellerON);
       Registry.bind(systemTimeTellerONHashCode, systemTimeTellerON);
+      Registry.bind(clientUserTransactionServiceONHashCode, clientUserTransactionServiceON);
    }
 
    /** 
@@ -169,6 +177,13 @@
       return systemTimeTellerMBean;
    }
    
+   public ClientUserTransactionService createClientUserTransactionService() throws Exception
+   {
+      ClientUserTransactionService clientUserTransactionServiceMBean = new ClientUserTransactionService();
+      mbs.registerMBean(clientUserTransactionServiceMBean, clientUserTransactionServiceON);
+      return clientUserTransactionServiceMBean;
+   }
+   
    /**
     * Deploy date time teller mbean in each server, or invoker endpoint, 
     * creating a mock HATarget with the list of replicants and associating the 
@@ -188,6 +203,11 @@
    {
       deploy(replicants, systemTimeTellerON, "SystemTimeTellerReplicant");
    }
+
+   public void deployClientUserTransactionService() throws Exception
+   {
+      deploy(replicants, clientUserTransactionServiceON, "ClientUserTransactionServiceReplicant");
+   }   
    
    /**
     * Create a proxy to date time teller bean.
@@ -217,6 +237,12 @@
       return server.createProxy(systemTimeTellerON, policyClass.newInstance(), "UnitTestPartition/SystemTimeTellerMBean");
    }
    
+   public Invoker createClientUserTransactionProxy(int serverIndex, Class<? extends LoadBalancePolicy> policyClass) throws Exception
+   {
+      InvokerHA server = replicants.get(serverIndex);
+      return server.createProxy(clientUserTransactionServiceON, policyClass.newInstance(), "UnitTestPartition/ClientUserTransactionServiceMBean");
+   }   
+   
    /**
     * Create a new invocation for date time teller mbean 
     * 
@@ -245,6 +271,11 @@
    public Invocation createSystemTimeTellerInvocation(Transaction tx, InvokerHaFailureType failureType)
    {
       return createInvocation(tx, systemTimeTellerONHashCode, failureType);
+   }
+   
+   public Invocation createClientUserTransactionInvocation(Transaction tx, InvokerHaFailureType failureType)
+   {
+      return createInvocation(tx, clientUserTransactionServiceONHashCode, failureType);
    }   
    
    /**
@@ -254,7 +285,8 @@
    {
       /* Unregister from the JMX registry */
       Registry.unbind(dateTimeTellerONHashCode);
-      Registry.unbind(systemTimeTellerONHashCode);      
+      Registry.unbind(systemTimeTellerONHashCode);
+      Registry.unbind(clientUserTransactionServiceONHashCode);
    }
    
    /**
@@ -274,6 +306,11 @@
    {
       undeploy(replicants, systemTimeTellerON);
    }
+
+   public void undeployClientUserTransactionService() throws Exception
+   {
+      undeploy(replicants, clientUserTransactionServiceON);
+   }   
    
    /**
     * Unregister invoker endpoints from mbean server.
@@ -414,6 +451,11 @@
       Object invoke(Invocation invocation) throws Exception;
    }
    
+   public interface ClientUserTransactionServiceMBean
+   {
+      Object invoke(Invocation invocation) throws Exception;      
+   }
+   
    /** Classes **/
    
    public class DateTimeTeller implements DateTimeTellerMBean
@@ -434,6 +476,15 @@
       }      
    }
    
+   public class ClientUserTransactionService implements ClientUserTransactionServiceMBean
+   {
+      public Object invoke(Invocation invocation) throws Exception
+      {
+         // Return new tpc -> only begin() calls really tested as they set the sticky target
+         return new UID();
+      }
+   }
+   
    /**
     * MockHATarget class that avoids using DistributedReplicantManager in any 
     * way. The unit test will force changes in the composition of replicants, 

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaTransactionalMockUtils.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaTransactionalMockUtils.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/InvokerHaTransactionalMockUtils.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -25,12 +25,20 @@
 
 import javax.transaction.HeuristicMixedException;
 import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
 import javax.transaction.RollbackException;
 import javax.transaction.Synchronization;
 import javax.transaction.SystemException;
 import javax.transaction.Transaction;
+import javax.transaction.UserTransaction;
 import javax.transaction.xa.XAResource;
 
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.Invoker;
+import org.jboss.invocation.InvokerInterceptor;
+import org.jboss.proxy.ClientUserTransactionStickyInterceptor;
+import org.jboss.proxy.Interceptor;
+import org.jboss.proxy.TransactionStickyInterceptor;
 import org.jboss.tm.TransactionPropagationContextFactory;
 import org.jboss.tm.TransactionPropagationContextImporter;
 import org.jboss.tm.TransactionPropagationContextUtil;
@@ -42,7 +50,7 @@
  */
 public class InvokerHaTransactionalMockUtils
 {
-   private MockTransactionPropagationContextFactory tpcf;
+   private static MockTransactionPropagationContextFactory tpcf;
    
    private MockTransactionPropagationContextImporter tpci;   
    
@@ -155,4 +163,119 @@
       }
    }
 
+   public static class MockUserTransaction implements UserTransaction
+   {
+      private Invoker invoker;
+      
+      private InvokerHaInfrastructure infrastructure; 
+      
+      public MockUserTransaction(Invoker invoker, InvokerHaInfrastructure infrastructure)
+      {
+         this.invoker = invoker;
+         this.infrastructure = infrastructure;
+      }
+
+      public void begin() throws NotSupportedException, SystemException
+      {
+         try
+         {
+            Invocation inv = infrastructure.createClientUserTransactionInvocation(null, null);
+            UID uid = (UID) new MockClientUserTransactionStickyInterceptor(invoker).invoke(inv);
+            tpcf.setUid(uid);
+         }
+         catch (Throwable e)
+         {
+            throw new RuntimeException("Exception during mock UT.begin", e);
+         }
+      }
+
+      public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+            SecurityException, IllegalStateException, SystemException
+      {
+         tpcf.setUid(null);
+      }
+
+      public int getStatus() throws SystemException
+      {
+         return 0;
+      }
+
+      public void rollback() throws IllegalStateException, SecurityException, SystemException
+      {
+      }
+
+      public void setRollbackOnly() throws IllegalStateException, SystemException
+      {
+      }
+
+      public void setTransactionTimeout(int seconds) throws SystemException
+      {
+      }
+   }
+   
+   public static class MockClientUserTransactionStickyInterceptor extends ClientUserTransactionStickyInterceptor
+   {
+      private Invoker invoker;
+      
+      public MockClientUserTransactionStickyInterceptor(Invoker invoker)
+      {
+         this.invoker = invoker;
+      }
+
+      @Override
+      public Interceptor getNext()
+      {
+         InvokerInterceptor.setLocal(invoker);
+         
+         return new InvokerInterceptor()
+         {
+            @Override
+            public boolean isLocal(Invocation invocation)
+            {
+               return true;
+            }
+         };
+      }
+
+      @Override
+      protected String getProxyFamilyName(Invocation invocation) throws Exception
+      {
+         return "UnitTestPartition/ClientUserTransactionServiceMBean";
+      }
+   }
+   
+   public static class MockTransactionStickyInterceptor extends TransactionStickyInterceptor
+   {
+      private Invoker invoker;
+      
+      private String proxyFamilyName;
+      
+      public MockTransactionStickyInterceptor(Invoker invoker, String proxyFamilyName)
+      {
+         this.invoker = invoker;
+         this.proxyFamilyName = proxyFamilyName;
+      }
+
+      @Override
+      public Interceptor getNext()
+      {
+         InvokerInterceptor.setLocal(invoker);
+         
+         return new InvokerInterceptor()
+         {
+            @Override
+            public boolean isLocal(Invocation invocation)
+            {
+               return true;
+            }
+         };
+      }
+
+      @Override
+      protected String getProxyFamilyName(Invocation invocation) throws Exception
+      {
+         return proxyFamilyName;
+      }
+   }
+   
 }

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaMockUtils.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaMockUtils.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaMockUtils.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -121,18 +121,6 @@
       public Object invoke(Invocation invocation) throws Exception
       {
          return super.invoke(invocation);
-      }
-      
-      @Override
-      protected void putIfExistsTransactionTarget(Invocation invocation, Object tpc) throws Exception
-      {
-         InvokerHaFailureType failureType = (InvokerHaFailureType)invocation.getValue("FAILURE_TYPE");
-         if (failureType != null)
-         {
-            failureType.injectFailureIfExistsBeforeServer();
-         }
-         
-         super.putIfExistsTransactionTarget(invocation, tpc);
       }      
    }
 

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaTransactionStickyUnitTestCase.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaTransactionStickyUnitTestCase.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/JRMPInvokerHaTransactionStickyUnitTestCase.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -23,6 +23,9 @@
 
 import java.util.List;
 
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 import org.jboss.invocation.InvokerHA;
 import org.jboss.test.cluster.invokerha.JRMPInvokerHaUnitTestCase.JRMPInvokerHaFactory;
 import org.jboss.test.cluster.invokerha.AbstractInvokerHaTransactionSticky;
@@ -62,4 +65,12 @@
          return "TX_STICKY_TARGET";
       }
    }
+   
+   public static Test suite() 
+   {
+      /* No transactions to be run for JRMP invoker version of transaction 
+       * sticky functionality because this old legacy invoker is no longer 
+       * supported for transaction sticky functionality. */
+      return new TestSuite();
+   }
 }

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/UnifiedInvokerHaMockUtils.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -142,9 +142,9 @@
       {
          return new MockClient(locator);
       }
-
+      
       @Override
-      protected void putIfExistsTransactionTarget(Invocation invocation, Object tpc) throws Exception
+      public Object invoke(Invocation invocation) throws Exception
       {
          InvokerHaFailureType failureType = (InvokerHaFailureType)invocation.getValue("FAILURE_TYPE");
          if (failureType != null)
@@ -152,9 +152,9 @@
             failureType.injectFailureIfExistsBeforeServer();
          }
          
-         super.putIfExistsTransactionTarget(invocation, tpc);
+         return super.invoke(invocation);
       }
-      
+
       public InvokerLocator getLocator()
       {
          return super.getLocator();

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/ejb/test/UserTransactionStickyUnitTestCase.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/ejb/test/UserTransactionStickyUnitTestCase.java	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/main/org/jboss/test/cluster/invokerha/ejb/test/UserTransactionStickyUnitTestCase.java	2008-11-20 14:49:58 UTC (rev 81364)
@@ -34,7 +34,6 @@
 import org.jboss.test.JBossClusteredTestCase;
 import org.jboss.test.cluster.invokerha.ejb.UserTransactionStickyHome;
 import org.jboss.test.cluster.invokerha.ejb.UserTransactionStickyRemote;
-import org.jnp.interfaces.NamingContext;
 
 /**
  * UserTransactionStickyTestCase.
@@ -68,8 +67,15 @@
    {
       UserTransaction tx;
 
-      ctx = createDefaultPartitionContext();
+      // Connect to the server0 JNDI
+      String[] urls = getNamingURLs();
+      Properties env1 = new Properties();
+      env1.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.NamingContextFactory");
+      env1.setProperty(Context.PROVIDER_URL, urls[0]);
+      ctx = new InitialContext(env1);      
       
+      // ctx = createDefaultPartitionContext();
+      
       for (int i = 1; i <= numTxs; i++)
       {         
          tx = (UserTransaction)ctx.lookup("UserTransaction");
@@ -100,21 +106,21 @@
       }      
    }
 
-   private Properties getDefaultProperties()
-   {
-      Properties p = new Properties();
-      p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
-      p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
-      return p;
-   }   
+//   private Properties getDefaultProperties()
+//   {
+//      Properties p = new Properties();
+//      p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
+//      p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
+//      return p;
+//   }   
+//   
+//   private Context createDefaultPartitionContext() throws Exception
+//   {
+//      Properties p = getDefaultProperties();
+//      p.put(NamingContext.JNP_PARTITION_NAME, "DefaultPartition"); // partition name.
+//      return new InitialContext(p);
+//   }
    
-   private Context createDefaultPartitionContext() throws Exception
-   {
-      Properties p = getDefaultProperties();
-      p.put(NamingContext.JNP_PARTITION_NAME, "DefaultPartition"); // partition name.
-      return new InitialContext(p);
-   }
-   
    private static void log(Object message)
    {
       log.info(message);

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/cluster/invokerha/ejb/META-INF/jboss.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/cluster/invokerha/ejb/META-INF/jboss.xml	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/cluster/invokerha/ejb/META-INF/jboss.xml	2008-11-20 14:49:58 UTC (rev 81364)
@@ -18,10 +18,10 @@
        
     </enterprise-beans>
     
-    <!-- invoker-proxy-bindings>
+    <invoker-proxy-bindings>
        <invoker-proxy-binding>
          <name>ustxsticky-clustered-stateless-unified-invoker</name>
-         <invoker-mbean>jboss:service=invoker,type=unifiedha,ext=ustxsticky</invoker-mbean>
+         <invoker-mbean>jboss:service=invoker,type=unifiedha</invoker-mbean>
          <proxy-factory>org.jboss.proxy.ejb.ProxyFactoryHA</proxy-factory>
          <proxy-factory-config>
            <client-interceptors>
@@ -30,6 +30,7 @@
                <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
                <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
                <interceptor>org.jboss.proxy.ejb.SingleRetryInterceptor</interceptor>
+               <interceptor>org.jboss.proxy.TransactionStickyInterceptor</interceptor>
                <interceptor call-by-value="false">org.jboss.invocation.InvokerInterceptor</interceptor>
                <interceptor call-by-value="true">org.jboss.invocation.MarshallingInvokerInterceptor</interceptor>
              </home>
@@ -38,17 +39,19 @@
                <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
                <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
                <interceptor>org.jboss.proxy.ejb.SingleRetryInterceptor</interceptor>
+               <interceptor>org.jboss.proxy.TransactionStickyInterceptor</interceptor>               
                <interceptor call-by-value="false">org.jboss.invocation.InvokerInterceptor</interceptor>
                <interceptor call-by-value="true">org.jboss.invocation.MarshallingInvokerInterceptor</interceptor>
              </bean>
            </client-interceptors>
          </proxy-factory-config>
        </invoker-proxy-binding>    
-    </invoker-proxy-bindings -->
+    </invoker-proxy-bindings>
     
     <container-configurations>
       <container-configuration extends="Clustered Stateless SessionBean">
          <container-name>User Transaction Stickiness Verifier Clustered Stateless SessionBean</container-name>
+         <invoker-proxy-binding-name>ustxsticky-clustered-stateless-unified-invoker</invoker-proxy-binding-name>         
          <container-interceptors>
            <interceptor>org.jboss.test.cluster.invokerha.ejb.UserTransactionStickinessVerifierInterceptor</interceptor>
            <interceptor>org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor</interceptor>

Modified: branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/test-configs/ustxsticky/conf/jboss-service.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/test-configs/ustxsticky/conf/jboss-service.xml	2008-11-20 14:31:17 UTC (rev 81363)
+++ branches/JBPAPP_4_2_0_GA_CP04_JBPAPP-1180_JBPAPP-1268_JBPAPP-1428/testsuite/src/resources/test-configs/ustxsticky/conf/jboss-service.xml	2008-11-20 14:49:58 UTC (rev 81364)
@@ -395,6 +395,7 @@
             <attribute name="ClientInterceptors">
                <interceptors>
                   <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
+                  <interceptor>org.jboss.proxy.ClientUserTransactionStickyInterceptor</interceptor>
                   <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
                </interceptors>
             </attribute>




More information about the jboss-cvs-commits mailing list