cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From egl...@apache.org
Subject svn commit: r534016 - in /incubator/cxf/trunk: api/src/main/java/org/apache/cxf/endpoint/ api/src/main/java/org/apache/cxf/message/ rt/core/src/main/java/org/apache/cxf/clustering/ rt/core/src/main/java/org/apache/cxf/endpoint/ rt/core/src/main/java/or...
Date Tue, 01 May 2007 11:43:12 GMT
Author: eglynn
Date: Tue May  1 04:43:11 2007
New Revision: 534016

URL: http://svn.apache.org/viewvc?view=rev&rev=534016
Log:
Added a ConduitSelector implementing failover within a static cluster (i.e. a cluster defined by multiple endpoints within a service).

Added:
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/Retryable.java   (with props)
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java   (with props)
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/Messages.properties   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/ControlImpl.java   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/FailoverTest.java   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/GreeterImpl.java   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/Server.java   (with props)
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/failover.xml   (with props)
Modified:
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/AbstractConduitSelector.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/ConduitSelector.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/DeferredConduitSelector.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/NullConduitSelector.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/PreexistingConduitSelector.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Exchange.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/ExchangeImpl.java
    incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java
    incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/ServiceImplTest.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/soapServiceConfig.xml
    incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/ClientFactoryBean.java
    incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
    incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java
    incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/Proxy.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/interceptor/InterceptorFaultTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/addressing/wsa_interceptors.xml
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/ControlImpl.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/SequenceTest.java
    incubator/cxf/trunk/testutils/src/main/java/org/apache/cxf/greeter_control/ControlImpl.java
    incubator/cxf/trunk/testutils/src/main/resources/wsdl/greeter_control.wsdl
    incubator/cxf/trunk/testutils/src/main/resources/wsdl/hello_world.wsdl

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/AbstractConduitSelector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/AbstractConduitSelector.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/AbstractConduitSelector.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/AbstractConduitSelector.java Tue May  1 04:43:11 2007
@@ -40,7 +40,8 @@
  */
 public abstract class AbstractConduitSelector implements ConduitSelector {
 
-    private Conduit selectedConduit;
+    protected Conduit selectedConduit;
+    protected Endpoint endpoint;
 
     /**
      * Constructor, allowing a specific conduit to override normal selection.
@@ -50,7 +51,7 @@
     public AbstractConduitSelector(Conduit c) {
         selectedConduit = c;
     }
-    
+        
     /**
      * Mechanics to actually get the Conduit from the ConduitInitiator
      * if necessary.
@@ -60,7 +61,6 @@
     protected Conduit getSelectedConduit(Message message) {
         if (selectedConduit == null) {
             Exchange exchange = message.getExchange();
-            Endpoint endpoint = exchange.get(Endpoint.class);
             EndpointInfo ei = endpoint.getEndpointInfo();
             String transportID = ei.getTransportId();
             try {
@@ -92,6 +92,20 @@
             }
         }
         return selectedConduit;
+    }
+
+    /**
+     * @return the encapsulated Endpoint
+     */
+    public Endpoint getEndpoint() {
+        return endpoint;
+    }
+
+    /**
+     * @param endpoint the endpoint to encapsulate
+     */
+    public void setEndpoint(Endpoint ep) {
+        endpoint = ep;
     }
     
     /**

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/ConduitSelector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/ConduitSelector.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/ConduitSelector.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/ConduitSelector.java Tue May  1 04:43:11 2007
@@ -30,7 +30,7 @@
  * into the Client via config.
  */
 public interface ConduitSelector {
-    
+        
     /**
      * Called prior to the interceptor chain being traversed.
      * This is the point at which an eager strategy would retrieve
@@ -58,4 +58,14 @@
      * @param exchange represents the completed MEP
      */
     void complete(Exchange exchange);
+
+    /**
+     * @return the encapsulated Endpoint
+     */
+    Endpoint getEndpoint();
+
+    /**
+     * @param endpoint the endpoint to encapsulate
+     */
+    void setEndpoint(Endpoint endpoint);
 }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/DeferredConduitSelector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/DeferredConduitSelector.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/DeferredConduitSelector.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/DeferredConduitSelector.java Tue May  1 04:43:11 2007
@@ -51,14 +51,30 @@
         super(c);
     }
 
+    /**
+     * Called prior to the interceptor chain being traversed.
+     * 
+     * @param message the current Message
+     */
     public void prepare(Message message) {
         // nothing to do
     }
 
+    /**
+     * Called when a Conduit is actually required.
+     * 
+     * @param message
+     * @return the Conduit to use for mediation of the message
+     */
     public Conduit selectConduit(Message message) {
         return getSelectedConduit(message);
     }
 
+    /**
+     * Called on completion of the MEP for which the Conduit was required.
+     * 
+     * @param exchange represents the completed MEP
+     */    
     public void complete(Exchange exchange) {
         // nothing to do
     }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/NullConduitSelector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/NullConduitSelector.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/NullConduitSelector.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/NullConduitSelector.java Tue May  1 04:43:11 2007
@@ -31,15 +31,47 @@
  */
 public class NullConduitSelector implements ConduitSelector {
 
+    private Endpoint endpoint;
+    
+    /**
+     * Called prior to the interceptor chain being traversed.
+     * 
+     * @param message the current Message
+     */
     public void prepare(Message message) {
         // nothing to do
     }
 
+    /**
+     * Called when a Conduit is actually required.
+     * 
+     * @param message
+     * @return the Conduit to use for mediation of the message
+     */
     public Conduit selectConduit(Message message) {
         return null;
     }
 
+    /**
+     * Called on completion of the MEP for which the Conduit was required.
+     * 
+     * @param exchange represents the completed MEP
+     */
     public void complete(Exchange exchange) {
         // nothing to do
+    }
+    
+    /**
+     * @return the encapsulated Endpoint
+     */
+    public Endpoint getEndpoint() {
+        return endpoint;
+    }
+
+    /**
+     * @param endpoint the endpoint to encapsulate
+     */
+    public void setEndpoint(Endpoint ep) {
+        endpoint = ep;
     }
 }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/PreexistingConduitSelector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/PreexistingConduitSelector.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/PreexistingConduitSelector.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/PreexistingConduitSelector.java Tue May  1 04:43:11 2007
@@ -33,6 +33,7 @@
     ConduitSelector {
 
     private Conduit selectedConduit;
+    private Endpoint endpoint;
 
     /**
      * Constructor.
@@ -40,7 +41,18 @@
      * @param c the pre-existing Conduit.
      */
     public PreexistingConduitSelector(Conduit c) {
+        this(c, null);
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param c the pre-existing Conduit.
+     * @param e the target Endpoint
+     */
+    public PreexistingConduitSelector(Conduit c, Endpoint e) {
         selectedConduit = c;
+        endpoint = e;
     }
 
     /**
@@ -73,5 +85,19 @@
      */
     public void complete(Exchange exchange) {
         // nothing to do
+    }
+    
+    /**
+     * @return the encapsulated Endpoint
+     */
+    public Endpoint getEndpoint() {
+        return endpoint;
+    }
+
+    /**
+     * @param endpoint the endpoint to encapsulate
+     */
+    public void setEndpoint(Endpoint ep) {
+        endpoint = ep;
     }
 }

Added: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/Retryable.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/Retryable.java?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/Retryable.java (added)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/Retryable.java Tue May  1 04:43:11 2007
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.endpoint;
+
+import java.util.Map;
+
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.service.model.BindingOperationInfo;
+
+/**
+ * Implemented by Clients that are willing to accept retried invocations.
+ */
+public interface Retryable {
+    Object[] invoke(BindingOperationInfo oi,
+                    Object[] params, 
+                    Map<String, Object> context,
+                    Exchange exchange) throws Exception;
+}

Propchange: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/endpoint/Retryable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Exchange.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Exchange.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Exchange.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Exchange.java Tue May  1 04:43:11 2007
@@ -69,4 +69,6 @@
      * @param b true if the exchange is known to be a one-way exchange
      */
     void setOneWay(boolean b);
+    
+    void clear();
 }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/ExchangeImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/ExchangeImpl.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/ExchangeImpl.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/ExchangeImpl.java Tue May  1 04:43:11 2007
