Author: sergeyb
Date: Tue Nov 12 19:10:45 2013
New Revision: 1541199
URL: http://svn.apache.org/r1541199
Log:
[CXF-5378] Optional support for the failover feature reacting to HTTP errors
Modified:
cxf/trunk/rt/features/clustering/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/FailoverTest.java
Modified:
cxf/trunk/rt/features/clustering/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/features/clustering/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java?rev=1541199&r1=1541198&r2=1541199&view=diff
==============================================================================
---
cxf/trunk/rt/features/clustering/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java
(original)
+++
cxf/trunk/rt/features/clustering/src/main/java/org/apache/cxf/clustering/FailoverTargetSelector.java
Tue Nov 12 19:10:45 2013
@@ -26,6 +26,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.PropertyUtils;
import org.apache.cxf.endpoint.AbstractConduitSelector;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
@@ -51,7 +52,7 @@ public class FailoverTargetSelector exte
protected ConcurrentHashMap<InvocationKey, InvocationContext> inProgress
= new ConcurrentHashMap<InvocationKey, InvocationContext>();;
protected FailoverStrategy failoverStrategy;
-
+ private boolean supportNotAvailableErrorsOnly;
/**
* Normal constructor.
*/
@@ -78,6 +79,8 @@ public class FailoverTargetSelector exte
return;
}
Exchange exchange = message.getExchange();
+ setupExchangeExceptionProperties(exchange);
+
InvocationKey key = new InvocationKey(exchange);
if (!inProgress.containsKey(key)) {
Endpoint endpoint = exchange.get(Endpoint.class);
@@ -95,6 +98,10 @@ public class FailoverTargetSelector exte
}
}
+ protected void setupExchangeExceptionProperties(Exchange ex) {
+ ex.remove("org.apache.cxf.transport.no_io_exceptions");
+ }
+
/**
* Called when a Conduit is actually required.
*
@@ -121,7 +128,7 @@ public class FailoverTargetSelector exte
invocation = inProgress.get(key);
}
boolean failover = false;
- if (requiresFailover(exchange)) {
+ if (invocation != null && requiresFailover(exchange)) {
Conduit old =
(Conduit)exchange.getOutMessage().remove(Conduit.class.getName());
Endpoint failoverTarget = getFailoverTarget(exchange, invocation);
@@ -242,6 +249,12 @@ public class FailoverTargetSelector exte
"CHECK_FAILURE_IN_TRANSPORT",
new Object[] {ex, failover});
}
+ if (failover
+ && isSupportNotAvailableErrorsOnly()
+ && exchange.get(Message.RESPONSE_CODE) != null
+ &&
!PropertyUtils.isTrue(exchange.get("org.apache.cxf.transport.service_not_available")))
{
+ failover = false;
+ }
return failover;
}
@@ -342,6 +355,14 @@ public class FailoverTargetSelector exte
return false;
}
+ public boolean isSupportNotAvailableErrorsOnly() {
+ return supportNotAvailableErrorsOnly;
+ }
+
+ public void setSupportNotAvailableErrorsOnly(boolean support) {
+ this.supportNotAvailableErrorsOnly = support;
+ }
+
/**
* 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
Modified:
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java?rev=1541199&r1=1541198&r2=1541199&view=diff
==============================================================================
---
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
(original)
+++
cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
Tue Nov 12 19:10:45 2013
@@ -944,7 +944,7 @@ public abstract class AbstractClient imp
exchange.put(Bus.class, cfg.getBus());
exchange.put(MessageObserver.class, new ClientMessageObserver(cfg));
exchange.put(Endpoint.class, cfg.getConduitSelector().getEndpoint());
- exchange.put("org.apache.cxf.http.no_io_exceptions", true);
+ exchange.put("org.apache.cxf.transport.no_io_exceptions", true);
//REVISIT - when response handling is actually put onto the in chain,
this will likely not be needed
exchange.put(StaxInEndingInterceptor.STAX_IN_NOCLOSE, Boolean.TRUE);
m.setExchange(exchange);
Modified:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java?rev=1541199&r1=1541198&r2=1541199&view=diff
==============================================================================
---
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
(original)
+++
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
Tue Nov 12 19:10:45 2013
@@ -1551,8 +1551,13 @@ public abstract class HTTPConduit
// This property should be set in case the exceptions should not
be handled here
// For example jax rs uses this
boolean noExceptions =
MessageUtils.isTrue(outMessage.getContextualProperty(
- "org.apache.cxf.http.no_io_exceptions"));
+ "org.apache.cxf.transport.no_io_exceptions"));
+
if (responseCode >= 400 && responseCode != 500 && !noExceptions) {
+
+ if (responseCode == 404 || responseCode == 503) {
+
exchange.put("org.apache.cxf.transport.service_not_available", true);
+ }
throw new HTTPException(responseCode, getResponseMessage(),
url.toURL());
}
Modified:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java?rev=1541199&r1=1541198&r2=1541199&view=diff
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
(original)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSSoapBookTest.java
Tue Nov 12 19:10:45 2013
@@ -911,7 +911,7 @@ public class JAXRSSoapBookTest extends A
features.add(testFeature);
bean.setFeatures(features);
BookStoreJaxrsJaxws proxy = (BookStoreJaxrsJaxws)bean.create();
-
WebClient.getConfig(proxy).getRequestContext().put("org.apache.cxf.http.no_io_exceptions",
false);
+
WebClient.getConfig(proxy).getRequestContext().put("org.apache.cxf.transport.no_io_exceptions",
false);
try {
//321 is special case - causes error code of 525
proxy.getBook(new Long(param));
Modified:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/FailoverTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/FailoverTest.java?rev=1541199&r1=1541198&r2=1541199&view=diff
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/FailoverTest.java
(original)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/failover/FailoverTest.java
Tue Nov 12 19:10:45 2013
@@ -111,6 +111,26 @@ public class FailoverTest extends Abstra
}
@Test
+ public void testSequentialStrategyWith404() throws Exception {
+ FailoverFeature feature = getFeature(false, false, Server.ADDRESS3);
+ feature.getTargetSelector().setSupportNotAvailableErrorsOnly(true);
+ strategyTestWebClient(Server.ADDRESS2 + "/new", feature,
Server.ADDRESS3, null, false, false);
+ }
+
+ @Test
+ public void testSequentialStrategyWith406() throws Exception {
+ FailoverFeature feature = getFeature(false, false, Server.ADDRESS3);
+ strategyTestWebClientHttpError(Server.ADDRESS2, feature,
Server.ADDRESS3, false);
+ }
+
+ @Test
+ public void testSequentialStrategyWith406NoFailover() throws Exception {
+ FailoverFeature feature = getFeature(false, false, Server.ADDRESS3);
+ feature.getTargetSelector().setSupportNotAvailableErrorsOnly(true);
+ strategyTestWebClientHttpError(Server.ADDRESS2, feature,
Server.ADDRESS3, true);
+ }
+
+ @Test
public void testRandomStrategyWebClient() throws Exception {
FailoverFeature feature =
getFeature(false, true, Server.ADDRESS3, Server.ADDRESS2);
@@ -341,6 +361,23 @@ public class FailoverTest extends Abstra
expectRandom,
randomized);
}
+
+ protected void strategyTestWebClientHttpError(String currentReplica,
+ FailoverFeature feature,
+ String newReplica,
+ boolean notAvailableOnly) throws Exception {
+ WebClient bookStore = getWebClient(currentReplica, feature);
+ verifyStrategy(bookStore, SequentialStrategy.class);
+ bookStore.path("bookstore/webappexceptionXML");
+ Response r = bookStore.get();
+ assertEquals(406, r.getStatus());
+ String currEndpoint = getCurrentEndpointAddress(bookStore);
+ if (notAvailableOnly) {
+ assertTrue(currEndpoint.equals(currentReplica));
+ } else {
+ assertTrue(currEndpoint.equals(newReplica));
+ }
+ }
protected String getCurrentEndpointAddress(Object client) {