Repository: camel Updated Branches: refs/heads/camel-2.15.x 5e121e91d -> f8905dc27
CAMEL-9230: CXFRS NPE when response code not in Response.Status. Thanks to Ron Ten-Hove for the patch. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f8905dc2 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f8905dc2 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f8905dc2 Branch: refs/heads/camel-2.15.x Commit: f8905dc27f6cc3a2d840fe6654f9ebb8a37fb067 Parents: 5e121e9 Author: Claus Ibsen <davscl...@apache.org> Authored: Sat Oct 17 09:57:07 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sat Oct 17 09:59:53 2015 +0200 ---------------------------------------------------------------------- .../component/cxf/jaxrs/CxfRsProducer.java | 28 +++++++++++++++++++- .../component/cxf/jaxrs/CxfRsProducerTest.java | 27 +++++++++++++++++++ .../cxf/jaxrs/testbean/CustomerService.java | 7 +++-- 3 files changed, 59 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/f8905dc2/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java index 734d972..358987f 100644 --- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java +++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java @@ -402,7 +402,7 @@ public class CxfRsProducer extends DefaultProducer { protected CxfOperationException populateCxfRsProducerException(Exchange exchange, Response response, int responseCode) { CxfOperationException exception; String uri = exchange.getFromEndpoint().getEndpointUri(); - String statusText = Response.Status.fromStatusCode(responseCode).toString(); + String statusText = statusTextFromResponseCode(responseCode); Map<String, String> headers = parseResponseHeaders(response, exchange); //Get the response detail string String copy = exchange.getContext().getTypeConverter().convertTo(String.class, response.getEntity()); @@ -423,6 +423,32 @@ public class CxfRsProducer extends DefaultProducer { return exception; } + /** + * Convert the given HTTP response code to its corresponding status text or + * response category. This is useful to avoid creating NPEs if this producer + * is presented with an HTTP response code that the JAX-RS API doesn't know. + * + * @param responseCode the HTTP response code to be converted to status text + * @return the status text for the code, or, if JAX-RS doesn't know the code, + * the status category as text + */ + String statusTextFromResponseCode(int responseCode) { + Response.Status status = Response.Status.fromStatusCode(responseCode); + + return status != null ? status.toString() : responseCategoryFromCode(responseCode); + } + + /** + * Return the category of the given HTTP response code, as text. Invalid + * codes will result in appropriate text; this method never returns null. + * + * @param responseCode HTTP response code whose category is to be returned + * @return the category of the give response code; never {@code null}. + */ + private String responseCategoryFromCode(int responseCode) { + return Response.Status.Family.familyOf(responseCode).name(); + } + protected Map<String, String> parseResponseHeaders(Object response, Exchange camelExchange) { Map<String, String> answer = new HashMap<String, String>(); http://git-wip-us.apache.org/repos/asf/camel/blob/f8905dc2/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerTest.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerTest.java b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerTest.java index 1ed46a7..50bd010 100644 --- a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerTest.java +++ b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducerTest.java @@ -42,6 +42,10 @@ import org.junit.Test; import org.springframework.context.support.AbstractXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; + public class CxfRsProducerTest extends CamelSpringTestSupport { private static int port1 = CXFTestSupport.getPort1(); private static int port2 = CXFTestSupport.getPort("CxfRsProducerTest.jetty"); @@ -468,4 +472,27 @@ public class CxfRsProducerTest extends CamelSpringTestSupport { assertTrue("The feature should be initialized", feature.initialized); } + @Test + public void testProducer422Response() { + Exchange exchange = template.send("cxfrs://http://localhost:" + getPort1() + "/" + getClass().getSimpleName() + "/?httpClientAPI=true", new Processor() { + public void process(Exchange exchange) throws Exception { + exchange.setPattern(ExchangePattern.InOut); + Message message = exchange.getIn(); + // Try to create a new Customer with an invalid name + message.setHeader(Exchange.HTTP_METHOD, "POST"); + message.setHeader(Exchange.HTTP_PATH, "/customerservice/customers"); + Customer customer = new Customer(); + customer.setId(8888); + customer.setName(""); // will trigger a 422 response (a common REST server validation response code) + message.setBody(customer); + } + }); + + assertNotNull("Expect the exception here", exchange.getException()); + assertThat("Exception should be a CxfOperationException", exchange.getException(), instanceOf(CxfOperationException.class)); + + CxfOperationException cxfOperationException = CxfOperationException.class.cast(exchange.getException()); + + assertThat("CXF operation exception has correct response code", cxfOperationException.getStatusCode(), is(422)); + } } http://git-wip-us.apache.org/repos/asf/camel/blob/f8905dc2/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/CustomerService.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/CustomerService.java b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/CustomerService.java index 39ec9df..c051948 100644 --- a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/CustomerService.java +++ b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/CustomerService.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; - import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -32,7 +31,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; - +import org.apache.cxf.common.util.StringUtils; /** * @@ -91,6 +90,10 @@ public class CustomerService { @POST @Path("/customers/") public Response addCustomer(Customer customer) { + if (StringUtils.isEmpty(customer.getName())) { + return Response.status(422).build(); + } + customer.setId(currentId.incrementAndGet()); customers.put(customer.getId(), customer);