What's the Camel Transport for CXF
In CXF you offer or consume a webservice by defining it´s 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 use camel´s routing engine and integration patterns support smoothly together with your CXF services.
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.
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 jar in your app cxf will scan the jar and load a CamelTransportFactory for you.
<bean class="org.apache.camel.component.cxf.transport.CamelTransportFactory">
<property name="bus" ref="cxf" />
<property name="camelContext" ref="camelContext" />
<!-- 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>
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();
camelTransportFactory.setCamelContext(context)
ConduitInitiatorManager cim = bus.getExtension(ConduitInitiatorManager.class);
cim.registerConduitInitiator(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory);
DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
dfm.registerDestinationFactory(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory);
BusFactory.setDefaultBus(bus);
Configure the destination and conduit
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.
<beans ...
xmlns:camel="http: ...
xsi:schemaLocation="...
http: http: ...>
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, the 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 name="{http: <camelContext id="context" xmlns="http:>
<route>
<from uri="direct:EndpointC" />
<to uri="direct:EndpointD" />
</route>
</camelContext>
</camel:destination>
...
The camel:destination 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 destination |
camel:camelContextRef |
The camel context id which you want inject into the camel destination |
The conduit element
You configure an 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.
...
<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>
<camel:conduit name="*.camel-conduit">
...
</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 |
Example Using Camel as a load balancer for CXF
This example show how to use the camel load balance feature in CXF, and you need load the configuration file in CXF and publish the endpoints on the address "camel://direct:EndpointA" and "camel://direct:EndpointB"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://cxf.apache.org/transports/camel"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/transports/camel http://cxf.apache.org/transports/camel.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/cxfEndpoint.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
">
<!-- Enable bridge between Camel Property Placeholder and Spring Property placeholder so we can use system properties
to dynamically set the port number for unit testing the example. -->
<bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"/>
<bean id = "roundRobinRef" class="org.apache.camel.processor.loadbalancer.RoundRobinLoadBalancer" />
<camelContext id="dest_context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="jetty:http://localhost:{{port}}/GreeterContext/GreeterPort"/>
<loadBalance ref="roundRobinRef">
<to uri="direct:EndpointA"/>
<to uri="direct:EndpointB"/>
</loadBalance>
</route>
</camelContext>
<camel:destination name="{http://apache.org/hello_world_soap_http}CamelPort.camel-destination">
<camel:camelContextRef>dest_context</camel:camelContextRef>
</camel:destination>
</beans>
Complete Howto and Example for attaching Camel to CXF
Better JMS Transport for CXF Webservice using Apache Camel