@@ -20,6 +20,7 @@
 package org.apache.cxf.message;
 
 import org.apache.cxf.endpoint.ConduitSelector;
+import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.endpoint.PreexistingConduitSelector;
 import org.apache.cxf.transport.Conduit;
 import org.apache.cxf.transport.Destination;
@@ -85,7 +86,8 @@
     }
 
     public void setConduit(Conduit c) {
-        put(ConduitSelector.class, new PreexistingConduitSelector(c));
+        put(ConduitSelector.class,
+            new PreexistingConduitSelector(c, get(Endpoint.class)));
     }
 
     public void setOutMessage(Message m) {
@@ -109,5 +111,16 @@
 
     public void setSession(Session session) {
         this.session = session;
+    }
+    
+    public void clear() {
+        super.clear();
+        destination = null;
+        oneWay = false;
+        inMessage = null;
+        outMessage = null;
+        inFaultMessage = null;
+        outFaultMessage = null;
+        session = null;
     }
 }

Modified: incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java (original)
+++ incubator/cxf/trunk/api/src/main/java/org/apache/cxf/message/Message.java Tue May  1 04:43:11 2007
@@ -31,7 +31,7 @@
     String REQUESTOR_ROLE = "org.apache.cxf.client";
 
     String INBOUND_MESSAGE = "org.apache.cxf.message.inbound";
