Repository: camel Updated Branches: refs/heads/master 295e0d62c -> f3a5e219a
CAMEL-8372: CXFRS consumer should use a default handler if a model resource has no registered handler Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f3a5e219 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f3a5e219 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f3a5e219 Branch: refs/heads/master Commit: f3a5e219aaccf5dc0a09d2031d72b7022c65495f Parents: 295e0d6 Author: Akitoshi Yoshida <[email protected]> Authored: Fri Feb 20 14:40:18 2015 +0100 Committer: Akitoshi Yoshida <[email protected]> Committed: Fri Feb 20 14:40:18 2015 +0100 ---------------------------------------------------------------------- .../component/cxf/jaxrs/CxfRsEndpoint.java | 45 ++++++- .../cxf/jaxrs/DefaultModelResource.java | 31 +++++ .../component/cxf/jaxrs/CxfRsConsumerTest.java | 133 +++++++++++++------ .../CustomerServiceDefaultHandlerModel.xml | 27 ++++ 4 files changed, 189 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/f3a5e219/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java index 70bf5d2..04368a7 100644 --- a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java +++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsEndpoint.java @@ -49,6 +49,8 @@ import org.apache.cxf.jaxrs.AbstractJAXRSFactoryBean; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; import org.apache.cxf.jaxrs.model.ClassResourceInfo; +import org.apache.cxf.jaxrs.model.UserResource; +import org.apache.cxf.jaxrs.utils.ResourceUtils; import org.apache.cxf.logging.FaultListener; import org.apache.cxf.message.Message; import org.slf4j.Logger; @@ -216,9 +218,7 @@ public class CxfRsEndpoint extends DefaultEndpoint implements HeaderFilterStrate if (getAddress() != null) { sfb.setAddress(getAddress()); } - if (modelRef != null) { - sfb.setModelRef(modelRef); - } + processResourceModel(sfb); if (getResourceClasses() != null) { sfb.setResourceClasses(getResourceClasses()); } @@ -235,6 +235,36 @@ public class CxfRsEndpoint extends DefaultEndpoint implements HeaderFilterStrate sfb.setStart(false); } + private void processResourceModel(JAXRSServerFactoryBean sfb) { + // Currently a CXF model document is the only possible source + // of the model. Other sources will be supported going forward + if (modelRef != null) { + + List<UserResource> resources = ResourceUtils.getUserResources(modelRef, sfb.getBus()); + + processUserResources(sfb, resources); + } + } + + /* + * Prepare model beans and set them on the factory. + * The model beans can be created from a variety of sources such as + * CXF Model extensions but also other documents (to be supported in the future). + */ + private void processUserResources(JAXRSServerFactoryBean sfb, List<UserResource> resources) { + for (UserResource resource : resources) { + if (resource.getName() == null) { + resource.setName(DefaultModelResource.class.getName()); + } + } + // The CXF to Camel exchange binding may need to be customized + // for the operation name, request, response types be derived from + // the model info (when a given model does provide this info) as opposed + // to a matched method which is of no real use with a default handler. + sfb.setModelBeans(resources); + + } + protected void setupJAXRSClientFactoryBean(JAXRSClientFactoryBean cfb, String address) { // address if (address != null) { @@ -301,7 +331,14 @@ public class CxfRsEndpoint extends DefaultEndpoint implements HeaderFilterStrate } protected JAXRSServerFactoryBean newJAXRSServerFactoryBean() { - return new JAXRSServerFactoryBean(); + return new JAXRSServerFactoryBean() { + protected boolean isValidClassResourceInfo(ClassResourceInfo cri) { + // CXF will consider interfaces created for managing model resources + // invalid - however it is fine with Camel processors if no service invocation + // is requested. + return !performInvocation || !cri.getServiceClass().isInterface(); + } + }; } protected JAXRSClientFactoryBean newJAXRSClientFactoryBean() { http://git-wip-us.apache.org/repos/asf/camel/blob/f3a5e219/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultModelResource.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultModelResource.java b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultModelResource.java new file mode 100644 index 0000000..fe83f76 --- /dev/null +++ b/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/DefaultModelResource.java @@ -0,0 +1,31 @@ +/** + * 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.camel.component.cxf.jaxrs; + +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; + +import org.apache.cxf.jaxrs.ext.DefaultMethod; +/** + * Default JAX-RS resource that may be used + * to support document-only CXFRS consumers + */ +public interface DefaultModelResource { + @Path("{path:.*}") + @DefaultMethod + Response defaultResourceMethod(); +} http://git-wip-us.apache.org/repos/asf/camel/blob/f3a5e219/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java index fe1071a..cd6d683 100644 --- a/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java +++ b/components/camel-cxf/src/test/java/org/apache/camel/component/cxf/jaxrs/CxfRsConsumerTest.java @@ -18,10 +18,16 @@ package org.apache.camel.component.cxf.jaxrs; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import javax.servlet.ServletRequest; +import javax.ws.rs.HttpMethod; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.camel.Exchange; @@ -56,15 +62,20 @@ public class CxfRsConsumerTest extends CamelTestSupport { "cxfrs://http://localhost:" + CXT + "/rest3?" + "resourceClasses=org.apache.camel.component.cxf.jaxrs.testbean.CustomerServiceNoAnnotations&" + "modelRef=classpath:/org/apache/camel/component/cxf/jaxrs/CustomerServiceModel.xml"; + private static final String CXF_RS_ENDPOINT_URI4 = + "cxfrs://http://localhost:" + CXT + "/rest4?" + + "modelRef=classpath:/org/apache/camel/component/cxf/jaxrs/CustomerServiceDefaultHandlerModel.xml"; protected RouteBuilder createRouteBuilder() throws Exception { final Processor testProcessor = new TestProcessor(); + final Processor testProcessor2 = new TestProcessor2(); return new RouteBuilder() { public void configure() { errorHandler(new NoErrorHandlerBuilder()); from(CXF_RS_ENDPOINT_URI).process(testProcessor); from(CXF_RS_ENDPOINT_URI2).process(testProcessor); from(CXF_RS_ENDPOINT_URI3).process(testProcessor); + from(CXF_RS_ENDPOINT_URI4).process(testProcessor2); } }; } @@ -97,6 +108,19 @@ public class CxfRsConsumerTest extends CamelTestSupport { public void testGetCustomerInterfaceAndModel() throws Exception { doTestGetCustomer("rest3"); } + @Test + public void testGetCustomerDefaultHandlerAndModel() throws Exception { + doTestGetCustomer("rest4"); + } + @Test + public void testEchoCustomerDefaultHandlerAndModel() throws Exception { + WebTarget target = + ClientBuilder.newClient().target("http://localhost:" + CXT + "/" + "rest4" + "/customerservice/customers"); + Customer c = + target.request(MediaType.APPLICATION_JSON).post(Entity.json(new Customer(333, "Barry")), Customer.class); + assertEquals(333L, c.getId()); + assertEquals("Barry", c.getName()); + } private void doTestGetCustomer(String contextUri) throws Exception { invokeGetCustomer("http://localhost:" + CXT + "/" + contextUri + "/customerservice/customers/126", @@ -154,54 +178,60 @@ public class CxfRsConsumerTest extends CamelTestSupport { httpclient.close(); } } - - private static class TestProcessor implements Processor { + + private static abstract class AbstractTestProcessor implements Processor { + public void processGetCustomer(Exchange exchange) throws Exception { + Message inMessage = exchange.getIn(); + String httpMethod = inMessage.getHeader(Exchange.HTTP_METHOD, String.class); + assertEquals("Get a wrong http method", "GET", httpMethod); + String path = inMessage.getHeader(Exchange.HTTP_PATH, String.class); + // The parameter of the invocation is stored in the body of in message + String id = inMessage.getBody(String.class); + if ("/customerservice/customers/126".equals(path)) { + Customer customer = new Customer(); + customer.setId(Long.parseLong(id)); + customer.setName("Willem"); + // We just put the response Object into the out message body + exchange.getOut().setBody(customer); + } else { + if ("/customerservice/customers/400".equals(path)) { + // We return the remote client IP address this time + org.apache.cxf.message.Message cxfMessage = inMessage.getHeader(CxfConstants.CAMEL_CXF_MESSAGE, org.apache.cxf.message.Message.class); + ServletRequest request = (ServletRequest) cxfMessage.get("HTTP.REQUEST"); + // Just make sure the request object is not null + assertNotNull("The request object should not be null", request); + Response r = Response.status(200).entity("The remoteAddress is 127.0.0.1").build(); + exchange.getOut().setBody(r); + return; + } + if ("/customerservice/customers/123".equals(path)) { + // send a customer response back + Response r = Response.status(200).entity("customer response back!").build(); + exchange.getOut().setBody(r); + return; + } + if ("/customerservice/customers/456".equals(path)) { + Response r = Response.status(404).entity("Can't found the customer with uri " + path).build(); + throw new WebApplicationException(r); + } else if ("/customerservice/customers/234".equals(path)) { + Response r = Response.status(404).entity("Can't found the customer with uri " + path).build(); + exchange.getOut().setBody(r); + exchange.getOut().setFault(true); + } else { + throw new RuntimeCamelException("Can't found the customer with uri " + path); + } + } + } + + } + private static class TestProcessor extends AbstractTestProcessor { public void process(Exchange exchange) throws Exception { Message inMessage = exchange.getIn(); // Get the operation name from in message String operationName = inMessage.getHeader(CxfConstants.OPERATION_NAME, String.class); if ("getCustomer".equals(operationName)) { - String httpMethod = inMessage.getHeader(Exchange.HTTP_METHOD, String.class); - assertEquals("Get a wrong http method", "GET", httpMethod); - String path = inMessage.getHeader(Exchange.HTTP_PATH, String.class); - // The parameter of the invocation is stored in the body of in message - String id = inMessage.getBody(String.class); - if ("/customerservice/customers/126".equals(path)) { - Customer customer = new Customer(); - customer.setId(Long.parseLong(id)); - customer.setName("Willem"); - // We just put the response Object into the out message body - exchange.getOut().setBody(customer); - } else { - if ("/customerservice/customers/400".equals(path)) { - // We return the remote client IP address this time - org.apache.cxf.message.Message cxfMessage = inMessage.getHeader(CxfConstants.CAMEL_CXF_MESSAGE, org.apache.cxf.message.Message.class); - ServletRequest request = (ServletRequest) cxfMessage.get("HTTP.REQUEST"); - // Just make sure the request object is not null - assertNotNull("The request object should not be null", request); - Response r = Response.status(200).entity("The remoteAddress is 127.0.0.1").build(); - exchange.getOut().setBody(r); - return; - } - if ("/customerservice/customers/123".equals(path)) { - // send a customer response back - Response r = Response.status(200).entity("customer response back!").build(); - exchange.getOut().setBody(r); - return; - } - if ("/customerservice/customers/456".equals(path)) { - Response r = Response.status(404).entity("Can't found the customer with uri " + path).build(); - throw new WebApplicationException(r); - } else if ("/customerservice/customers/234".equals(path)) { - Response r = Response.status(404).entity("Can't found the customer with uri " + path).build(); - exchange.getOut().setBody(r); - exchange.getOut().setFault(true); - } else { - throw new RuntimeCamelException("Can't found the customer with uri " + path); - } - } - } - if ("updateCustomer".equals(operationName)) { + processGetCustomer(exchange); + } else if ("updateCustomer".equals(operationName)) { assertEquals("Get a wrong customer message header", "header1;header2", inMessage.getHeader("test")); String httpMethod = inMessage.getHeader(Exchange.HTTP_METHOD, String.class); assertEquals("Get a wrong http method", "PUT", httpMethod); @@ -216,4 +246,21 @@ public class CxfRsConsumerTest extends CamelTestSupport { } } + private static class TestProcessor2 extends AbstractTestProcessor { + public void process(Exchange exchange) throws Exception { + Message inMessage = exchange.getIn(); + // Get the operation name from in message + String path = inMessage.getHeader(Exchange.HTTP_PATH, String.class); + if (path.startsWith("/customerservice/customers")) { + String httpMethod = inMessage.getHeader(Exchange.HTTP_METHOD, String.class); + if (HttpMethod.GET.equals(httpMethod)) { + processGetCustomer(exchange); + } else if (HttpMethod.POST.equals(httpMethod)) { + InputStream inBody = exchange.getIn().getBody(InputStream.class); + exchange.getOut().setBody(Response.ok(inBody).build()); + } + } + } + + } } http://git-wip-us.apache.org/repos/asf/camel/blob/f3a5e219/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CustomerServiceDefaultHandlerModel.xml ---------------------------------------------------------------------- diff --git a/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CustomerServiceDefaultHandlerModel.xml b/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CustomerServiceDefaultHandlerModel.xml new file mode 100644 index 0000000..21a923d --- /dev/null +++ b/components/camel-cxf/src/test/resources/org/apache/camel/component/cxf/jaxrs/CustomerServiceDefaultHandlerModel.xml @@ -0,0 +1,27 @@ +<!-- + 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. +--> +<model xmlns="http://cxf.apache.org/jaxrs"> + <resource path="customerservice"> + <operation name="getCustomer" verb="GET" path="/customers/{id}" produces="application/json"> + <param name="id" type="PATH"/> + </operation> + <operation name="echoCustomer" verb="POST" path="/customers" + produces="application/json" consumes="application/json"> + <param name="customer" type="REQUEST_BODY"/> + </operation> + </resource> +</model>
