Chapter 79. CXF-RS Component Available as of Camel version 2.0 The cxfrs: component provides integration with Apache CXF for connecting to JAX-RS 1.1 and 2.0 services hosted in CXF. When using CXF as a consumer, the CXF Bean Component allows you to factor out how message payloads are received from their processing as a RESTful or SOAP web service. This has the potential of using a multitude of transports to consume web services. The bean component's configuration is also simpler and provides the fastest method to implement web services using Camel and CXF. Maven users will need to add the following dependency to their pom.xml for this component: <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-cxf</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency> 79.1. URI format cxfrs://address?options Where address represents the CXF endpoint's address cxfrs:bean:rsEndpoint Where rsEndpoint represents the spring bean's name which presents the CXFRS client or server For either style above, you can append options to the URI as follows: cxfrs:bean:cxfEndpoint?resourceClasses=org.apache.camel.rs.Example 79.2. Options The CXF-RS component supports 3 options, which are listed below. Name Description Default Type useGlobalSslContext Parameters (security) Enable usage of global SSL context parameters. false boolean headerFilterStrategy (filter) To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message. HeaderFilterStrategy resolveProperty Placeholders (advanced) Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders. true boolean The CXF-RS endpoint is configured using URI syntax: with the following path and query parameters: 79.2.1. Path Parameters (2 parameters): Name Description Default Type beanId To lookup an existing configured CxfRsEndpoint. Must used bean: as prefix. String address The service publish address. String 79.2.2. Query Parameters (30 parameters): Name Description Default Type features (common) Set the feature list to the CxfRs endpoint. List loggingFeatureEnabled (common) This option enables CXF Logging Feature which writes inbound and outbound REST messages to log. false boolean loggingSizeLimit (common) To limit the total size of number of bytes the logger will output when logging feature has been enabled. int modelRef (common) This option is used to specify the model file which is useful for the resource class without annotation. When using this option, then the service class can be omitted, to emulate document-only endpoints String providers (common) Set custom JAX-RS provider(s) list to the CxfRs endpoint. You can specify a string with a list of providers to lookup in the registy separated by comma. String resourceClasses (common) The resource classes which you want to export as REST service. Multiple classes can be separated by comma. List schemaLocations (common) Sets the locations of the schema(s) which can be used to validate the incoming XML or JAXB-driven JSON. List skipFaultLogging (common) This option controls whether the PhaseInterceptorChain skips logging the Fault that it catches. false boolean bindingStyle (consumer) Sets how requests and responses will be mapped to/from Camel. Two values are possible: SimpleConsumer: This binding style processes request parameters, multiparts, etc. and maps them to IN headers, IN attachments and to the message body. It aims to eliminate low-level processing of org.apache.cxf.message.MessageContentsList. It also also adds more flexibility and simplicity to the response mapping. Only available for consumers. Default: The default style. For consumers this passes on a MessageContentsList to the route, requiring low-level processing in the route. This is the traditional binding style, which simply dumps the org.apache.cxf.message.MessageContentsList coming in from the CXF stack onto the IN message body. The user is then responsible for processing it according to the contract defined by the JAX-RS method signature. Custom: allows you to specify a custom binding through the binding option. Default BindingStyle bridgeErrorHandler (consumer) Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. false boolean publishedEndpointUrl (consumer) This option can override the endpointUrl that published from the WADL which can be accessed with resource address url plus _wadl String exceptionHandler (consumer) To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. ExceptionHandler exchangePattern (consumer) Sets the exchange pattern when the consumer creates an exchange. ExchangePattern serviceBeans (consumer) The service beans which you want to export as REST service. Multiple beans can be separated by comma. List cookieHandler (producer) Configure a cookie handler to maintain a HTTP session CookieHandler hostnameVerifier (producer) The hostname verifier to be used. Use the # notation to reference a HostnameVerifier from the registry. HostnameVerifier sslContextParameters (producer) The Camel SSL setting reference. Use the # notation to reference the SSL Context. SSLContextParameters throwExceptionOnFailure (producer) This option tells the CxfRsProducer to inspect return codes and will generate an Exception if the return code is larger than 207. true boolean httpClientAPI (producer) If it is true, the CxfRsProducer will use the HttpClientAPI to invoke the service. If it is false, the CxfRsProducer will use the ProxyClientAPI to invoke the service true boolean ignoreDeleteMethodMessage Body (producer) This option is used to tell CxfRsProducer to ignore the message body of the DELETE method when using HTTP API. false boolean maxClientCacheSize (producer) This option allows you to configure the maximum size of the cache. The implementation caches CXF clients or ClientFactoryBean in CxfProvider and CxfRsProvider. 10 int binding (advanced) To use a custom CxfBinding to control the binding between Camel Message and CXF Message. CxfRsBinding bus (advanced) To use a custom configured CXF Bus. Bus continuationTimeout (advanced) This option is used to set the CXF continuation timeout which could be used in CxfConsumer by default when the CXF server is using Jetty or Servlet transport. 30000 long cxfRsEndpointConfigurer (advanced) This option could apply the implementation of org.apache.camel.component.cxf.jaxrs.CxfRsEndpointConfigurer which supports to configure the CXF endpoint in programmatic way. User can configure the CXF server and client by implementing configureServer/Client method of CxfEndpointConfigurer. CxfRsEndpoint Configurer defaultBus (advanced) Will set the default bus when CXF endpoint create a bus by itself false boolean headerFilterStrategy (advanced) To use a custom HeaderFilterStrategy to filter header to and from Camel message. HeaderFilterStrategy performInvocation (advanced) When the option is true, Camel will perform the invocation of the resource class instance and put the response object into the exchange for further processing. false boolean propagateContexts (advanced) When the option is true, JAXRS UriInfo, HttpHeaders, Request and SecurityContext contexts will be available to custom CXFRS processors as typed Camel exchange properties. These contexts can be used to analyze the current requests using JAX-RS API. false boolean synchronous (advanced) Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). false boolean 79.3. Spring Boot Auto-Configuration The component supports 4 options, which are listed below. Name Description Default Type camel.component.cxfrs.enabled Enable cxfrs component true Boolean camel.component.cxfrs.header-filter-strategy To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message. The option is a org.apache.camel.spi.HeaderFilterStrategy type. String camel.component.cxfrs.resolve-property-placeholders Whether the component should resolve property placeholders on itself when starting. Only properties which are of String type can use property placeholders. true Boolean camel.component.cxfrs.use-global-ssl-context-parameters Enable usage of global SSL context parameters. false Boolean You can also configure the CXF REST endpoint through the spring configuration. Since there are lots of difference between the CXF REST client and CXF REST Server, we provide different configuration for them. Please check out the schema file and CXF JAX-RS documentation for more information. 79.4. How to configure the REST endpoint in Camel In camel-cxf schema file , there are two elements for the REST endpoint definition. cxf:rsServer for REST consumer, cxf:rsClient for REST producer. You can find a Camel REST service route configuration example here. 79.5. How to override the CXF producer address from message header The camel-cxfrs producer supports to override the services address by setting the message with the key of "CamelDestinationOverrideUrl". // set up the service address from the message header to override the setting of CXF endpoint exchange.getIn().setHeader(Exchange.DESTINATION_OVERRIDE_URL, constant(getServiceAddress())); 79.6. Consuming a REST Request - Simple Binding Style Available as of Camel 2.11 The Default binding style is rather low-level, requiring the user to manually process the MessageContentsList object coming into the route. Thus, it tightly couples the route logic with the method signature and parameter indices of the JAX-RS operation. Somewhat inelegant, difficult and error-prone. In contrast, the SimpleConsumer binding style performs the following mappings, in order to make the request data more accessible to you within the Camel Message: JAX-RS Parameters (@HeaderParam, @QueryParam, etc.) are injected as IN message headers. The header name matches the value of the annotation. The request entity (POJO or other type) becomes the IN message body. If a single entity cannot be identified in the JAX-RS method signature, it falls back to the original MessageContentsList . Binary @Multipart body parts become IN message attachments, supporting DataHandler , InputStream , DataSource and CXF's Attachment class. Non-binary @Multipart body parts are mapped as IN message headers. The header name matches the Body Part name. Additionally, the following rules apply to the Response mapping : If the message body type is different to javax.ws.rs.core.Response (user-built response), a new Response is created and the message body is set as the entity (so long it's not null). The response status code is taken from the Exchange.HTTP_RESPONSE_CODE header, or defaults to 200 OK if not present. If the message body type is equal to javax.ws.rs.core.Response , it means that the user has built a custom response, and therefore it is respected and it becomes the final response. In all cases, Camel headers permitted by custom or default HeaderFilterStrategy are added to the HTTP response. 79.6.1. Enabling the Simple Binding Style This binding style can be activated by setting the bindingStyle parameter in the consumer endpoint to value SimpleConsumer : from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer") .to("log:TEST?showAll=true"); 79.6.2. Examples of request binding with different method signatures Below is a list of method signatures along with the expected result from the Simple binding. public Response doAction(BusinessObject request); Request payload is placed in IN message body, replacing the original MessageContentsList. public Response doAction(BusinessObject request, @HeaderParam("abcd") String abcd, @QueryParam("defg") String defg); Request payload placed in IN message body, replacing the original MessageContentsList. Both request params mapped as IN message headers with names abcd and defg. public Response doAction(@HeaderParam("abcd") String abcd, @QueryParam("defg") String defg); Both request params mapped as IN message headers with names abcd and defg. The original MessageContentsList is preserved, even though it only contains the 2 parameters. public Response doAction(@Multipart(value="body1") BusinessObject request, @Multipart(value="body2") BusinessObject request2); The first parameter is transferred as a header with name body1, and the second one is mapped as header body2. The original MessageContentsList is preserved as the IN message body. public Response doAction(InputStream abcd); The InputStream is unwrapped from the MessageContentsList and preserved as the IN message body. public Response doAction(DataHandler abcd); The DataHandler is unwrapped from the MessageContentsList and preserved as the IN message body. 79.6.3. More examples of the Simple Binding Style Given a JAX-RS resource class with this method: @POST @Path("/customers/{type}") public Response newCustomer(Customer customer, @PathParam("type") String type, @QueryParam("active") @DefaultValue("true") boolean active) { return null; } Serviced by the following route: from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer") .recipientList(simple("direct:USD{header.operationName}")); from("direct:newCustomer") .log("Request: type=USD{header.type}, active=USD{header.active}, customerData=USD{body}"); The following HTTP request with XML payload (given that the Customer DTO is JAXB-annotated): POST /customers/gold?active=true Payload: <Customer> <fullName>Raul Kripalani</fullName> <country>Spain</country> <project>Apache Camel</project> </Customer> Will print the message: Request: type=gold, active=true, customerData=<Customer.toString() representation> For more examples on how to process requests and write responses can be found here . 79.7. Consuming a REST Request - Default Binding Style The CXF JAXRS front end implements the JAX-RS (JSR-311) API , so we can export the resources classes as a REST service. And we leverage the CXF Invoker API to turn a REST request into a normal Java object method invocation. Unlike the Camel Restlet component, you don't need to specify the URI template within your endpoint, CXF takes care of the REST request URI to resource class method mapping according to the JSR-311 specification. All you need to do in Camel is delegate this method request to a right processor or endpoint. Here is an example of a CXFRS route... private static final String CXF_RS_ENDPOINT_URI = "cxfrs://http://localhost:" + CXT + "/rest?resourceClasses=org.apache.camel.component.cxf.jaxrs.testbean.CustomerServiceResource"; private static final String CXF_RS_ENDPOINT_URI2 = "cxfrs://http://localhost:" + CXT + "/rest2?resourceClasses=org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"; private static final String CXF_RS_ENDPOINT_URI3 = "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"; private static final String CXF_RS_ENDPOINT_URI5 = "cxfrs://http://localhost:" + CXT + "/rest5?" + "propagateContexts=true&" + "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(); final Processor testProcessor3 = new TestProcessor3(); 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); from(CXF_RS_ENDPOINT_URI5).process(testProcessor3); } }; } And the corresponding resource class used to configure the endpoint... INFO:*Note about resource classes* By default, JAX-RS resource classes are only*used to configure JAX-RS properties. Methods will *not be executed during routing of messages to the endpoint. Instead, it is the responsibility of the route to do all processing. Note that starting from Camel 2.15 it is also sufficient to provide an interface only as opposed to a no-op service implementation class for the default mode. Starting from Camel 2.15, if a performInvocation option is enabled, the service implementation will be invoked first, the response will be set on the Camel exchange and the route execution will continue as usual. This can be useful for integrating the existing JAX-RS implementations into Camel routes and for post-processing JAX-RS Responses in custom processors. @Path("/customerservice/") public interface CustomerServiceResource { @GET @Path("/customers/{id}/") Customer getCustomer(@PathParam("id") String id); @PUT @Path("/customers/") Response updateCustomer(Customer customer); @Path("/{id}") @PUT() @Consumes({ "application/xml", "text/plain", "application/json" }) @Produces({ "application/xml", "text/plain", "application/json" }) Object invoke(@PathParam("id") String id, String payload); } 79.8. How to invoke the REST service through camel-cxfrs producer The CXF JAXRS front end implements a proxy-based client API , with this API you can invoke the remote REST service through a proxy. The camel-cxfrs producer is based on this proxy API . You just need to specify the operation name in the message header and prepare the parameter in the message body, the camel-cxfrs producer will generate right REST request for you. Here is an example: Exchange exchange = template.send("direct://proxy", new Processor() { public void process(Exchange exchange) throws Exception { exchange.setPattern(ExchangePattern.InOut); Message inMessage = exchange.getIn(); // set the operation name inMessage.setHeader(CxfConstants.OPERATION_NAME, "getCustomer"); // using the proxy client API inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.FALSE); // set a customer header inMessage.setHeader("key", "value"); // setup the accept content type inMessage.setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json"); // set the parameters , if you just have one parameter // camel will put this object into an Object[] itself inMessage.setBody("123"); } }); // get the response message Customer response = (Customer) exchange.getOut().getBody(); assertNotNull("The response should not be null ", response); assertEquals("Get a wrong customer id ", 123, response.getId()); assertEquals("Get a wrong customer name", "John", response.getName()); assertEquals("Get a wrong response code", 200, exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE)); assertEquals("Get a wrong header value", "value", exchange.getOut().getHeader("key")); The CXF JAXRS front end also provides a http centric client API . You can also invoke this API from camel-cxfrs producer. You need to specify the HTTP_PATH and the HTTP_METHOD and let the producer use the http centric client API by using the URI option httpClientAPI or by setting the message header CxfConstants.CAMEL_CXF_RS_USING_HTTP_API . You can turn the response object to the type class specified with the message header CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS . Exchange exchange = template.send("direct://http", new Processor() { public void process(Exchange exchange) throws Exception { exchange.setPattern(ExchangePattern.InOut) Message inMessage = exchange.getIn(); // using the http central client API inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.TRUE); // set the Http method inMessage.setHeader(Exchange.HTTP_METHOD, "GET"); // set the relative path inMessage.setHeader(Exchange.HTTP_PATH, "/customerservice/customers/123"); // Specify the response class , cxfrs will use InputStream as the response object type inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, Customer.class); // set a customer header inMessage.setHeader("key", "value"); // since we use the Get method, so we don't need to set the message body inMessage.setBody(null); } }); From Camel 2.1, we also support to specify the query parameters from cxfrs URI for the CXFRS http centric client. Exchange exchange = template.send("cxfrs://http://localhost:9003/testQuery?httpClientAPI=true&q1=12&q2=13" To support the Dynamical routing, you can override the URI's query parameters by using the CxfConstants.CAMEL_CXF_RS_QUERY_MAP header to set the parameter map for it. Map<String, String> queryMap = new LinkedHashMap<>(); queryMap.put("q1", "new"); queryMap.put("q2", "world"); inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_QUERY_MAP, queryMap); 79.9. What's the Camel Transport for CXF In CXF you offer or consume a webservice by defining its address. The first part of the address specifies the protocol to use. For example address="http://localhost:9000" in an endpoint configuration means your service will be offered using the http protocol on port 9000 of localhost. When you integrate Camel Tranport into CXF you get a new transport "camel". So you can specify address="camel://direct:MyEndpointName" to bind the CXF service address to a camel direct endpoint. Technically speaking Camel transport for CXF is a component which implements the CXF transport API with the Camel core library. This allows you to easily use Camel's routing engine and integration patterns support together with your CXF services. 79.10. Integrate Camel into CXF transport layer To include the Camel Tranport into your CXF bus you use the CamelTransportFactory. You can do this in Java as well as in Spring. 79.10.1. Setting up the Camel Transport in Spring You can use the following snippet in your applicationcontext if you want to configure anything special. If you only want to activate the camel transport you do not have to do anything in your application context. As soon as you include the camel-cxf-transport jar (or camel-cxf.jar if your camel version is less than 2.7.x) in your app, cxf will scan the jar and load a CamelTransportFactory for you. <!-- you don't need to specify the CamelTransportFactory configuration as it is auto load by CXF bus --> <bean class="org.apache.camel.component.cxf.transport.CamelTransportFactory"> <property name="bus" ref="cxf" /> <property name="camelContext" ref="camelContext" /> <!-- checkException new added in Camel 2.1 and Camel 1.6.2 --> <!-- If checkException is true , CamelDestination will check the outMessage's exception and set it into camel exchange. You can also override this value in CamelDestination's configuration. The default value is false. This option should be set true when you want to leverage the camel's error handler to deal with fault message --> <property name="checkException" value="true" /> <property name="transportIds"> <list> <value>http://cxf.apache.org/transports/camel</value> </list> </property> </bean> 79.10.2. Integrating the Camel Transport in a programmatic way Camel transport provides a setContext method that you could use to set the Camel context into the transport factory. If you want this factory take effect, you need to register the factory into the CXF bus. Here is a full example for you. import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.transport.ConduitInitiatorManager; import org.apache.cxf.transport.DestinationFactoryManager; ... BusFactory bf = BusFactory.newInstance(); Bus bus = bf.createBus(); CamelTransportFactory camelTransportFactory = new CamelTransportFactory(); // set up the CamelContext which will be use by the CamelTransportFactory camelTransportFactory.setCamelContext(context) // if you are using CXF higher then 2.4.x the camelTransportFactory.setBus(bus); // if you are lower CXF, you need to register the ConduitInitiatorManager and DestinationFactoryManager like below // register the conduit initiator ConduitInitiatorManager cim = bus.getExtension(ConduitInitiatorManager.class); cim.registerConduitInitiator(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory); // register the destination factory DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class); dfm.registerDestinationFactory(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory); // set or bus as the default bus for cxf BusFactory.setDefaultBus(bus); 79.11. Configure the destination and conduit with Spring 79.11.1. Namespace The elements used to configure an Camel transport endpoint are defined in the namespace http://cxf.apache.org/transports/camel . It is commonly referred to using the prefix camel . In order to use the Camel transport configuration elements, you will need to add the lines shown below to the beans element of your endpoint's configuration file. In addition, you will need to add the configuration elements' namespace to the xsi:schemaLocation attribute. Adding the Configuration Namespace <beans ... xmlns:camel="http://cxf.apache.org/transports/camel ... xsi:schemaLocation="... http://cxf.apache.org/transports/camel http://cxf.apache.org/transports/camel.xsd ...> 79.11.2. The destination element You configure an Camel transport server endpoint using the camel:destination element and its children. The camel:destination element takes a single attribute, name , that specifies the WSDL port element that corresponds to the endpoint. The value for the name attribute takes the form portQName `.camel-destination`. The example below shows the camel:destination element that would be used to add configuration for an endpoint that was specified by the WSDL fragment <port binding="widgetSOAPBinding" name="widgetSOAPPort"> if the endpoint's target namespace was http://widgets.widgetvendor.net . camel:destination Element ... <camel:destination name="{http://widgets/widgetvendor.net}widgetSOAPPort.http-destination> <camelContext id="context" xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="direct:EndpointC" /> <to uri="direct:EndpointD" /> </route> </camelContext> </camel:destination> <!-- new added feature since Camel 2.11.x <camel:destination name="{http://widgets/widgetvendor.net}widgetSOAPPort.camel-destination" camelContextId="context" /> ... The camel:destination element for Spring has a number of child elements that specify configuration information. They are described below. Element Description camel-spring:camelContext You can specify the camel context in the camel destination camel:camelContextRef The camel context id which you want inject into the camel destination 79.11.3. The conduit element You configure a Camel transport client using the camel:conduit element and its children. The camel:conduit element takes a single attribute, name , that specifies the WSDL port element that corresponds to the endpoint. The value for the name attribute takes the form portQName `.camel-conduit`. For example, the code below shows the camel:conduit element that would be used to add configuration for an endpoint that was specified by the WSDL fragment <port binding="widgetSOAPBinding" name="widgetSOAPPort"> if the endpoint's target namespace was http://widgets.widgetvendor.net . http-conf:conduit Element ... <camelContext id="conduit_context" xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="direct:EndpointA" /> <to uri="direct:EndpointB" /> </route> </camelContext> <camel:conduit name="{http://widgets/widgetvendor.net}widgetSOAPPort.camel-conduit"> <camel:camelContextRef>conduit_context</camel:camelContextRef> </camel:conduit> <!-- new added feature since Camel 2.11.x <camel:conduit name="{http://widgets/widgetvendor.net}widgetSOAPPort.camel-conduit" camelContextId="conduit_context" /> <camel:conduit name="*.camel-conduit"> <!-- you can also using the wild card to specify the camel-conduit that you want to configure --> ... </camel:conduit> ... The camel:conduit element has a number of child elements that specify configuration information. They are described below. Element Description camel-spring:camelContext You can specify the camel context in the camel conduit camel:camelContextRef The camel context id which you want inject into the camel conduit 79.12. Configure the destination and conduit with Blueprint From Camel 2.11.x , Camel Transport supports to be configured with Blueprint. If you are using blueprint, you should use the namespace http://cxf.apache.org/transports/camel/blueprint and import the schema like the blow. Adding the Configuration Namespace for blueprint <beans ... xmlns:camel="http://cxf.apache.org/transports/camel/blueprint" ... xsi:schemaLocation="... http://cxf.apache.org/transports/camel/blueprint http://cxf.apache.org/schmemas/blueprint/camel.xsd ...> In blueprint camel:conduit camel:destination only has one camelContextId attribute, they doesn't support to specify the camel context in the camel destination. <camel:conduit id="*.camel-conduit" camelContextId="camel1" /> <camel:destination id="*.camel-destination" camelContextId="camel1" /> 79.13. Example Using Camel as a load balancer for CXF This example shows how to use the camel load balancing feature in CXF. You need to load the configuration file in CXF and publish the endpoints on the address "camel://direct:EndpointA" and "camel://direct:EndpointB" 79.14. Complete Howto and Example for attaching Camel to CXF Better JMS Transport for CXF Webservice using Apache Camel

Commands:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-cxf</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency>
cxfrs://address?options
cxfrs:bean:rsEndpoint
cxfrs:bean:cxfEndpoint?resourceClasses=org.apache.camel.rs.Example
cxfrs:beanId:address
// set up the service address from the message header to override the setting of CXF endpoint exchange.getIn().setHeader(Exchange.DESTINATION_OVERRIDE_URL, constant(getServiceAddress()));
from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer") .to("log:TEST?showAll=true");
@POST @Path("/customers/{type}") public Response newCustomer(Customer customer, @PathParam("type") String type, @QueryParam("active") @DefaultValue("true") boolean active) { return null; }
from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer") .recipientList(simple("direct:USD{header.operationName}")); from("direct:newCustomer") .log("Request: type=USD{header.type}, active=USD{header.active}, customerData=USD{body}");
POST /customers/gold?active=true Payload: <Customer> <fullName>Raul Kripalani</fullName> <country>Spain</country> <project>Apache Camel</project> </Customer>
Request: type=gold, active=true, customerData=<Customer.toString() representation>
private static final String CXF_RS_ENDPOINT_URI = "cxfrs://http://localhost:" + CXT + "/rest?resourceClasses=org.apache.camel.component.cxf.jaxrs.testbean.CustomerServiceResource"; private static final String CXF_RS_ENDPOINT_URI2 = "cxfrs://http://localhost:" + CXT + "/rest2?resourceClasses=org.apache.camel.component.cxf.jaxrs.testbean.CustomerService"; private static final String CXF_RS_ENDPOINT_URI3 = "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"; private static final String CXF_RS_ENDPOINT_URI5 = "cxfrs://http://localhost:" + CXT + "/rest5?" + "propagateContexts=true&" + "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(); final Processor testProcessor3 = new TestProcessor3(); 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); from(CXF_RS_ENDPOINT_URI5).process(testProcessor3); } }; }
@Path("/customerservice/") public interface CustomerServiceResource { @GET @Path("/customers/{id}/") Customer getCustomer(@PathParam("id") String id); @PUT @Path("/customers/") Response updateCustomer(Customer customer); @Path("/{id}") @PUT() @Consumes({ "application/xml", "text/plain", "application/json" }) @Produces({ "application/xml", "text/plain", "application/json" }) Object invoke(@PathParam("id") String id, String payload); }
Exchange exchange = template.send("direct://proxy", new Processor() { public void process(Exchange exchange) throws Exception { exchange.setPattern(ExchangePattern.InOut); Message inMessage = exchange.getIn(); // set the operation name inMessage.setHeader(CxfConstants.OPERATION_NAME, "getCustomer"); // using the proxy client API inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.FALSE); // set a customer header inMessage.setHeader("key", "value"); // setup the accept content type inMessage.setHeader(Exchange.ACCEPT_CONTENT_TYPE, "application/json"); // set the parameters , if you just have one parameter // camel will put this object into an Object[] itself inMessage.setBody("123"); } }); // get the response message Customer response = (Customer) exchange.getOut().getBody(); assertNotNull("The response should not be null ", response); assertEquals("Get a wrong customer id ", 123, response.getId()); assertEquals("Get a wrong customer name", "John", response.getName()); assertEquals("Get a wrong response code", 200, exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE)); assertEquals("Get a wrong header value", "value", exchange.getOut().getHeader("key"));
Exchange exchange = template.send("direct://http", new Processor() { public void process(Exchange exchange) throws Exception { exchange.setPattern(ExchangePattern.InOut) Message inMessage = exchange.getIn(); // using the http central client API inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_USING_HTTP_API, Boolean.TRUE); // set the Http method inMessage.setHeader(Exchange.HTTP_METHOD, "GET"); // set the relative path inMessage.setHeader(Exchange.HTTP_PATH, "/customerservice/customers/123"); // Specify the response class , cxfrs will use InputStream as the response object type inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS, Customer.class); // set a customer header inMessage.setHeader("key", "value"); // since we use the Get method, so we don't need to set the message body inMessage.setBody(null); } });
Exchange exchange = template.send("cxfrs://http://localhost:9003/testQuery?httpClientAPI=true&q1=12&q2=13"
Map<String, String> queryMap = new LinkedHashMap<>(); queryMap.put("q1", "new"); queryMap.put("q2", "world"); inMessage.setHeader(CxfConstants.CAMEL_CXF_RS_QUERY_MAP, queryMap);
<!-- you don't need to specify the CamelTransportFactory configuration as it is auto load by CXF bus --> <bean class="org.apache.camel.component.cxf.transport.CamelTransportFactory"> <property name="bus" ref="cxf" /> <property name="camelContext" ref="camelContext" /> <!-- checkException new added in Camel 2.1 and Camel 1.6.2 --> <!-- If checkException is true , CamelDestination will check the outMessage's exception and set it into camel exchange. You can also override this value in CamelDestination's configuration. The default value is false. This option should be set true when you want to leverage the camel's error handler to deal with fault message --> <property name="checkException" value="true" /> <property name="transportIds"> <list> <value>http://cxf.apache.org/transports/camel</value> </list> </property> </bean>
import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.transport.ConduitInitiatorManager; import org.apache.cxf.transport.DestinationFactoryManager; BusFactory bf = BusFactory.newInstance(); Bus bus = bf.createBus(); CamelTransportFactory camelTransportFactory = new CamelTransportFactory(); // set up the CamelContext which will be use by the CamelTransportFactory camelTransportFactory.setCamelContext(context) // if you are using CXF higher then 2.4.x the camelTransportFactory.setBus(bus); // if you are lower CXF, you need to register the ConduitInitiatorManager and DestinationFactoryManager like below // register the conduit initiator ConduitInitiatorManager cim = bus.getExtension(ConduitInitiatorManager.class); cim.registerConduitInitiator(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory); // register the destination factory DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class); dfm.registerDestinationFactory(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory); // set or bus as the default bus for cxf BusFactory.setDefaultBus(bus);
<beans xmlns:camel="http://cxf.apache.org/transports/camel xsi:schemaLocation=" http://cxf.apache.org/transports/camel http://cxf.apache.org/transports/camel.xsd ...>
<camel:destination name="{http://widgets/widgetvendor.net}widgetSOAPPort.http-destination> <camelContext id="context" xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="direct:EndpointC" /> <to uri="direct:EndpointD" /> </route> </camelContext> </camel:destination> <!-- new added feature since Camel 2.11.x <camel:destination name="{http://widgets/widgetvendor.net}widgetSOAPPort.camel-destination" camelContextId="context" />
<camelContext id="conduit_context" xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="direct:EndpointA" /> <to uri="direct:EndpointB" /> </route> </camelContext> <camel:conduit name="{http://widgets/widgetvendor.net}widgetSOAPPort.camel-conduit"> <camel:camelContextRef>conduit_context</camel:camelContextRef> </camel:conduit> <!-- new added feature since Camel 2.11.x <camel:conduit name="{http://widgets/widgetvendor.net}widgetSOAPPort.camel-conduit" camelContextId="conduit_context" /> <camel:conduit name="*.camel-conduit"> <!-- you can also using the wild card to specify the camel-conduit that you want to configure --> </camel:conduit>
<beans xmlns:camel="http://cxf.apache.org/transports/camel/blueprint" xsi:schemaLocation=" http://cxf.apache.org/transports/camel/blueprint http://cxf.apache.org/schmemas/blueprint/camel.xsd ...>
<camel:conduit id="*.camel-conduit" camelContextId="camel1" /> <camel:destination id="*.camel-destination" camelContextId="camel1" />