-    String INVOCATION_OBJECTS = "org.apache.cxf.invocation.objects";
+    String INVOCATION_CONTEXT = "org.apache.cxf.invocation.context";
     
     String MIME_HEADERS = "org.apache.cxf.mime.headers";
     

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java Tue May  1 04:43:11 2007
@@ -0,0 +1,343 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.clustering;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.endpoint.AbstractConduitSelector;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.endpoint.Retryable;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.service.model.BindingOperationInfo;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.service.model.ServiceInfo;
+import org.apache.cxf.transport.Conduit;
+
+
+/**
+ * Implements a target selection strategy based on failover to an 
+ * alternate target endpoint when a transport level failure is 
+ * encountered.
+ */
+public class FailoverTargetSelector extends AbstractConduitSelector {
+
+    private static final Logger LOG =
+        LogUtils.getL7dLogger(FailoverTargetSelector.class);
+    private Map<InvocationKey, InvocationContext> inProgress;
+    
+    /**
+     * Normal constructor.
+     */
+    public FailoverTargetSelector() {
+        this(null);
+    }
+    
+    /**
+     * Constructor, allowing a specific conduit to override normal selection.
+     * 
+     * @param c specific conduit
+     */
+    public FailoverTargetSelector(Conduit c) {
+        super(c);
+        inProgress = new HashMap<InvocationKey, InvocationContext>();
+    }
+    
+    /**
+     * Called prior to the interceptor chain being traversed.
+     * 
+     * @param message the current Message
+     */
+    public synchronized void prepare(Message message) {
+        Exchange exchange = message.getExchange();
+        InvocationKey key = new InvocationKey(exchange);
+        if (!inProgress.containsKey(key)) {
+            Endpoint endpoint = exchange.get(Endpoint.class);
+            BindingOperationInfo bindingOperationInfo =
+                exchange.get(BindingOperationInfo.class);
+            Object[] params = message.getContent(List.class).toArray();
+            Map<String, Object> context =
+                CastUtils.cast((Map)message.get(Message.INVOCATION_CONTEXT));
+            InvocationContext invocation = 
+                new InvocationContext(endpoint, 
+                                      bindingOperationInfo,
+                                      params,
+                                      context);
+            inProgress.put(key, invocation);
+        }
+    }
+
+    /**
+     * Called when a Conduit is actually required.
+     * 
+     * @param message
+     * @return the Conduit to use for mediation of the message
+     */
+    public Conduit selectConduit(Message message) {
+        return getSelectedConduit(message);
+    }
+
+    /**
+     * Called on completion of the MEP for which the Conduit was required.
+     * 
+     * @param exchange represents the completed MEP
+     */
+    public void complete(Exchange exchange) {
+        InvocationKey key = new InvocationKey(exchange);
+        InvocationContext invocation = null;
+        synchronized (this) {
+            invocation = inProgress.get(key);
+        }
+        boolean failover = false;
+        if (requiresFailover(exchange)) {
+            Endpoint failoverTarget = getFailoverTarget(exchange, invocation);
+            if (failoverTarget != null) {
+                endpoint = failoverTarget;
+                selectedConduit.close();
+                selectedConduit = null;
+                Exception prevExchangeFault =
+                    (Exception)exchange.remove(Exception.class.getName());
+                Message outMessage = exchange.getOutMessage();
+                Exception prevMessageFault =
+                    outMessage.getContent(Exception.class);
+                outMessage.setContent(Exception.class, null);
+                overrideAddressProperty(invocation.getContext());
+                Retryable retry = exchange.get(Retryable.class);
+                exchange.clear();
+                if (retry != null) {
+                    try {
+                        failover = true;
+                        retry.invoke(invocation.getBindingOperationInfo(),
+                                     invocation.getParams(),
+                                     invocation.getContext(),
+                                      exchange);
+                    } catch (Exception e) {
+                        if (exchange.get(Exception.class) != null) {
+                            exchange.put(Exception.class, prevExchangeFault);
+                        }
+                        if (outMessage.getContent(Exception.class) != null) {
+                            outMessage.setContent(Exception.class,
+                                                  prevMessageFault);
+                        }
+                    }
+                }
+            } else {
+                if (endpoint != invocation.getOriginalEndpoint()) {
+                    endpoint = invocation.getOriginalEndpoint();
+                    getLogger().log(Level.INFO,
+                                    "REVERT_TO_ORIGINAL_TARGET",
+                                    endpoint.getEndpointInfo().getName());
+                }
+            }
+        }
+        if (!failover) {
+            getLogger().info("FAILOVER_NOT_REQUIRED");
+            synchronized (this) {
+                inProgress.remove(key);
+            }
+        }
+    }
+
+    /**
+     * @return the logger to use
+     */
+    protected Logger getLogger() {
+        return LOG;
+    }
+
+    /**
+     * Check if the exchange is suitable for a failover.
+     * 
+     * @param exchange the current Exchange
+     * @return boolean true iff a failover should be attempted
+     */
+    private boolean requiresFailover(Exchange exchange) {
+        Message outMessage = exchange.getOutMessage();
+        Exception ex = outMessage.get(Exception.class) != null
+                       ? outMessage.get(Exception.class)
+                       : exchange.get(Exception.class);
+        getLogger().log(Level.INFO,
+                        "CHECK_LAST_INVOKE_FAILED",
+                        new Object[] {ex != null});
+        Throwable curr = ex;
+        boolean failover = false;
+        while (curr != null) {
+            getLogger().log(Level.WARNING,
+                            "CHECK_FAILURE_IN_TRANSPORT",
+                            new Object[] {ex, curr instanceof IOException});
+            failover = curr instanceof java.io.IOException;
+            curr = curr.getCause();
+        }
+        return failover;
+    }
+    
+    /**
+     * Get the failover target endpoint, if a suitable one is available.
+     * 
+     * @param exchange the current Exchange
+     * @param invocation the current InvocationContext
+     * @return a failover endpoint if one is available
+     */
+    private Endpoint getFailoverTarget(Exchange exchange,
+                                       InvocationContext invocation) {        
+        if (invocation.getAlternateTargets() == null) {
+            // no previous failover attempt on this invocation
+            //
+            Endpoint endpoint = exchange.get(Endpoint.class);
+            Collection<ServiceInfo> services = endpoint.getService().getServiceInfos();
+            QName currentBinding = endpoint.getBinding().getBindingInfo().getName();
+            invocation.setAlternateTargets(new ArrayList<Endpoint>());
+            for (ServiceInfo service : services) {
+                Collection<EndpointInfo> candidates = service.getEndpoints();
+                for (EndpointInfo candidate : candidates) {
+                    QName candidateBinding = candidate.getBinding().getName();
+                    if (candidateBinding.equals(currentBinding)) {
+                        if (!candidate.getAddress().equals(
+                                 endpoint.getEndpointInfo().getAddress())) {
+                            Endpoint alternate =
+                                endpoint.getService().getEndpoints().get(candidate.getName());
+                            if (alternate != null) {
+                                getLogger().log(Level.INFO,
+                                                "FAILOVER_CANDIDATE_ACCEPTED",
+                                                candidate.getName());
+                                invocation.getAlternateTargets().add(alternate);
+                            }
+                        }
+                    } else {
+                        getLogger().log(Level.INFO,
+                                        "FAILOVER_CANDIDATE_REJECTED",
+                                        new Object[] {candidate.getName(), candidateBinding});
+                    }
+                }
+            }
+        } 
+
+        Endpoint failoverTarget = null;
+        if (invocation.getAlternateTargets().size() > 0) {
+            // REVISIT: configurable sequential or randomized
+            failoverTarget = invocation.getAlternateTargets().remove(0);
+            getLogger().log(Level.WARNING,
+                            "FAILING_OVER_TO",
+                            new Object[] {failoverTarget.getEndpointInfo().getName()});
+        } else {
+            getLogger().warning("NO_ALTERNATE_TARGETS_REMAIN");
+        }
+        return failoverTarget;
+    }
+    
+    /**
+     * Override the ENDPOINT_ADDRESS property in the request context
+     * 
+     * @param context the request context
+     */
+    private void overrideAddressProperty(Map<String, Object> context) {
+        Map<String, Object> requestContext =
+            CastUtils.cast((Map)context.get(Client.REQUEST_CONTEXT));
+        if (requestContext != null) {
+            requestContext.put(Message.ENDPOINT_ADDRESS,
+                               getEndpoint().getEndpointInfo().getAddress());
+            requestContext.put("javax.xml.ws.service.endpoint.address",
+                               getEndpoint().getEndpointInfo().getAddress());            
+        }
+    }
+            
+    /**
+     * Used to wrap an Exchange for usage as a Map key. The raw Exchange
+     * is not a suitable key type, as the hashCode is computed from its
+     * current contents, which may obvioulsy change over the lifetime of
+     * an invocation.
+     */
+    private static class InvocationKey {
+        private Exchange exchange;
+        
+        InvocationKey(Exchange ex) {
+            exchange = ex;     
+        }
+        
+        @Override
+        public int hashCode() {
+            return System.identityHashCode(exchange);
+        }
+        
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof InvocationKey
+                   && exchange == ((InvocationKey)o).exchange;
+        }
+    }
+
+
+    /**
+     * Records the context of an invocation.
+     */
+    private static class InvocationContext {
+        private Endpoint originalEndpoint;
+        private BindingOperationInfo bindingOperationInfo;
+        private Object[] params; 
+        private Map<String, Object> context;
+        private List<Endpoint> alternateTargets;
+        
+        InvocationContext(Endpoint endpoint,
+                          BindingOperationInfo boi,
+                          Object[] prms, 
+                          Map<String, Object> ctx) {
+            originalEndpoint = endpoint;
+            bindingOperationInfo = boi;
+            params = prms;
+            context = ctx;
+        }
+
+        Endpoint getOriginalEndpoint() {
+            return originalEndpoint;
+        }
+        
+        BindingOperationInfo getBindingOperationInfo() {
+            return bindingOperationInfo;
+        }
+        
+        Object[] getParams() {
+            return params;
+        }
+        
+        Map<String, Object> getContext() {
+            return context;
+        }
+        
+        List<Endpoint> getAlternateTargets() {
+            return alternateTargets;
+        }
+
+        void setAlternateTargets(List<Endpoint> alternates) {
+            alternateTargets = alternates;
+        }
+    }    
+}

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/Messages.properties
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/Messages.properties?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/Messages.properties (added)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/Messages.properties Tue May  1 04:43:11 2007
@@ -0,0 +1,28 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one
+#    or more contributor license agreements. See the NOTICE file
+#    distributed with this work for additional information
+#    regarding copyright ownership. The ASF licenses this file
+#    to you under the Apache License, Version 2.0 (the
+#    "License"); you may not use this file except in compliance
+#    with the License. You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing,
+#    software distributed under the License is distributed on an
+#    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#    KIND, either express or implied. See the License for the
+#    specific language governing permissions and limitations
+#    under the License.
+#
+#
+REVERT_TO_ORIGINAL_TARGET = reverted to original endpoint {0}
+FAILOVER_NOT_REQUIRED = failover not required
+NO_ALTERNATE_TARGETS_REMAIN = no alternate targets remain => giving up on failover
+CHECK_LAST_INVOKE_FAILED = last invocation raised fault?: {0}
+CHECK_FAILURE_IN_TRANSPORT = failure {0} caused at transport level?: {1}
+FAILOVER_CANDIDATE_ACCEPTED = failover candidate {0} accepted
+FAILOVER_CANDIDATE_REJECTED = failover candidate {0} rejected on binding mismatch
+FAILING_OVER_TO = failing over to alternate target {0}
\ No newline at end of file

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/Messages.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/clustering/Messages.properties
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/endpoint/ClientImpl.java Tue May  1 04:43:11 2007
@@ -60,28 +60,31 @@
 import org.apache.cxf.transport.MessageObserver;
 import org.apache.cxf.wsdl11.WSDLServiceFactory;
 
