CXF Component
The cxf: component provides integration with Apache CXF for connecting to JAX-WS services hosted in 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>
URI format
cxf://address?options
Where address represents the CXF endpoint's address
cxf:bean:cxfEndpoint
Where cxfEndpoint represents the spring bean's name which presents the CXF endpoint
For either style above, you can append options to the URI as follows:
cxf:bean:cxfEndpoint?wsdlURL=wsdl/hello_world.wsdl&dataFormat=PAYLOAD
Options
Name |
Description |
Example |
Required? |
default value |
---|---|---|---|---|
wsdlURL |
The location of the WSDL. |
file://local/wsdl/hello.wsdl or wsdl/hello.wsdl |
No |
WSDL is obtained from endpoint address by default |
serviceClass |
The name of the SEI(Service Endpoint Interface) implementation class. This class can have but does not require JSR181 annotations. |
org.apache.camel.Hello |
Yes for CXF provider, for CXF Consumer only if POJO dataFormat option is used |
|
serviceName |
The service name this service is implementing, it maps to the wsdl:service@name. |
{ http://org.apache.camel} |
Only if more than one serviceName in WSDL present |
|
portName |
The port name this service is implementing, it maps to the wsdl:port@name. |
{ http://org.apache.camel} |
Only if more than one portName under the serviceName is present |
|
dataFormat |
Which data type messages the CXF endpoint supports |
POJO, PAYLOAD, MESSAGE |
No |
POJO |
wrapped |
Which kind of operation that CXF endpoint producer will invoke |
true, false |
No |
false |
The serviceName and portName are QNames, so if you provide them be sure to prefix them with their {namespace} as shown in the examples above.
The descriptions of the dataformats
DataFormat |
Description |
---|---|
POJO |
POJOs (Plain old Java objects) are the Java parameters to the method being invoked on the target server. |
PAYLOAD |
PAYLOAD is the message payload (the contents of the soap:body) after message configuration in the CXF endpoint is applied. |
MESSAGE |
MESSAGE is the raw message that is received from the transport layer. |
Configure the CXF endpoints with spring
You can configure the CXF endpoint with the below spring configuration file, and you can also embed the endpoint into the camelContext tags.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://activemq.apache.org/camel/schema/cxfEndpoint" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://activemq.apache.org/camel/schema/cxfEndpoint http://activemq.apache.org/camel/schema/cxf/cxfEndpoint.xsd http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd "> <cxf:cxfEndpoint id="routerEndpoint" address="http://localhost:9003/CamelContext/RouterPort" serviceClass="org.apache.hello_world_soap_http.GreeterImpl"/> <cxf:cxfEndpoint id="serviceEndpoint" address="http://localhost:9000/SoapContext/SoapPort" wsdlURL="testutils/hello_world.wsdl" serviceClass="org.apache.hello_world_soap_http.Greeter" endpointName="s:SoapPort" serviceName="s:SOAPService" xmlns:s="http://apache.org/hello_world_soap_http" /> <camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring"> <route> <from uri="cxf:bean:routerEndpoint" /> <to uri="cxf:bean:serviceEndpoint" /> </route> </camelContext> </beans>
Be sure to include the JAX-WS schemaLocation
attribute specified on the root beans element. This allows CXF to validate the file and is required. Also note the namespace declarations at the end of the <cxf:cxfEndpoint/> tag--these are required because the combined "{namespace}localName" syntax is presently not supported for this tag's attribute values.
The jaxws:endpoint
element supports many additional attributes:
Name |
Value |
---|---|
PortName |
The endpoint name this service is implementing, it maps to the wsdl:port@name. In the format of "ns:PORT_NAME" where ns is a namespace prefix valid at this scope. |
serviceName |
The service name this service is implementing, it maps to the wsdl:service@name. In the format of "ns:SERVICE_NAME" where ns is a namespace prefix valid at this scope. |
wsdlURL |
The location of the WSDL. Can be on the classpath, file system, or be hosted remotely. |
bindingId |
The bindingId for the service model to use |
address |
The service publish address |
bus |
The bus name that will be used in the jaxws endpoint. |
serviceClass |
The class name of the SEI(Service Endpoint Interface) class which could have JSR181 annotation or not |
It also supports many child elements:
Name |
Value |
---|---|
cxf:inInterceptors |
The incoming interceptors for this endpoint. A list of <bean>s or <ref>s. |
cxf:inFaultInterceptors |
The incoming fault interceptors for this endpoint. A list of <bean>s or <ref>s. |
cxf:outInterceptors |
The outgoing interceptors for this endpoint. A list of <bean>s or <ref>s. |
cxf:outFaultInterceptors |
The outgoing fault interceptors for this endpoint. A list of <bean>s or <ref>s. |
cxf:properties |
A properties map which should be supplied to the JAX-WS endpoint. See below. |
cxf:dataBinding |
You can specify the which DataBinding will be use in the endpoint, This can be supplied using the Spring <bean class="MyDataBinding"/> syntax. |
cxf:binding |
You can specify the BindingFactory for this endpoint to use. This can be supplied using the Spring <bean class="MyBindingFactory"/> syntax. |
cxf:features |
The features that hold the interceptors for this endpoint. A list of <bean>s or <ref>s |
cxf:schemaLocations |
The schema locations for endpoint to use. A list of <schemaLocation>s |
cxf:serviceFactory |
The service factory for this endpoint to use. This can be supplied using the Spring <bean class="MyServiceFactory"/> syntax |
You can find more advanced examples which show how to provide interceptors and properties here: http://cwiki.apache.org/CXF20DOC/jax-ws-configuration.html
How to consume the message from the camel-cxf endpoint in POJO data format
The camel-cxf endpoint consumer POJO data format is based on the cxf invoker, so the message header has a property with the name of CxfConstants.OPERATION_NAME and the message body is a list of the SEI method parameters.
from(SIMPLE_ENDPOINT_URI).process(new Processor() { public void process(final Exchange exchange) { Message request = exchange.getIn(); // Get the parameter list List parameter = in.getBody(List.class); // Get the operation name String operation = (String)in.getHeader(CxfConstants.OPERATION_NAME); Object result = null; if (operation.equals(ECHO_OPERATION)) { result = operation + " " + (String)parameter.get(0); } // Put the result back exchange.getOut().setBody(result); } });
How to prepare the message for the camel-cxf endpoint in POJO data format
The camel-cxf endpoint producer is based on the cxf client API. First you need to specify the operation name in the message header , then add the method parameters into a list and set the message with this parameter list will be ok. The response message's body is an object array, you can get the result from that array.
CxfExchange exchange = (CxfExchange)template.send(getJaxwsEndpointUri(), new Processor() { public void process(final Exchange exchange) { final List<String> params = new ArrayList<String>(); params.add(TEST_MESSAGE); exchange.getIn().setBody(params); exchange.getIn().setHeader(CxfConstants.OPERATION_NAME, GREET_ME_OPERATION); } }); org.apache.camel.Message out = exchange.getOut(); Object[] output = (Object[])out.getBody(); LOG.info("Received output text: " + output[0]); assertEquals("reply body on Camel", "Hello " + TEST_MESSAGE, output[0]);
How to propagate camel-cxf endpoint's request and response context
cxf client API provides a way to invoke the operation with request and response context. If you are using camel-cxf endpoint producer to invoke the outside web service, you can set the request context and get response context with below codes.
CxfExchange exchange = (CxfExchange)template.send(getJaxwsEndpointUri(), new Processor() { public void process(final Exchange exchange) { final List<String> params = new ArrayList<String>(); params.add(TEST_MESSAGE); // Set the request context to the inMessage Map<String, Object> requestContext = new HashMap<String, Object>(); requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, JAXWS_SERVER_ADDRESS); exchange.getIn().setBody(params); exchange.getIn().setHeader(Client.REQUEST_CONTEXT , requestContext); exchange.getIn().setHeader(CxfConstants.OPERATION_NAME, GREET_ME_OPERATION); } }); org.apache.camel.Message out = exchange.getOut(); Object[] output = (Object[])out.getBody(); LOG.info("Received output text: " + output[0]); // Get the response context form outMessage Map<String, Object> responseContext = CastUtils.cast((Map)out.getHeader(Client.RESPONSE_CONTEXT)); assertNotNull(responseContext); assertEquals("Get the wrong wsdl opertion name", "{http://apache.org/hello_world_soap_http}greetMe", responseContext.get("javax.xml.ws.wsdl.operation").toString());