-public class ClientImpl extends AbstractBasicInterceptorProvider implements Client, MessageObserver {
+public class ClientImpl
+    extends AbstractBasicInterceptorProvider
+    implements Client, Retryable, MessageObserver {
+    
     public static final String FINISHED = "exchange.finished";
     
     private static final Logger LOG = LogUtils.getL7dLogger(ClientImpl.class);
     
     protected Bus bus;
-    protected Endpoint endpoint;
     protected ConduitSelector conduitSelector;
     protected ClientOutFaultObserver outFaultObserver; 
     protected int synchronousTimeout = 10000; // default 10 second timeout
 
     public ClientImpl(Bus b, Endpoint e) {
-        this(b, e, null);
+        this(b, e, (ConduitSelector)null);
     }
 
     public ClientImpl(Bus b, Endpoint e, Conduit c) {
+       this(b, e, new PreexistingConduitSelector(c));
+    }
+    
+    public ClientImpl(Bus b, Endpoint e, ConduitSelector sc) {
         bus = b;
-        endpoint = e;
         outFaultObserver = new ClientOutFaultObserver(bus);
-        if (null != c) {
-            conduitSelector = new PreexistingConduitSelector(c);
-        }
+        getConduitSelector(sc).setEndpoint(e);
     }
 
     public ClientImpl(URL wsdlUrl) {
@@ -91,7 +94,7 @@
     public ClientImpl(URL wsdlUrl, QName port) {
         this(BusFactory.getDefaultBus(), wsdlUrl, null, port);
     }
-    
+
     public ClientImpl(Bus bus, URL wsdlUrl, QName service, QName port) {
         this.bus = bus;
         
@@ -102,7 +105,7 @@
         EndpointInfo epfo = findEndpoint(svc, port);
 
         try {
-            endpoint = new EndpointImpl(bus, svc, epfo);
+            getConduitSelector().setEndpoint(new EndpointImpl(bus, svc, epfo));
         } catch (EndpointException epex) {
             throw new IllegalStateException("Unable to create endpoint: " + epex.getMessage(), epex);
         }
@@ -146,7 +149,7 @@
     }
 
     public Endpoint getEndpoint() {
-        return this.endpoint;
+        return getConduitSelector().getEndpoint();
     }
 
     public Object[] invoke(BindingOperationInfo oi, Object... params) throws Exception {
@@ -160,7 +163,7 @@
     }
     
     public Object[] invoke(QName operationName, Object... params) throws Exception {
-        BindingOperationInfo op = endpoint.getEndpointInfo().getBinding().getOperation(operationName);
+        BindingOperationInfo op = getEndpoint().getEndpointInfo().getBinding().getOperation(operationName);
         if (op == null) {
             throw new UncheckedException(
                 new org.apache.cxf.common.i18n.Message("NO_OPERATION", LOG, operationName));
@@ -175,6 +178,18 @@
 
     public Object[] invoke(BindingOperationInfo oi, Object[] params, 
                            Map<String, Object> context) throws Exception {
+        return invoke(oi, params, context, null);
+    }        
+    
+    public Object[] invoke(BindingOperationInfo oi,
+                           Object[] params, 
+                           Map<String, Object> context,
+                           Exchange exchange) throws Exception {
+        if (exchange == null) {
+            exchange = new ExchangeImpl();
+        }
+        Endpoint endpoint = getEndpoint();
+
         Map<String, Object> requestContext = null;
         Map<String, Object> responseContext = null;
         if (LOG.isLoggable(Level.FINE)) {
@@ -184,11 +199,11 @@
         if (null != context) {
             requestContext = CastUtils.cast((Map)context.get(REQUEST_CONTEXT));
             responseContext = CastUtils.cast((Map)context.get(RESPONSE_CONTEXT));
+            message.put(Message.INVOCATION_CONTEXT, context);
         }    
         //setup the message context
         setContext(requestContext, message);
         setParameters(params, message);
-        Exchange exchange = new ExchangeImpl();
 
         if (null != requestContext) {
             exchange.putAll(requestContext);
@@ -198,16 +213,16 @@
         exchange.setOutMessage(message);
         
         setOutMessageProperties(message, oi);
-        setExchangeProperties(exchange, oi);
+        setExchangeProperties(exchange, endpoint, oi);
         
         // setup chain
 
-        PhaseInterceptorChain chain = setupInterceptorChain();
+        PhaseInterceptorChain chain = setupInterceptorChain(endpoint);
         message.setInterceptorChain(chain);
         
         modifyChain(chain, requestContext);
         chain.setFaultObserver(outFaultObserver);
-                
+        
         // setup conduit selector
         prepareConduitSelector(message);
         
@@ -307,13 +322,22 @@
     }
     
     public void onMessage(Message message) {
+        Endpoint endpoint = message.getExchange().get(Endpoint.class);
+        if (endpoint == null) {
+            // in this case correlation will occur outside the transport,
+            // however there's a possibility that the endpoint may have been 
+            // rebased in the meantime, so that the response will be mediated
+            // via a set of in interceptors provided by a *different* endpoint
+            //
+            endpoint = getConduitSelector().getEndpoint();
+            message.getExchange().put(Endpoint.class, endpoint);            
+        }
         message = endpoint.getBinding().createMessage(message);
         message.put(Message.REQUESTOR_ROLE, Boolean.TRUE);
         message.put(Message.INBOUND_MESSAGE, Boolean.TRUE);
         PhaseManager pm = bus.getExtension(PhaseManager.class);
         PhaseInterceptorChain chain = new PhaseInterceptorChain(pm.getInPhases());
         message.setInterceptorChain(chain);
-        message.getExchange().put(Endpoint.class, endpoint);
         
         List<Interceptor> il = bus.getInInterceptors();
         if (LOG.isLoggable(Level.FINE)) {
@@ -361,7 +385,7 @@
         Message message = new MessageImpl();
         Exchange exchange = new ExchangeImpl();
         message.setExchange(exchange);
-        setExchangeProperties(exchange, null);
+        setExchangeProperties(exchange, null, null);
         return getConduitSelector().selectConduit(message);
     }
 
@@ -378,26 +402,29 @@
     }
     
     protected void setExchangeProperties(Exchange exchange,
+                                         Endpoint endpoint,
                                          BindingOperationInfo boi) {
-       
-        exchange.put(Service.class, endpoint.getService());
-        exchange.put(Endpoint.class, endpoint);
-        if (endpoint.getEndpointInfo().getService() != null) {
-            exchange.put(ServiceInfo.class, endpoint.getEndpointInfo().getService());
-            exchange.put(InterfaceInfo.class, endpoint.getEndpointInfo().getService().getInterface());
+        if (endpoint != null) {
+            exchange.put(Endpoint.class, endpoint);
+            exchange.put(Service.class, endpoint.getService());
+            if (endpoint.getEndpointInfo().getService() != null) {
+                exchange.put(ServiceInfo.class, endpoint.getEndpointInfo().getService());
+                exchange.put(InterfaceInfo.class, endpoint.getEndpointInfo().getService().getInterface());
+            }
+            exchange.put(Binding.class, endpoint.getBinding());
+            exchange.put(BindingInfo.class, endpoint.getEndpointInfo().getBinding());
         }
-        exchange.put(Binding.class, endpoint.getBinding());
-        exchange.put(BindingInfo.class, endpoint.getEndpointInfo().getBinding());
         if (boi != null) {
             exchange.put(BindingOperationInfo.class, boi);
             exchange.put(OperationInfo.class, boi.getOperationInfo());
         }
                 
         exchange.put(MessageObserver.class, this);
+        exchange.put(Retryable.class, this);
         exchange.put(Bus.class, bus);
     }
 
-    protected PhaseInterceptorChain setupInterceptorChain() { 
+    protected PhaseInterceptorChain setupInterceptorChain(Endpoint endpoint) { 
 
         PhaseManager pm = bus.getExtension(PhaseManager.class);
         PhaseInterceptorChain chain = new PhaseInterceptorChain(pm.getOutPhases());
@@ -430,7 +457,7 @@
     }
 
     protected void setEndpoint(Endpoint e) {
-        endpoint = e;
+        getConduitSelector().setEndpoint(e);
     }
 
     public int getSynchronousTimeout() {
@@ -441,14 +468,22 @@
         this.synchronousTimeout = synchronousTimeout;
     }
     
-    public synchronized ConduitSelector getConduitSelector() {
+    public final ConduitSelector getConduitSelector() {
+        return getConduitSelector(null);
+    }
+    
+    protected final synchronized ConduitSelector getConduitSelector(
+        ConduitSelector override
+    ) {
         if (null == conduitSelector) {
-            conduitSelector = new UpfrontConduitSelector();
+            setConduitSelector(override != null
+                               ? override 
+                               : new UpfrontConduitSelector());
         }
         return conduitSelector;
     }
 
-    public void setConduitSelector(ConduitSelector selector) {
+    public final void setConduitSelector(ConduitSelector selector) {
         conduitSelector = selector;
     }
 

Modified: incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainInterceptor.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainInterceptor.java (original)
+++ incubator/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/OutgoingChainInterceptor.java Tue May  1 04:43:11 2007
@@ -81,7 +81,7 @@
                     ex.get(EndpointReferenceType.class);
                 conduit = ex.getDestination().getBackChannel(ex.getInMessage(), null, target);
                 ex.put(ConduitSelector.class, 
-                       new PreexistingConduitSelector(conduit));
+                       new PreexistingConduitSelector(conduit, ex.get(Endpoint.class)));
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java Tue May  1 04:43:11 2007
@@ -74,17 +74,10 @@
     private JAXBContext context;
     private Service.Mode mode;
 
-    private Endpoint endpoint;
     private ConduitSelector conduitSelector;
     
     DispatchImpl(Bus b, Service.Mode m, Class<T> clazz, Executor e, Endpoint ep) {
-        super(((JaxWsEndpointImpl)ep).getJaxwsBinding());
-        bus = b;
-        cl = clazz;
-        executor = e;
-        mode = m;
-        endpoint = ep;
-        setupEndpointAddressContext();
+        this(b, m, null, clazz, e, ep);
     }
 
     DispatchImpl(Bus b, Service.Mode m, JAXBContext ctx, Class<T> clazz, Executor e, Endpoint ep) {
@@ -94,11 +87,11 @@
         context = ctx;
         cl = clazz;
         mode = m;
-        endpoint = ep;
-        setupEndpointAddressContext();
+        getConduitSelector().setEndpoint(ep);
+        setupEndpointAddressContext(ep);
     }
 
-    private void setupEndpointAddressContext() {
+    private void setupEndpointAddressContext(Endpoint endpoint) {
         //NOTE for jms transport the address would be null
         if (null != endpoint
             && null != endpoint.getEndpointInfo().getAddress()) {
@@ -116,6 +109,7 @@
             LOG.info("Dispatch: invoke called");
         }
 
+        Endpoint endpoint = getEndpoint();
         Message message = endpoint.getBinding().createMessage();
 
         if (context != null) {
@@ -137,11 +131,11 @@
         Exchange exchange = new ExchangeImpl();
 
         exchange.setOutMessage(message);
-        setExchangeProperties(exchange);
+        setExchangeProperties(exchange, endpoint);
 
         message.setContent(Object.class, obj);
 
-        PhaseInterceptorChain chain = getDispatchOutChain();
+        PhaseInterceptorChain chain = getDispatchOutChain(endpoint);
         message.setInterceptorChain(chain);
 
         // setup conduit selector
@@ -211,7 +205,7 @@
         return inMsg;
     }
 
-    private PhaseInterceptorChain getDispatchOutChain() {
+    private PhaseInterceptorChain getDispatchOutChain(Endpoint endpoint) {
         PhaseManager pm = bus.getExtension(PhaseManager.class);
         PhaseInterceptorChain chain = new PhaseInterceptorChain(pm.getOutPhases());
 
@@ -235,6 +229,7 @@
     }
 
     public void onMessage(Message message) {
+        Endpoint endpoint = getEndpoint();
         message = endpoint.getBinding().createMessage(message);
 
         message.put(Message.REQUESTOR_ROLE, Boolean.TRUE);
@@ -271,7 +266,7 @@
 
     private Executor getExecutor() {
         if (executor == null) {
-            executor = endpoint.getService().getExecutor();
+            executor = getEndpoint().getService().getExecutor();
         }
         if (executor == null) {
             executor = Executors.newFixedThreadPool(5);
@@ -281,6 +276,10 @@
         }
         return executor;
     }
+    
+    private Endpoint getEndpoint() {
+        return getConduitSelector().getEndpoint();
+    }
 
     public Future<?> invokeAsync(T obj, AsyncHandler<T> asyncHandler) {
         Response<?> r = invokeAsync(obj);
@@ -313,11 +312,10 @@
     }
     
     protected void prepareConduitSelector(Message message) {
-        getConduitSelector().prepare(message);
         message.getExchange().put(ConduitSelector.class, getConduitSelector());
     }
     
-    protected void setExchangeProperties(Exchange exchange) {
+    protected void setExchangeProperties(Exchange exchange, Endpoint endpoint) {
         exchange.put(Service.Mode.class, mode);
         exchange.put(Class.class, cl);
         exchange.put(org.apache.cxf.service.Service.class, endpoint.getService());

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java Tue May  1 04:43:11 2007
@@ -57,17 +57,15 @@
     protected ThreadLocal <Map<String, Object>> responseContext =
             new ThreadLocal<Map<String, Object>>();
 
-    private Endpoint endpoint;
     private final Binding binding;
 
     public JaxWsClientProxy(Client c, Binding b) {
         super(c);
-        this.endpoint = c.getEndpoint();
         this.binding = b;
-        setupEndpointAddressContext();
+        setupEndpointAddressContext(getClient().getEndpoint());
     }
 
-    private void setupEndpointAddressContext() {
+    private void setupEndpointAddressContext(Endpoint endpoint) {
         // NOTE for jms transport the address would be null
         if (null != endpoint && null != endpoint.getEndpointInfo().getAddress()) {
             getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
@@ -77,6 +75,7 @@
 
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
+        Endpoint endpoint = getClient().getEndpoint();
         MethodDispatcher dispatcher = (MethodDispatcher)endpoint.getService().get(
                                                                                   MethodDispatcher.class
                                                                                       .getName());
@@ -142,7 +141,12 @@
             } else {
                 throw new WebServiceException(ex);
             }
+        } finally {
+            if (endpoint != getClient().getEndpoint()) {
+                setupEndpointAddressContext(getClient().getEndpoint());
+            }
         }
+        
         // need to do context mapping from cxf message to jax-ws
         ContextPropertiesMapping.mapResponsefromCxf2Jaxws(respContext);
         return result;
@@ -155,6 +159,7 @@
         FutureTask<Object> f = new FutureTask<Object>(new JAXWSAsyncCallable(this, method, oi, params,
                                                                              context));
 
+        Endpoint endpoint = getClient().getEndpoint();
         endpoint.getExecutor().execute(f);
         Response<?> r = new AsyncResponse<Object>(f, Object.class);
         if (params.length > 0 && params[params.length - 1] instanceof AsyncHandler) {

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/ServiceImplTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/ServiceImplTest.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/ServiceImplTest.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/ServiceImplTest.java Tue May  1 04:43:11 2007
@@ -38,6 +38,7 @@
 import org.apache.cxf.bus.spring.SpringBusFactory;
 import org.apache.cxf.calculator.CalculatorPortType;
 import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.endpoint.NullConduitSelector;
 import org.apache.cxf.frontend.ClientProxy;
 import org.apache.hello_world_soap_http.Greeter;
 import org.apache.hello_world_soap_http.SOAPService;
@@ -59,6 +60,9 @@
         
         Client client = ClientProxy.getClient(proxy);
         assertEquals("bar", client.getEndpoint().get("foo"));
+        assertNotNull("expected ConduitSelector", client.getConduitSelector());
+        assertTrue("unexpected ConduitSelector",
+                   client.getConduitSelector() instanceof NullConduitSelector);
     }
     
     @Override

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/soapServiceConfig.xml
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/soapServiceConfig.xml?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/soapServiceConfig.xml (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/soapServiceConfig.xml Tue May  1 04:43:11 2007
@@ -31,6 +31,9 @@
      <jaxws:properties>
       <entry key="foo" value="bar"/>
     </jaxws:properties>
+    <jaxws:conduitSelector>
+      <bean class="org.apache.cxf.endpoint.NullConduitSelector"/>
+    </jaxws:conduitSelector>
   </jaxws:client>
 
 </beans>

Modified: incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/ClientFactoryBean.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/ClientFactoryBean.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/ClientFactoryBean.java (original)
+++ incubator/cxf/trunk/rt/frontend/simple/src/main/java/org/apache/cxf/frontend/ClientFactoryBean.java Tue May  1 04:43:11 2007
@@ -56,8 +56,7 @@
     }
 
     protected void createClient(Endpoint ep) {
-        client = new ClientImpl(getBus(), ep);
-        client.setConduitSelector(getConduitSelector());
+        client = new ClientImpl(getBus(), ep, getConduitSelector());
     }
 
     protected void applyFeatures() {

Modified: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java (original)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java Tue May  1 04:43:11 2007
@@ -1722,6 +1722,11 @@
                         + " Conduit: " + getConduitName());
             }
             
+            if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
+                throw new IOException(connection.getResponseMessage());
+            }
+
+            
             Exchange exchange = outMessage.getExchange();
             
             if (isOneway(exchange)

Modified: incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java (original)
+++ incubator/cxf/trunk/rt/ws/addr/src/main/java/org/apache/cxf/ws/addressing/ContextUtils.java Tue May  1 04:43:11 2007
@@ -374,7 +374,8 @@
                         : OutgoingChainInterceptor.getOutInterceptorChain(exchange);
                     partialResponse.setInterceptorChain(chain);
                     exchange.put(ConduitSelector.class,
-                                 new PreexistingConduitSelector(backChannel));
+                                 new PreexistingConduitSelector(backChannel,
+                                                                exchange.get(Endpoint.class)));
 
                     if (!partialResponse.getInterceptorChain().doIntercept(partialResponse) 
                             && partialResponse.getContent(Exception.class) != null) {

Modified: incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/Proxy.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/Proxy.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/Proxy.java (original)
+++ incubator/cxf/trunk/rt/ws/rm/src/main/java/org/apache/cxf/ws/rm/Proxy.java Tue May  1 04:43:11 2007
@@ -206,13 +206,9 @@
     
     class RMClient extends ClientImpl {
 
-        org.apache.cxf.ws.addressing.EndpointReferenceType address;
-
         RMClient(Bus bus, Endpoint endpoint, Conduit conduit,
-            org.apache.cxf.ws.addressing.EndpointReferenceType a) {
-            super(bus, endpoint);  
-            address = a;
-            setConduitSelector(new DeferredConduitSelector(conduit) {
+                 final org.apache.cxf.ws.addressing.EndpointReferenceType a) {
+            super(bus, endpoint, new DeferredConduitSelector(conduit) {
                 @Override
                 public Conduit selectConduit(Message message) {
                     Conduit conduit = null;
@@ -220,8 +216,8 @@
                     org.apache.cxf.ws.addressing.EndpointReferenceType original = 
                         endpointInfo.getTarget();
                     try {
-                        if (null != address) {
-                            endpointInfo.setAddress(address);
+                        if (null != a) {
+                            endpointInfo.setAddress(a);
                         }
                         conduit = super.selectConduit(message);
                     } finally {
@@ -229,8 +225,7 @@
                     }
                     return conduit;
                 }
-            });
-
+            });  
         }
 
         @Override

Added: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/ControlImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/ControlImpl.java?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/ControlImpl.java (added)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/ControlImpl.java Tue May  1 04:43:11 2007
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.cxf.systest.clustering;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Future;
+import java.util.logging.Logger;
+
+import javax.jws.WebService;
+import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Endpoint;
+import javax.xml.ws.Response;
+
+import org.apache.cxf.greeter_control.Control;
+import org.apache.cxf.greeter_control.types.FaultLocation;
+import org.apache.cxf.greeter_control.types.StartGreeterResponse;
+import org.apache.cxf.greeter_control.types.StopGreeterResponse;
+
+
+@WebService(serviceName = "ControlService", 
+            portName = "ControlPort", 
+            endpointInterface = "org.apache.cxf.greeter_control.Control", 
+            targetNamespace = "http://cxf.apache.org/greeter_control")
+public class ControlImpl implements Control {
+    
+    private static final Logger LOG = Logger.getLogger(ControlImpl.class.getName());
+    private Map<String, Endpoint> endpoints = new HashMap<String, Endpoint>();
+    
+    public boolean startGreeter(String address) {
+        GreeterImpl implementor = new GreeterImpl(address);
+        endpoints.put(address, Endpoint.publish(address, implementor));
+        LOG.info("Published greeter endpoint on: " + address);
+        return true;        
+    }
+
+    public boolean stopGreeter(String address) {  
+        Endpoint endpoint = endpoints.get(address);
+        if (null != endpoint) {
+            LOG.info("Stopping Greeter endpoint on: " + address);
+            endpoint.stop();
+        } else {
+            LOG.info("No endpoint active for: " + address);
+        }
+        endpoint = null;
+        return true;
+    }
+    
+    //--Irrelevant Boilerplate
+
+    public void setFaultLocation(FaultLocation fl) {
+        // never called
+    }
+    
+    public Future<?> startGreeterAsync(String requestType, AsyncHandler<StartGreeterResponse> asyncHandler) {
+        // never called
+        return null;
+    }
+
+    public Response<StartGreeterResponse> startGreeterAsync(String requestType) {
+        // never called
+        return null;
+    }
+
+    public Response<StopGreeterResponse> stopGreeterAsync(String requestType) {
+        // never called
+        return null;
+    }
+
+    public Future<?> stopGreeterAsync(String requestType,
+                                      AsyncHandler<StopGreeterResponse> asyncHandler) {
+        // never called
+        return null;
+    }    
+}

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/ControlImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/FailoverTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/FailoverTest.java?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/FailoverTest.java (added)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/FailoverTest.java Tue May  1 04:43:11 2007
@@ -0,0 +1,256 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.clustering;
+
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.clustering.FailoverTargetSelector;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.greeter_control.ClusteredGreeterService;
+import org.apache.cxf.greeter_control.Control;
+import org.apache.cxf.greeter_control.ControlService;
+import org.apache.cxf.greeter_control.Greeter;
+import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Tests failover within a static cluster.
+ */
+public class FailoverTest extends AbstractBusClientServerTestBase {
+
+    private static final Logger LOG =
+        Logger.getLogger(FailoverTest.class.getName());
+    private static final String FAILOVER_CONFIG =
+        "org/apache/cxf/systest/clustering/failover.xml";
+    private static final String REPLICA_A =
+        "http://localhost:9051/SoapContext/GreeterPort";
+    private static final String REPLICA_B =
+        "http://localhost:9052/SoapContext/GreeterPort"; 
+    private static final String REPLICA_C =
+        "http://localhost:9053/SoapContext/GreeterPort"; 
+    private static final String REPLICA_D =
+        "http://localhost:9054/SoapContext/GreeterPort"; 
+
+
+    private Bus bus;
+    private Control control;
+    private Greeter greeter;
+    private List<String> targets;
+
+    @BeforeClass
+    public static void startServers() throws Exception {
+        assertTrue("server did not launch correctly",
+                   launchServer(Server.class));
+    }
+            
+    @Before
+    public void setUp() {
+        targets = new ArrayList<String>();
+        SpringBusFactory bf = new SpringBusFactory();    
+        bus = bf.createBus(FAILOVER_CONFIG);
+        BusFactory.setDefaultBus(bus);
+    }
+    
+    @After
+    public void tearDown() {
+        if (null != control) {
+            for (String address : targets) {
+                assertTrue("Failed to stop greeter",
+                           control.stopGreeter(address));
+            }
+        }
+        targets = null;
+        if (bus != null) {
+            bus.shutdown(true);
+        }
+    }
+
+    @Test
+    public void testNoFailoverAcrossBindings() throws Exception {        
+        startTarget(REPLICA_D);
+        setupGreeter();
+
+        try {
+            greeter.greetMe("fred");
+            fail("expected exception");
+        } catch (Exception e) {
+            verifyCurrentEndpoint(REPLICA_A);
+        }
+    }
+    
+    @Test
+    public void testRevertExceptionOnUnsucessfulFailover() throws Exception {        
+        startTarget(REPLICA_B);
+        startTarget(REPLICA_C);
+        setupGreeter();
+        stopTarget(REPLICA_C);
+        stopTarget(REPLICA_B);
+        
+        try {
+            greeter.greetMe("fred");
+            fail("expected exception");
+        } catch (Exception e) {
+            Throwable cause = e;
+            while (cause.getCause() != null) {
+                cause = cause.getCause();
+            }
+            // failover attempt bails after retried invocations on 
+            // started & stopped replicas B & C fail with HTTP 404  
+            // indicated by a thrown IOException("Not found"),
+            // in which case we should revert back to the original 
+            // java.net.ConnectionException on the unavailable 
+            // replica A
+            //
+            assertTrue("should revert to original exception when no failover",
+                       cause instanceof ConnectException);
+            
+            // similarly the current endpoint referenced by the client 
+            // should also revert back to the origianl replica A
+            //
+            verifyCurrentEndpoint(REPLICA_A);
+        }
+    }
+
+    @Test
+    public void testInitialFailoverOnPrimaryReplicaUnavailable() throws Exception {
+        startTarget(REPLICA_C);
+        setupGreeter();
+        String response = null;
+        
+        response = greeter.greetMe("fred");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));
+        verifyCurrentEndpoint(REPLICA_C);
+        
+        response = greeter.greetMe("joe");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));        
+    }
+
+    @Test
+    public void testFailoverOnCurrentReplicaDeath() throws Exception {
+        startTarget(REPLICA_C);
+        setupGreeter();
+        String response = null;
+        
+        response = greeter.greetMe("fred");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));
+        verifyCurrentEndpoint(REPLICA_C);
+        
+        startTarget(REPLICA_B);
+        stopTarget(REPLICA_C);
+        
+        response = greeter.greetMe("joe");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_B));
+        verifyCurrentEndpoint(REPLICA_B);
+    }
+    
+    @Test
+    public void testNoFailbackWhileCurrentReplicaLive() throws Exception {
+        startTarget(REPLICA_C);
+        setupGreeter();
+        String response = null;
+        
+        response = greeter.greetMe("fred");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));
+        verifyCurrentEndpoint(REPLICA_C);
+
+        startTarget(REPLICA_A);
+        response = greeter.greetMe("joe");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));
+        verifyCurrentEndpoint(REPLICA_C);
+        
+        startTarget(REPLICA_B);
+        response = greeter.greetMe("bob");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));
+        verifyCurrentEndpoint(REPLICA_C);
+        
+        stopTarget(REPLICA_B);
+        response = greeter.greetMe("john");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));
+        verifyCurrentEndpoint(REPLICA_C);
+        
+        stopTarget(REPLICA_A);
+        response = greeter.greetMe("mike");
+        assertNotNull("expected non-null response", response);
+        assertTrue("response unexpected unexpected target: " + response,
+                   response.endsWith(REPLICA_C));
+        verifyCurrentEndpoint(REPLICA_C);
+    }
+    
+    private void startTarget(String address) {
+        ControlService cs = new ControlService();
+        control = cs.getControlPort();
+
+        LOG.info("starting replicated target: " + address);
+        assertTrue("Failed to start greeter", control.startGreeter(address));
+        targets.add(address);
+    }
+    
+    private void stopTarget(String address) {
+        if (control != null
+            && targets.contains(address)) {
+            LOG.info("starting replicated target: " + address);
+            assertTrue("Failed to start greeter", control.stopGreeter(address));
+            targets.remove(address);
+        }
+    }
+
+    private void verifyCurrentEndpoint(String replica) {
+        assertEquals("unexpected current endpoint",
+                     replica,
+                     ClientProxy.getClient(greeter).getEndpoint().getEndpointInfo().getAddress());
+    }
+    
+    private void setupGreeter() {
+        ClusteredGreeterService cs = new ClusteredGreeterService();
+        // REVISIT: why doesn't the generic (i.e. non-Port-specific)
+        // Service.getPort() load the <jaxws:client> configuration?
+        greeter = cs.getReplicatedPortA();
+        assertTrue("unexpected conduit slector",
+                   ClientProxy.getClient(greeter).getConduitSelector()
+                   instanceof FailoverTargetSelector);
+    }
+}

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/FailoverTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/GreeterImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/GreeterImpl.java?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/GreeterImpl.java (added)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/GreeterImpl.java Tue May  1 04:43:11 2007
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.clustering;
+
+import javax.jws.WebService;
+
+import org.apache.cxf.greeter_control.AbstractGreeterImpl;
+
+@WebService(serviceName = "GreeterService",
+            portName = "GreeterPort",
+            endpointInterface = "org.apache.cxf.greeter_control.Greeter",
+            targetNamespace = "http://cxf.apache.org/greeter_control",
+            wsdlLocation = "testutils/greeter_control.wsdl")
+public class GreeterImpl extends AbstractGreeterImpl {
+    private String address;
+    
+    GreeterImpl(String addr) {
+        address = addr;    
+    }
+    
+    public String greetMe(String s) {
+        return super.greetMe(s) + " from: " + address;
+    }
+}

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/GreeterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/Server.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/Server.java?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/Server.java (added)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/Server.java Tue May  1 04:43:11 2007
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.systest.clustering;
+
+
+import javax.xml.ws.Endpoint;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.bus.spring.SpringBusFactory;
+import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
+
+public class Server extends AbstractBusTestServerBase {
+   
+    private static final String ADDRESS = "http://localhost:9001/SoapContext/ControlPort";
+ 
+    protected void run()  {
+
+        SpringBusFactory factory = new SpringBusFactory();
+        Bus bus = factory.createBus();
+        BusFactory.setDefaultBus(bus);
+        setBus(bus);
+
+        ControlImpl implementor = new ControlImpl();
+        Endpoint.publish(ADDRESS, implementor);
+    }
+
+    public static void main(String[] args) {
+        try { 
+            Server s = new Server(); 
+            s.start();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            System.exit(-1);
+        } finally { 
+            System.out.println("done!");
+        }
+    }
+
+}

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/Server.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/failover.xml
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/failover.xml?view=auto&rev=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/failover.xml (added)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/failover.xml Tue May  1 04:43:11 2007
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+ 
+  http://www.apache.org/licenses/LICENSE-2.0
+ 
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:jaxws="http://cxf.apache.org/jaxws"
+       xsi:schemaLocation="
+http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+  
+    <jaxws:client id="{http://cxf.apache.org/greeter_control}ReplicatedPortA"
+                  createdFromAPI="true">
+        <jaxws:conduitSelector>
+            <bean class="org.apache.cxf.clustering.FailoverTargetSelector"/>
+        </jaxws:conduitSelector>
+    </jaxws:client>
+
+    <jaxws:client id="{http://cxf.apache.org/greeter_control}ReplicatedPortB"
+                  createdFromAPI="true">
+        <jaxws:conduitSelector>
+            <bean class="org.apache.cxf.clustering.FailoverTargetSelector"/>
+        </jaxws:conduitSelector>
+    </jaxws:client>
+    
+    <jaxws:client id="{http://cxf.apache.org/greeter_control}ReplicatedPortC"
+                  createdFromAPI="true">
+        <jaxws:conduitSelector>
+            <bean class="org.apache.cxf.clustering.FailoverTargetSelector"/>
+        </jaxws:conduitSelector>
+    </jaxws:client>
+</beans>

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/failover.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/clustering/failover.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/interceptor/InterceptorFaultTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/interceptor/InterceptorFaultTest.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/interceptor/InterceptorFaultTest.java (original)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/interceptor/InterceptorFaultTest.java Tue May  1 04:43:11 2007
@@ -131,12 +131,12 @@
     @After
     public void tearDown() {
         if (null != greeter) {
-            assertTrue("Failed to stop greeter.", control.stopGreeter());
+            assertTrue("Failed to stop greeter.", control.stopGreeter(null));
             greeterBus.shutdown(true);
             greeterBus = null;
         }
         if (null != control) {  
-            assertTrue("Failed to stop greeter", control.stopGreeter());
+            assertTrue("Failed to stop greeter", control.stopGreeter(null));
             controlBus.shutdown(true);
         }
     }

Modified: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/addressing/wsa_interceptors.xml
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/addressing/wsa_interceptors.xml?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/addressing/wsa_interceptors.xml (original)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/addressing/wsa_interceptors.xml Tue May  1 04:43:11 2007
@@ -59,7 +59,7 @@
     </bean>
 
     <jaxws:client id="{http://apache.org/hello_world_soap_http}SoapPort" 
-                  abstract="true">
+                  createdFromAPI="true">
         <jaxws:conduitSelector>
             <bean class="org.apache.cxf.endpoint.DeferredConduitSelector"/>
         </jaxws:conduitSelector>

Modified: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/ControlImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/ControlImpl.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/ControlImpl.java (original)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/ControlImpl.java Tue May  1 04:43:11 2007
@@ -41,7 +41,7 @@
     private static final Logger LOG = Logger.getLogger(ControlImpl.class.getName());
     
     @Override
-    public boolean stopGreeter() {  
+    public boolean stopGreeter(String requestType) {  
         
         if (null != endpoint) {
             LOG.info("Stopping Greeter endpoint");

Modified: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/SequenceTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/SequenceTest.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/SequenceTest.java (original)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/ws/rm/SequenceTest.java Tue May  1 04:43:11 2007
@@ -121,14 +121,14 @@
     @After
     public void tearDown() {
         if (null != greeter) {
-            assertTrue("Failed to stop greeter.", control.stopGreeter());                        
+            assertTrue("Failed to stop greeter.", control.stopGreeter(null));                        
             RMManager manager = greeterBus.getExtension(RMManager.class);
             manager.shutdown();
             greeterBus.shutdown(true);
             greeterBus = null;
         }
         if (null != control) {  
-            assertTrue("Failed to stop greeter", control.stopGreeter());
+            assertTrue("Failed to stop greeter", control.stopGreeter(null));
             controlBus.shutdown(true);
         }
     }

Modified: incubator/cxf/trunk/testutils/src/main/java/org/apache/cxf/greeter_control/ControlImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/testutils/src/main/java/org/apache/cxf/greeter_control/ControlImpl.java?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/testutils/src/main/java/org/apache/cxf/greeter_control/ControlImpl.java (original)
+++ incubator/cxf/trunk/testutils/src/main/java/org/apache/cxf/greeter_control/ControlImpl.java Tue May  1 04:43:11 2007
@@ -93,7 +93,7 @@
         return null != greeterBus; 
     }
 
-    public boolean stopGreeter() {  
+    public boolean stopGreeter(String requestType) {  
         LOG.fine("Stopping greeter");
         
         if (null != endpoint) {
@@ -143,12 +143,12 @@
         return null;
     }
 
-    public Response<StopGreeterResponse> stopGreeterAsync() {
+    public Response<StopGreeterResponse> stopGreeterAsync(String requestType) {
         // never called
         return null;
     }
 
-    public Future<?> stopGreeterAsync(AsyncHandler<StopGreeterResponse> asyncHandler) {
+    public Future<?> stopGreeterAsync(String requestType, AsyncHandler<StopGreeterResponse> asyncHandler) {
         // never called
         return null;
     }

Modified: incubator/cxf/trunk/testutils/src/main/resources/wsdl/greeter_control.wsdl
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/testutils/src/main/resources/wsdl/greeter_control.wsdl?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/testutils/src/main/resources/wsdl/greeter_control.wsdl (original)
+++ incubator/cxf/trunk/testutils/src/main/resources/wsdl/greeter_control.wsdl Tue May  1 04:43:11 2007
@@ -88,7 +88,11 @@
                 </complexType>
             </element>
             <element name="stopGreeter">
-                <complexType/>
+                <complexType>
+                    <sequence>
+                        <element name="requestType" type="xsd:string"/>
+                    </sequence>
+                </complexType>
             </element>
             <element name="stopGreeterResponse">
                 <complexType>
@@ -294,6 +298,22 @@
         <wsdl:port binding="tns:GreeterSOAPBinding" name="GreeterPort">
             <soap:address location="http://localhost:9020/SoapContext/GreeterPort"/>
         </wsdl:port>
+    </wsdl:service>
+
+    <wsdl:service name="ClusteredGreeterService">
+        <wsdl:port binding="tns:GreeterSOAPBinding" name="ReplicatedPortA">
+            <soap:address location="http://localhost:9051/SoapContext/GreeterPort"/>
+        </wsdl:port>
+        <wsdl:port binding="tns:GreeterSOAPBinding" name="ReplicatedPortB">
+            <soap:address location="http://localhost:9052/SoapContext/GreeterPort"/>
+        </wsdl:port>
+        <wsdl:port binding="tns:GreeterSOAPBinding" name="ReplicatedPortC">
+            <soap:address location="http://localhost:9053/SoapContext/GreeterPort"/>
+        </wsdl:port>
+                <wsdl:port binding="tns:ControlSOAPBinding" name="ReplicatedPortD">
+            <soap:address location="http://localhost:9054/SoapContext/GreeterPort"/>
+        </wsdl:port>
+        
     </wsdl:service>
 
 </wsdl:definitions>

Modified: incubator/cxf/trunk/testutils/src/main/resources/wsdl/hello_world.wsdl
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/testutils/src/main/resources/wsdl/hello_world.wsdl?view=diff&rev=534016&r1=534015&r2=534016
==============================================================================
--- incubator/cxf/trunk/testutils/src/main/resources/wsdl/hello_world.wsdl (original)
+++ incubator/cxf/trunk/testutils/src/main/resources/wsdl/hello_world.wsdl Tue May  1 04:43:11 2007
@@ -392,7 +392,6 @@
     </wsdl:service>
     <wsdl:service name="SOAPServiceBogusAddressTest">
         <wsdl:port name="SoapPort" binding="tns:Greeter_SOAPBinding">
-            <!--<soap:address location="http://nowhere.nada.nil:45678/null/never"/>-->
             <soap:address location="FOO"/>
         </wsdl:port>
     </wsdl:service>



Mime
View raw message