© 2016 The original authors.
Provides Apache Camel integration with the WildFly Application Server.
The WildFly-Camel subsystem allows you to add Camel Routes as part of the WildFly configuration. Routes can be deployed as part of JavaEE applications. JavaEE components can access the Camel Core API and various Camel Component APIs.
Your Enterprise Integration Solution can be architected as a combination of JavaEE and Camel functionality.
1. Getting Started
This chapter takes you through the first steps of getting WildFly-Camel and provides the initial pointers to get up and running.
Download the Distribution
WildFly Camel is distributed as
-
WildFly Patch - wildfly-camel-patch
-
Docker Image - wildflyext/wildfly-camel
Installing the Camel Subsystem
Simply unpack the provided patch into the a supported WildFly installation. For possible WildFly target versions, see the compatibility page.
Standalone Server
In your WildFly home directory run …
$ bin/standalone.sh -c standalone-camel.xml
...
10:50:02,833 INFO [org.jboss.as.server] (ServerService Thread Pool -- 31) JBAS018559: Deployed "wildfly-camel.war" (runtime-name : "wildfly-camel.war")
10:50:02,834 INFO [org.jboss.as.server] (ServerService Thread Pool -- 31) JBAS018559: Deployed "hawtio.war" (runtime-name : "hawtio.war")
10:50:02,848 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://<IP_ADDRESS>:9990/management
10:50:02,849 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://<IP_ADDRESS>:9990
10:50:02,849 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.1.0.Final "Kenny" started in 10804ms
Domain Mode
Similarly, for the WildFly Domain Mode run …
$ bin/domain.sh -c domain-camel.xml
Enable Camel Subsystem
The patch does not modify existing configuration files. Instead it comes with a number of additional configurations files that end in -camel.xml
.
If you should want to add the Camel subsystem to existing configurations you can run the following command.
$ bin/fuseconfig.sh --configs=camel --enable
Processing config for: camel
Writing 'layers=fuse' to: .../wildfly-9.0.0.CR1/modules/layers.conf
Enable camel configuration in: .../wildfly-9.0.0.CR1/standalone/configuration/standalone.xml
Enable camel configuration in: .../wildfly-9.0.0.CR1/standalone/configuration/standalone-full.xml
Enable camel configuration in: .../wildfly-9.0.0.CR1/standalone/configuration/standalone-full-ha.xml
Enable camel configuration in: .../wildfly-9.0.0.CR1/standalone/configuration/standalone-ha.xml
Enable camel configuration in: .../wildfly-9.0.0.CR1/domain/configuration/domain.xml
There are currently three triggers that can be used to enable Camel for a deployment
-
a deployment that contains a *-camel-context.xml descriptor
-
a deployment that contains a type annotated with @CamelAware
-
a deployment that contains a type annotated with @ContextName
Docker Image
The easiest and most portable way to run WildFly-Camel is to use the wildflyext/wildfly-camel distribution.
$ docker run --rm -ti -p 8080:8080 -p 9990:9990 -e WILDFLY_MANAGEMENT_USER=admin -e WILDFLY_MANAGEMENT_PASSWORD=admin wildflyext/wildfly-camel
Maven Archetypes
To get started with writing Camel JEE applications, there are two Maven archetypes that can generate either a Camel Spring XML or Camel CDI application.
To generate a Camel CDI application, run the following from the command line.

 mvn archetype:generate -DarchetypeGroupId=org.wildfly.camel.archetypes \ -DarchetypeArtifactId=wildfly-camel-archetype-cdi \ -DarchetypeVersion=4.4.0 \ -DgroupId=com.mycompany \ -DartifactId=my-camel-cdi-application

To generate a Camel Spring XML application, run the following from the command line.

 mvn archetype:generate -DarchetypeGroupId=org.wildfly.camel.archetypes \ -DarchetypeArtifactId=wildfly-camel-archetype-spring \ -DarchetypeVersion=4.4.0 \ -DgroupId=com.mycompany \ -DartifactId=my-camel-spring-application

Instructions on how to build, test and run the project can be found within the generated README files.
2. Compatibility
The WildFly compatibility matrix
10.1.0.Final |
4.3 |
10.0.0.Final |
4.0, 4.1, 4.2 |
9.0.2.Final |
3.2, 3.3 |
9.0.1.Final |
3.1 |
9.0.0.CR1 |
3.0 |
8.2.0.Final |
2.1, 2.2, 2.3 |
8.1.0.Final |
2.0 |
3. Features
This chapter provides more detailed information about WildFly-Camel features.
Camel Context Definitions
Camel Contexts can be configured in standalone-camel.xml and domain.xml as part of the subsystem definition like this
<subsystem xmlns="urn:jboss:domain:camel:1.0">
<camelContext id="system-context-1">
<![CDATA[
<route>
<from uri="direct:start"/>
<transform>
<simple>Hello #{body}</simple>
</transform>
</route>
]]>
</camelContext>
</subsystem>
Camel Context Deployments
Camel contexts can be deployed to WildFly with a -camel-context.xml suffix.
-
As a standalone XML file
-
As part of another supported deployment
A deployment may contain multiple -camel-context.xml files.
A deployed Camel context is CDI injectable like this
@Resource(name = "java:jboss/camel/context/mycontext")
CamelContext camelContext;
Management Console
By default, access to management consoles is secured. We therefore need to setup a Management User first.
$ bin/add-user.sh
What type of user do you wish to add?
a) Management User (mgmt-users.properties)
b) Application User (application-users.properties)
The Hawt.io console should show the camel context from subsystem configuration.
Arquillian Test Support
The WildFly Camel test suite uses the WildFly Arquillian managed container. This can connect to an already running WildFly instance or alternatively start up a standalone server instance when needed.
A number of test enrichers have been implemented that allow you to have these WildFly Camel specific types injected into your Arquillian test cases.
@ArquillianResource
CamelContextFactory contextFactory;
@ArquillianResource
CamelContextRegistry contextRegistry;
4. Configuration
This chapter details information about the Camel subsytem and deployment configuration.
Camel Subsystem Configuration
The subsystem configuration may contain static system routes
<subsystem xmlns="urn:jboss:domain:camel:1.0">
<camelContext id="system-context-1">
<![CDATA[
<route>
<from uri="direct:start"/>
<transform>
<simple>Hello #{body}</simple>
</transform>
</route>
]]>
</camelContext>
</subsystem>
These routes are started automatically.
Camel Deployment Configuration
If you want to fine tune the default configuration of your Camel deployment, you can edit either the WEB-INF/jboss-all.xml
or META-INF/jboss-all.xml
configuration file in your deployment.
Use a <jboss-camel>
XML element within the jboss-all.xml
file to control the camel configuration.
Disabling the Camel Subsystem
If you don’t want the camel subsystem to be added into
your deployment, set the enabled="false"
attribute on the jboss-camel
XML element.
Example jboss-all.xml
file:
<jboss umlns="urn:jboss:1.0">
<jboss-camel xmlns="urn:jboss:jboss-camel:1.0" enabled="false"/>
</jboss>
Selecting Components
If you add nested <component>
or <component-module>
XML elements, then instead of adding the default list of Camel components to your deployment, only the specified components will be added to your deployment.
Example jboss-all.xml
file:
<jboss umlns="urn:jboss:1.0">
<jboss-camel xmlns="urn:jboss:jboss-camel:1.0">
<component name="camel-ftp"/>
<component-module name="org.apache.camel.component.rss"/>
</jboss-camel>
</jboss>
5. JavaEE Integration
This chapter details information about integration points with JavaEE.
5.1. CDI
CDI integration is provided by camel-cdi.
A Context with an associated route can be provided like this
@Startup
@ApplicationScoped
@ContextName("cdi-context")
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:start").transform(body().prepend("Hi"));
}
}
and consumed like this
@Inject
@ContextName("cdi-context")
private CamelContext camelctx;
5.2. EJB
Management support is provided through the camel-ejb component which integrates with the EJB3 subsystem.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start").to("ejb:java:module/HelloBean");
}
});
5.3. JAXB
JAXB support is provided through the Camel JAXB data format.
Camel supports unmarshalling XML data to JAXB annotated classes and marshalling from classes to XML. What follows demonstrates a simple Camel route for marshalling and unmarshalling with the Camel JAXB data format class.
5.3.1. JAXB Annotated class
@XmlRootElement(name = "customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer implements Serializable {
private String firstName;
private String lastName;
public Customer() {
}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
5.3.2. JAXB Class XML representation
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer xmlns="http://org/wildfly/test/jaxb/model/Customer">
<firstName>John</firstName>
<lastName>Doe</lastName>
</customer>
5.3.3. Camel JAXB Unmarshalling
WildFlyCamelContext camelctx = contextFactory.createCamelContext(getClass().getClassLoader());
final JaxbDataFormat jaxb = new JaxbDataFormat();
jaxb.setContextPath("org.wildfly.camel.test.jaxb.model");
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.unmarshal(jaxb);
}
});
camelctx.start();
ProducerTemplate producer = camelctx.createProducerTemplate();
// Send an XML representation of the customer to the direct:start endpoint
Customer customer = producer.requestBody("direct:start", readCustomerXml(), Customer.class);
Assert.assertEquals("John", customer.getFirstName());
Assert.assertEquals("Doe", customer.getLastName());
5.3.4. Camel JAXB Marshalling
WildFlyCamelContext camelctx = contextFactory.createCamelContext();
final JaxbDataFormat jaxb = new JaxbDataFormat();
jaxb.setContextPath("org.wildfly.camel.test.jaxb.model");
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.marshal(jaxb);
}
});
camelctx.start();
ProducerTemplate producer = camelctx.createProducerTemplate();
Customer customer = new Customer("John", "Doe");
String customerXML = producer.requestBody("direct:start", customer, String.class);
Assert.assertEquals(readCustomerXml(), customerXML);
5.4. JAX-RS
JAX-RS support is provided by Camel CXF-RS.
5.4.1. CXF-RS Producer
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<cxf:rsClient id="cxfProducer"
address="http://localhost:8080/rest"
serviceClass="org.wildfly.camel.examples.cxf.jaxrs.GreetingService" />
<camelContext id="cxfrs-camel-context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start" />
<setHeader headerName="operationName">
<simple>greet</simple>
</setHeader>
<setHeader headerName="CamelCxfRsUsingHttpAPI">
<constant>false</constant>
</setHeader>
<to uri="cxfrs:bean:cxfProducer" />
</route>
</camelContext>
</beans>
5.4.2. CXF-RS Consumer
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<cxf:rsServer id="cxfConsumer"
address="http://localhost:8080/rest"
serviceClass="org.wildfly.camel.examples.cxf.jaxrs.GreetingService" />
<camelContext id="cxfrs-camel-context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="cxfrs:bean:cxfConsumer" />
<setBody>
<constant>Hello world</constant>
</setBody>
</route>
</camelContext>
</beans>
5.4.3. JAX-RS Consumer with the Camel REST DSL
The Camel REST DSL gives the capability to write Camel routes that act as JAX-RS consumers. The following RouteBuilder class demonstrates this.
@Startup
@ApplicationScoped
@ContextName("rest-camel-context")
public class RestConsumerRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
// Use the camel-servlet component to provide REST integration
restConfiguration().component("servlet")
.contextPath("/rest").port(8080).bindingMode(RestBindingMode.json);
rest("/customer")
// GET /rest/customer
.get()
.produces(MediaType.APPLICATION_JSON)
.to("direct:getCustomers")
// GET /rest/customer/1
.get("/{id}")
.produces(MediaType.APPLICATION_JSON)
.to("direct:getCustomer")
// POST /rest/customer
.post()
.type(Customer.class)
.to("direct:createCustomer");
// PUT /rest/customer
.put()
.type(Customer.class)
.to("direct:updateCustomer");
// DELETE /rest/customer/1
.delete("/{id}")
.to("direct:deleteCustomer");
}
}
Note that the REST DSL configuration starts with restConfiguration().component("servlet")
. The WildFly Camel Subsystem only supports camel-servlet and camel-undertow for use with the REST DSL. Attempts to configure other components will not work.
By setting the binding mode, Camel can marshal and unmarshal JSON data either by specifying a 'produces()' or 'type()' configuration step.
5.4.4. JAX-RS Consumer with CamelProxy
JAX-RS consumer endpoints can be configured using the CamelProxy. The proxy enables you to proxy a producer sending to an Endpoint by a regular interface. When clients invoke methods on this interface, the proxy performs a request / reply to a specified endpoint.
Below is an example JAX-RS service interface and implementation.
// Service interface
@Path("/customer")
public interface CustomerService {
@GET
@Produces(MediaType.APPLICATION_JSON)
Response getCustomers();
@PUT
Response updateCustomer();
}
// Service implementation
public class CustomerServiceImpl implements CustomerService {
@Inject
@ContextName("rest-camel-context")
private CamelContext context;
@Produce(uri="direct:rest")
private CustomerService customerServiceProxy;
@Override
public Response getCustomers() {
return customerServiceProxy.getCustomers();
}
@Override
public Response updateCustomer(Customer customer) {
return customerServiceProxy.updateCustomer(customer);
}
}
Notice in the above code example that CustomerServiceImpl
delegates all method calls to a customerServiceProxy object which has been annotated
with @Produce
. This annotation is important as it configures a proxy for the direct:rest
endpoint against the CustomerService
interface. Whenever any of the REST service methods are invoked by clients, the direct:rest
camel route is triggered.
The RouteBuilder class implements logic for each REST service method invocation.
from("direct:rest")
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
BeanInvocation beanInvocation = exchange.getIn().getBody(BeanInvocation.class);
String methodName = beanInvocation.getMethod().getName();
if (methodName.equals("getCustomers")) {
List<Customer> customers = customerService.findAllCustomers();
exchange.getOut().setBody(Response.ok(customers).build());
} else if(methodName.equals("updateCustomer")) {
Customer updatedCustomer = (Customer) beanInvocation.getArgs()[0];
customerService.updateCustomer(updatedCustomer);
exchange.getOut().setBody(Response.ok().build());
}
}
});
In the above RouteBuilder a Processor
handles REST service method invocations that have been proxied through the direct:rest
endpoint.
The exchange message body will be an instance of BeanInvocation
. This can be used to determine which web service method was invoked and
what arguments were passed to it. In this example some simple logic is used to return results to the client based on the name of the method that
was called.
5.4.5. Security
Refer to the JAX-RS security section.
5.4.6. Code examples on GitHub
An example Camel CXF application is available on GitHub.
5.5. JAX-WS
WebService support is provided through the camel-cxf component which integrates with the WildFly WebServices subsystem that also uses Apache CXF.
5.5.1. JAX-WS CXF Producer
The following code example uses CXF to consume a web service which has been deployed by the WildFly web services subsystem.
JAX-WS web service
The following simple web service has a simple 'greet' method which will concatenate two string arguments together and return them.
When the WildFly web service subsystem detects classes containing JAX-WS annotations, it bootstraps a CXF endpoint. In this example the service endpoint will be located at http://hostname:port/context-root/greeting.
// Service interface
@WebService(name = "greeting")
public interface GreetingService {
@WebMethod(operationName = "greet", action = "urn:greet")
String greet(@WebParam(name = "message") String message, @WebParam(name = "name") String name);
}
// Service implementation
public class GreetingServiceImpl implements GreetingService{
public String greet(String message, String name) {
return message + " " + name ;
}
}
Camel route configuration
This RouteBuilder configures a CXF producer endpoint which will consume the 'greeting' web service defined above. CDI in conjunction with the camel-cdi component is used to bootstrap the RouteBuilder and CamelContext.
@Startup
@ApplicationScoped
@ContextName("cxf-camel-context")
public class CxfRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:start")
.to("cxf://http://localhost:8080/example-camel-cxf/greeting?serviceClass=" + GreetingService.class.getName());
}
}
The greeting web service 'greet' requires two parameters. These can be supplied to the above route by way of a ProducerTemplate
.
The web service method argument values are configured by constructing an object array which is passed as the exchange body.
String message = "Hello"
String name = "Kermit"
ProducerTemplate producer = camelContext.createProducerTemplate();
Object[] serviceParams = new Object[] {message, name};
String result = producer.requestBody("direct:start", serviceParams, String.class);
5.5.2. Camel CXF JAX-WS Consumer
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<cxf:cxfEndpoint id="cxfConsumer"
address="http://localhost:8080/webservices/greeting"
serviceClass="org.wildfly.camel.examples.cxf.jaxws.GreetingService" />
<camelContext id="cxfws-camel-context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="cxf:bean:cxfConsumer" />
<to uri="log:ws" />
</route>
</camelContext>
</beans>
5.5.3. JAX-WS Consumer with CamelProxy
JAX-WS consumer endpoints can be configured using the CamelProxy. The proxy enables you to proxy a producer sending to an Endpoint by a regular interface. When clients invoke methods on this interface, the proxy performs a request / reply to a specified endpoint.
Below is an example JAX-WS web service interface and implementation.
// Service interface
@WebService(name = "greeting")
public interface GreetingService {
@WebMethod(operationName = "greet", action = "urn:greet")
String greet(@WebParam(name = "name") String name);
@WebMethod(operationName = "greetWithMessage", action = "urn:greetWithMessage")
String greetWithMessage(@WebParam(name = "message") String message, @WebParam(name = "name") String name);
}
// Service implementation
@WebService(serviceName="greeting", endpointInterface = "org.wildfly.camel.examples.jaxws.GreetingService")
public class GreetingServiceImpl {
@Produce(uri="direct:start")
GreetingService greetingService;
@WebMethod(operationName = "greet")
public String greet(@WebParam(name = "name") String name) {
return greetingService.greet(name);
}
@WebMethod(operationName = "greetWithMessage")
public String greetWithMessage(@WebParam(name = "message") String message, @WebParam(name = "name") String name) {
return greetingService.greetWithMessage(message, name);
}
}
Notice in the above code example that GreetingServiceImpl
delegates all method calls to a greetingService object which has been annotated
with @Produce
. This annotation is important as it configures a proxy for the direct:start
endpoint against the GreetingService
interface. Whenever any of the web service methods are invoked by clients, the direct:start
camel route is triggered.
The RouteBuilder class implements logic for each web service method invocation.
@Startup
@ApplicationScoped
@ContextName("jaxws-camel-context")
public class JaxwsRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:start")
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
BeanInvocation beanInvocation = exchange.getIn().getBody(BeanInvocation.class);
String methodName = beanInvocation.getMethod().getName();
if(methodName.equals("greet")) {
String name = exchange.getIn().getBody(String.class);
exchange.getOut().setBody("Hello " + name);
} else if(methodName.equals("greetWithMessage")) {
String message = (String) beanInvocation.getArgs()[0];
String name = (String) beanInvocation.getArgs()[1];
exchange.getOut().setBody(message + " " + name);
} else {
throw new IllegalStateException("Unknown method invocation " + methodName);
}
}
});
}
In the above RouteBuilder a Processor
handles web service method invocations that have been proxied through the direct:start
endpoint.
The exchange message body will be an instance of BeanInvocation
. This can be used to determine which web service method was invoked and
what arguments were passed to it. In this example some simple logic is used to return results to the client based on the name of the method that
was called.
5.5.4. Security
Refer to the JAX-WS security section.
5.5.5. Code examples on GitHub
Example JAX-WS applications are available on GitHub.
5.6. JMS
Messaging support is provided through the camel-jms component which integrates with the WildFly Messaging (ActiveMQ Artemis) subsystem.
Integration with other JMS implementations is possible through configuration of vendor specific resource adapters, or if not available, by using the JBoss Generic JMS resource adapter.
5.6.1. WildFly JMS configuration
The WildFly messaging subsystem can be configured from within the standard WildFly XML configuration files, standalone.xml or domain.xml.
For the examples that follow we use the embedded ActiveMQ Artemis in memory instance. We first configure a new JMS queue on the messaging subsystem by adding the following XML configuration to the jms-destinations section.
<jms-queue name="WildFlyCamelQueue">
<entry name="java:/jms/queue/WildFlyCamelQueue"/>
</jms-queue>
Alternatively you could use a CLI script to add the queue.
jms-queue add --queue-address=WildFlyCamelQueue --entries=queue/WildFlyCamelQueue,java:/jms/queue/WildFlyCamelQueue
Or, you could create a messaging-deployment
configuration within a custom jms.xml deployment descriptor. See section 'Deployment of -jms.xml files' within the WildFly messaging subsystem documentation for more information.
5.6.2. Camel route configuration
The following JMS producer and consumer examples make use of WildFly’s embedded ActiveMQ Artemis sever to publish and consume messages to and from destinations.
The examples also use CDI in conjunction with the camel-cdi component. JMS ConnectionFactory instances are injected into the Camel RouteBuilder through JNDI lookups.
JMS Producer
The RouteBuilder begins by injecting the DefaultJMSConnectionFactory
connection factory from JNDI. If you’re wondering where the connection factory is defined, look at the WildFly XML configuration and you’ll see it is defined within the messaging subsystem.
Next a timer endpoint runs every 10 seconds to send an XML payload to the WildFlyCamelQueue destination that we configured earlier.
@Startup
@ApplicationScoped
@ContextName("jms-camel-context")
public class JmsRouteBuilder extends RouteBuilder {
@Resource(mappedName = "java:jboss/DefaultJMSConnectionFactory")
private ConnectionFactory connectionFactory;
@Override
public void configure() throws Exception {
JmsComponent component = new JmsComponent();
component.setConnectionFactory(connectionFactory);
getContext().addComponent("jms", component);
from("timer://sendJMSMessage?fixedRate=true&period=10000")
.transform(constant("<?xml version='1.0><message><greeting>hello world</greeting></message>"))
.to("jms:queue:WildFlyCamelQueue")
.log("JMS Message sent");
}
}
A log message will be output to the console each time a JMS message is added to the WildFlyCamelQueue destination. To verify that the messages really are being placed onto the queue, we can use the WildFly administration console.
JMS Consumer
To consume JMS messages the Camel RouteBuilder implementation is similar to the producer example.
As before, the connection factory is discovered from JNDI, injected and set on the JMSComponent instance.
When the JMS endpoint consumes messages from the WildFlyCamelQueue destination, the content is logged to the console.
@Override
public void configure() throws Exception {
JmsComponent component = new JmsComponent();
component.setConnectionFactory(connectionFactory);
getContext().addComponent("jms", component);
from("jms:queue:WildFlyCamelQueue")
.to("log:jms?showAll=true");
}
JMS Transactions
To enable Camel JMS routes to participate in JMS transactions, some additional configuration is required. Since camel-jms is built around spring-jms, we need to configure some Spring classes to enable them to work with WildFly’s transaction manager and connection factory. The following code example demonstrates how to use CDI to configure a transactional JMS Camel route.
The camel-jms component requires a transaction manager of type org.springframework.transaction.PlatformTransactionManager
. Therefore, we begin by creating a bean extending JtaTransactionManager
. Note that the bean is annotated with @Named
to allow the bean to be registered within the Camel bean registry. Also note that the WildFly transaction manager and user transaction instances are injected using CDI.
@Named("transactionManager")
public class CdiTransactionManager extends JtaTransactionManager {
@Resource(mappedName = "java:/TransactionManager")
private TransactionManager transactionManager;
@Resource
private UserTransaction userTransaction;
@PostConstruct
public void initTransactionManager() {
setTransactionManager(transactionManager);
setUserTransaction(userTransaction);
}
}
Next we need to declare the transaction policy that we want to use. Again we use the @Named
annotation to make the bean available to Camel. The transaction manager is also injected so that a TransactionTemplate can be created with the desired transaction policy. PROPAGATION_REQUIRED in this instance.
@Named("PROPAGATION_REQUIRED")
public class CdiRequiredPolicy extends SpringTransactionPolicy {
@Inject
public CdiRequiredPolicy(CdiTransactionManager cdiTransactionManager) {
super(new TransactionTemplate(cdiTransactionManager,
new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED)));
}
}
Now we can configure our Camel RouteBuilder class and inject the dependencies needed for the Camel JMS component. The WildFly XA connection factory is injected together with the transaction manager we configured earlier.
In this example RouteBuilder, whenever any messages are consumed from queue1, they are routed to another JMS queue named queue2. Messages consumed from queue2 result in JMS transaction being rolled back using the rollback() DSL method. This results in the original message being placed onto the dead letter queue(DLQ).
@Startup
@ApplicationScoped
@ContextName("jms-camel-context")
public class JMSRouteBuilder extends RouteBuilder {
@Resource(mappedName = "java:/JmsXA")
private ConnectionFactory connectionFactory;
@Inject
CdiTransactionManager transactionManager;
@Override
public void configure() throws Exception {
// Creates a JMS component which supports transactions
JmsComponent jmsComponent = JmsComponent.jmsComponentTransacted(connectionFactory, transactionManager);
getContext().addComponent("jms", jmsComponent);
from("jms:queue:queue1")
.transacted("PROPAGATION_REQUIRED")
.to("jms:queue:queue2");
// Force the transaction to roll back. The message will end up on the WildFly 'DLQ' message queue
from("jms:queue:queue2")
.to("log:end")
.rollback();
}
Remote JMS destinations
It’s possible for one WildFly instance to send messages to ActiveMQ Artemis destinations configured on another WildFly instance through remote JNDI.
Some additional WildFly configuration is required to achieve this. First an exported JMS queue is configured.
Only JNDI names bound in the java:jboss/exported
namespace are considered as candidates for remote clients, so the queue is named appropriately.
Note that the queue must be configured on the WildFly client application server and the WildFly remote server.
<jms-queue name="RemoteQueue">
<entry name="java:jboss/exported/jms/queues/RemoteQueue"/>
</jms-queue>
Before the client can connect to the remote server, user access credentials need to be configured. On the remote server run the add user utility to create a new application user within the 'guest' group. This example has a user with the name 'admin' and a password of 'secret'.
The RouteBuilder implementation is different to the previous examples. Instead of injecting the connection factory, we need to configure an InitalContext and retrieve it from JNDI ourselves.
The configureInitialContext
method creates this InitialContext. Notice that we need to set a provider URL which should reference your remote WildFly instance host name and port number. This example uses the WildFly JMS http-connector, but there are alternatives documented here.
Finally the route is configured to send an XML payload every 10 seconds to the remote destination configured earlier - 'RemoteQueue'.
@Override
public void configure() throws Exception {
Context initialContext = configureInitialContext();
ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup("java:jms/RemoteConnectionFactory");
JmsComponent component = new JmsComponent();
component.setConnectionFactory(connectionFactory);
getContext().addComponent("jms", component);
from("timer://foo?fixedRate=true&period=10000")
.transform(constant("<?xml version='1.0><message><greeting>hello world</greeting></message>"))
.to("jms:queue:RemoteQueue?username=admin&password=secret")
.to("log:jms?showAll=true");
}
private Context configureInitialContext() throws NamingException {
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
env.put(Context.PROVIDER_URL, System.getProperty(Context.PROVIDER_URL, "http-remoting://my-remote-host:8080"));
env.put(Context.SECURITY_PRINCIPAL, System.getProperty("username", "admin"));
env.put(Context.SECURITY_CREDENTIALS, System.getProperty("password", "secret"));
return new InitialContext(env);
}
5.6.3. Security
Refer to the JMS security section.
5.6.4. Code examples on GitHub
An example camel-jms application is available on GitHub.
5.7. JMX
Management support is provided through the camel-jmx component which integrates with the WildFly JMX subsystem.
CamelContext camelctx = contextFactory.createWildflyCamelContext(getClass().getClassLoader());
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
String host = InetAddress.getLocalHost().getHostName();
from("jmx:platform?format=raw&objectDomain=org.apache.camel&key.context=" + host + "/system-context-1&key.type=routes&key.name=\"route1\"" +
"&monitorType=counter&observedAttribute=ExchangesTotal&granularityPeriod=500").
to("direct:end");
}
});
camelctx.start();
ConsumerTemplate consumer = camelctx.createConsumerTemplate();
MonitorNotification notifcation = consumer.receiveBody("direct:end", MonitorNotification.class);
Assert.assertEquals("ExchangesTotal", notifcation.getObservedAttribute());
5.8. JNDI
JNDI integration is provided by a WildFly specific CamelContext, which is can be obtained like this
InitialContext inictx = new InitialContext();
CamelContextFactory factory = inictx.lookup("java:jboss/camel/CamelContextFactory");
WildFlyCamelContext camelctx = factory.createCamelContext();
From a WildFlyCamelContext
you can obtain a preconfigured Naming Context
Context context = camelctx.getNamingContext();
context.bind("helloBean", new HelloBean());
which can then be referenced from Camel routes.
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start").beanRef("helloBean");
}
});
camelctx.start();
5.9. JPA
JPA integration is provided by the Camel JPA component. Camel JPA applications are developed as per normal by providing a persistence.xml configuration file together with some JPA annotated classes.
5.9.1. Example persistence.xml
In this example we use the Wildfly in-memory ExampleDS datasource which is configured within the Wildfly standalone.xml configuration file.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="camel">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<class>org.wildfly.camel.test.jpa.model.Customer</class>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
5.9.2. Example JPA entitiy
@Entity
@Table(name = "customer")
public class Customer implements Serializable {
@Id
@GeneratedValue
private Long id;
private String firstName;
private String lastName;
public Customer() {
}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
5.9.3. Camel JPA endpoint / route configuration
Having configured JPA, you can make use of CDI to inject an EntityManager and UserTransaction instance into your RouteBuilder class or test case:
@PersistenceContext
EntityManager em;
@Inject
UserTransaction userTransaction;
Now to configure the Camel routes and JPA endpoint:
WildFlyCamelContext camelctx = contextFactory.createCamelContext(getClass().getClassLoader());
EntityManagerFactory entityManagerFactory = em.getEntityManagerFactory();
// Configure a transaction manager
JtaTransactionManager transactionManager = new JtaTransactionManager();
transactionManager.setUserTransaction(userTransaction);
transactionManager.afterPropertiesSet();
// Configure the JPA endpoint to use the correct EntityManagerFactory and JtaTransactionManager
final JpaEndpoint jpaEndpoint = new JpaEndpoint();
jpaEndpoint.setCamelContext(camelctx);
jpaEndpoint.setEntityType(Customer.class);
jpaEndpoint.setEntityManagerFactory(entityManagerFactory);
jpaEndpoint.setTransactionManager(transactionManager);
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.to(jpaEndpoint);
}
});
camelctx.start();
Finally, we can send a 'Customer' entity to the 'direct:start' endpoint and then query the ExampleDS datasource to verify that a record was saved.
Customer customer = new Customer("John", "Doe");
ProducerTemplate producer = camelctx.createProducerTemplate();
producer.sendBody("direct:start", customer);
// Query the in memory database customer table to verify that a record was saved
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Long> query = criteriaBuilder.createQuery(Long.class);
query.select(criteriaBuilder.count(query.from(Customer.class)));
long recordCount = em.createQuery(query).getSingleResult();
Assert.assertEquals(1L, recordCount);
6. Camel Components
This chapter details information about supported camel components
6.1. camel-activemq
Camel ActiveMQ integration is provided by the camel-activemq component.
The component can be configured to work with an embedded or external broker. For Wildfly / EAP container managed connection pools and XA-Transaction support, the ActiveMQ Resource Adapter can be configured into the container configuration file.
6.1.1. WildFly ActiveMQ resource adapter configuration
Dowonload the ActiveMQ resource adapter rar file. The following steps outline how to configure the ActiveMQ resource adapter.
1) Make sure your WildFly instance is stopped.
2) Copy the downloaded resource adapter to the relevant WildFly deployment directory. For standalone mode:
cp activemq-rar-5.11.1.rar ${JBOSS_HOME}/standalone/deployments/activemq-rar.rar
3) Configure the WildFly resource adapters subsystem for the ActiveMQ adapter.
<subsystem xmlns="urn:jboss:domain:resource-adapters:2.0">
<resource-adapters>
<resource-adapter id="activemq-rar.rar">
<archive>
activemq-rar.rar
</archive>
<transaction-support>XATransaction</transaction-support>
<config-property name="UseInboundSession">
false
</config-property>
<config-property name="Password">
defaultPassword
</config-property>
<config-property name="UserName">
defaultUser
</config-property>
<config-property name="ServerUrl">
tcp://localhost:61616?jms.rmIdFromConnectionId=true
</config-property>
<connection-definitions>
<connection-definition class-name="org.apache.activemq.ra.ActiveMQManagedConnectionFactory" jndi-name="java:/ActiveMQConnectionFactory" enabled="true" pool-name="ConnectionFactory">
<xa-pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>false</prefill>
<is-same-rm-override>false</is-same-rm-override>
</xa-pool>
</connection-definition>
</connection-definitions>
<admin-objects>
<admin-object class-name="org.apache.activemq.command.ActiveMQQueue" jndi-name="java:/queue/HELLOWORLDMDBQueue" use-java-context="true" pool-name="HELLOWORLDMDBQueue">
<config-property name="PhysicalName">
HELLOWORLDMDBQueue
</config-property>
</admin-object>
<admin-object class-name="org.apache.activemq.command.ActiveMQTopic" jndi-name="java:/topic/HELLOWORLDMDBTopic" use-java-context="true" pool-name="HELLOWORLDMDBTopic">
<config-property name="PhysicalName">
HELLOWORLDMDBTopic
</config-property>
</admin-object>
</admin-objects>
</resource-adapter>
</resource-adapters>
</subsystem>
If your resource adapter archive filename differs from activemq-rar.rar, you must change the content of the archive element in the preceding configuration to match the name of your archive file.
The values of the UserName and Password configuration properties must be chosen to match the credentials of a valid user in the external broker.
You might need to change the value of the ServerUrl configuration property to match the actual hostname and port exposed by the external broker.
4) Start WildFly. If everything is configured correctly, you should see a message within the WildFly server.log like.
13:16:08,412 INFO [org.jboss.as.connector.deployment] (MSC service thread 1-5) JBAS010406: Registered connection factory java:/AMQConnectionFactory
6.1.2. Camel route configuration
The following ActiveMQ producer and consumer examples make use of the ActiveMQ embedded broker and the 'vm' transport (thus avoiding the need for an external ActiveMQ broker).
The examples use CDI in conjunction with the camel-cdi component. JMS ConnectionFactory instances are injected into the Camel RouteBuilder through JNDI lookups.
ActiveMQ Producer
@Startup
@ApplicationScoped
@ContextName("activemq-camel-context")
public class ActiveMQRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("timer://sendJMSMessage?fixedRate=true&period=10000")
.transform(constant("<?xml version='1.0><message><greeting>hello world</greeting></message>"))
.to("activemq:queue:WildFlyCamelQueue?brokerURL=vm://localhost")
.log("JMS Message sent");
}
}
A log message will be output to the console each time a message is added to the WildFlyCamelQueue destination. To verify that the messages really are being placed onto the queue, we can use the ../features/hawtio.md[Hawtio console,window=_blank] provided by the WildFly Camel subsystem.
ActiveMQ Consumer
To consume ActiveMQ messages the Camel RouteBuilder implementation is similar to the producer example.
When the ActiveMQ endpoint consumes messages from the WildFlyCamelQueue destination, the content is logged to the console.
@Override
public void configure() throws Exception {
from("activemq:queue:WildFlyCamelQueue?brokerURL=vm://localhost")
.to("log:jms?showAll=true");
}
ActiveMQ Transactions
ActiveMQ Resource Adapter Configuration
The ActiveMQ resource adapter is required as we will want to leverage XA transaction support, connection pooling etc.
The XML snippet below shows how the resource adapter is configured within the WildFly server XML configuration. Notice that the ServerURL
is set to use an embedded broker. The connection factory is bound to the JNDI name java:/ActiveMQConnectionFactory
. This will be looked up in the RouteBuilder example that follows.
Finally, two queues are configured named 'queue1' and 'queue2'.
<subsystem xmlns="urn:jboss:domain:resource-adapters:2.0">
<resource-adapters>
<resource-adapter id="activemq-rar.rar">
...
<admin-objects>
<admin-object class-name="org.apache.activemq.command.ActiveMQQueue" jndi-name="java:/queue/queue1" use-java-context="true" pool-name="queue1pool">
<config-property name="PhysicalName">queue1</config-property>
</admin-object>
<admin-object class-name="org.apache.activemq.command.ActiveMQQueue" jndi-name="java:/queue/queue2" use-java-context="true" pool-name="queue2pool">
<config-property name="PhysicalName">queue2</config-property>
</admin-object>
</admin-objects>
</resource-adapter>
</resource-adapters>
</subsystem>
Transaction Manager
The camel-activemq component requires a transaction manager of type org.springframework.transaction.PlatformTransactionManager
. Therefore, we begin by creating a bean extending JtaTransactionManager
which fulfills this requirement. Note that the bean is annotated with @Named
to allow the bean to be registered within the Camel bean registry. Also note that the WildFly transaction manager and user transaction instances are injected using CDI.
@Named("transactionManager")
public class CdiTransactionManager extends JtaTransactionManager {
@Resource(mappedName = "java:/TransactionManager")
private TransactionManager transactionManager;
@Resource
private UserTransaction userTransaction;
@PostConstruct
public void initTransactionManager() {
setTransactionManager(transactionManager);
setUserTransaction(userTransaction);
}
}
Transaction Policy
Next we need to declare the transaction policy that we want to use. Again we use the @Named
annotation to make the bean available to Camel. The transaction manager is also injected so that a TransactionTemplate
can be created with the desired transaction policy. PROPAGATION_REQUIRED
in this instance.
@Named("PROPAGATION_REQUIRED")
public class CdiRequiredPolicy extends SpringTransactionPolicy {
@Inject
public CdiRequiredPolicy(CdiTransactionManager cdiTransactionManager) {
super(new TransactionTemplate(cdiTransactionManager,
new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED)));
}
}
Route Builder
Now we can configure our Camel RouteBuilder class and inject the dependencies needed for the Camel ActiveMQ component. The ActiveMQ connection factory that we configured on the resource adapter configutation is injected together with the transaction manager we configured earlier.
In this example RouteBuilder, whenever any messages are consumed from queue1, they are routed to another JMS queue named queue2. Messages consumed from queue2 result in JMS transaction being rolled back using the rollback() DSL method. This results in the original message being placed onto the dead letter queue(DLQ).
@Startup
@ApplicationScoped
@ContextName("activemq-camel-context")
public class ActiveMQRouteBuilder extends RouteBuilder {
@Resource(mappedName = "java:/ActiveMQConnectionFactory")
private ConnectionFactory connectionFactory;
@Inject
private CdiTransactionManager transactionManager;
@Override
public void configure() throws Exception {
ActiveMQComponent activeMQComponent = ActiveMQComponent.activeMQComponent();
activeMQComponent.setTransacted(false);
activeMQComponent.setConnectionFactory(connectionFactory);
activeMQComponent.setTransactionManager(transactionManager);
getContext().addComponent("activemq", activeMQComponent);
errorHandler(deadLetterChannel("activemq:queue:ActiveMQ.DLQ")
.useOriginalMessage()
.maximumRedeliveries(0)
.redeliveryDelay(1000));
from("activemq:queue:queue1F
.transacted("PROPAGATION_REQUIRED")
.to("activemq:queue:queue2");
from("activemq:queue:queue2")
.to("log:end")
.rollback();
}
}
6.1.3. Security
Refer to the JMS security section.
6.1.4. Code examples on GitHub
An example camel-activemq application is available on GitHub.
6.2. camel-atom
Atom feed consumption in Camel is provided by the camel-atom component.
The following example configures an Atom endpoint to consume the recent activity GitHub feed of user 'wildflyext'. The raw content of each feed entry is then written out as a file within directory 'feed/entries'.
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("atom://https://github.com/wildflyext.atom?splitEntries=true")
.process(new Processor() {
@Override
public void process(final Exchange exchange) throws Exception {
Entry entry = exchange.getIn().getBody(Entry.class);
exchange.getOut().setBody(entry.getContent());
}
})
.to("file:///feed/entries/");
}
});
6.3. camel-bean-validator
The camel-bean-validator component provides support for message body validation using the Java Bean Validation API.
6.4. camel-bindy
The goal of camel-bindy is to allow the parsing/binding of non-structured data to/from Java Beans that have binding mappings defined with annotations.
Here we have a annotated domain model class
@CsvRecord(separator = ",")
public class Customer {
@DataField(pos = 1)
private String firstName;
@DataField(pos = 2)
private String lastName;
...
}
We can use the BindyCsvDataFormat
data format unmarshall CSV data like John,Doe
to the domain model.
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.unmarshal(new BindyCsvDataFormat(Customer.class))
.to("mock:result");
}
});
camelctx.start();
6.5. camel-braintree
The camel-braintree component provides access to Braintree Payments trough through their Java SDK.
BraintreeComponent component = new BraintreeComponent(camelctx);
component.setConfiguration(configuration);
camelctx.addComponent("braintree", component);
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("timer://braintree?repeatCount=1")
.to("braintree:clientToken/generate")
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
latch.countDown();
}})
.to("mock:result");
}
});
6.6. camel-cassandra
The camel-cassandra component is an open source NoSQL database designed to handle large amounts on commodity hardware. Like Amazon’s DynamoDB, Cassandra has a peer-to-peer and master-less architecture to avoid single point of failure and garanty high availability. Like Google’s BigTable, Cassandra data is structured using column families which can be accessed through the Thrift RPC API or a SQL-like API called CQL.
6.7. camel-cdi
Covered by CDI.
6.8. camel-crypto
Secure message exchanges in camel is provided by the camel-crypto component.
With Camel cryptographic endpoints and Java’s Cryptographic extension it is easy to create Digital Signatures for Exchanges. Camel provides a pair of flexible endpoints which get used in concert to create a signature for an exchange in one part of the exchange’s workflow and then verify the signature in a later part of the workflow.
Begin by loading a keystore for binding to JNDI so that camel can discover it from its bean registry.
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = getClass().getResourceAsStream("/my-keystore.ks");
keystore.load(in, "my-keystore-password".toCharArray());
Certificate cert = keystore.getCertificate("my-certificate-alias");
KeyStoreParameters keystoreParameters = new KeyStoreParameters();
keystoreParameters.setPassword("my-keystore-password");
keystoreParameters.setResource("./my-keystore.ks");
InitialContext initialContext = new InitialContext();
initialContext.bind("signatureParams", keystoreParameters);
initialContext.bind("keystore", keystore);
initialContext.bind("myPublicKey", cert.getPublicKey());
initialContext.bind("myCert", cert);
initialContext.bind("myPrivateKey", keystore.getKey("my-certificate-alias", "my-keystore-password".toCharArray()));
Finally, a Camel route that signs and verifies an exchange.
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:sign")
.to("crypto:sign://basic?privateKey=#myPrivateKey")
.to("direct:verify");
from("direct:verify")
.to("crypto:verify://basic?publicKey=#myPublicKey")
.to("mock:result");
}
});
6.10. camel-dns
The camel-dns component provides the ability to:
-
Resolve a domain by its ip
-
Lookup information about a domain
-
Run DNS queries
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.to("dns:lookup");
}
});
ProducerTemplate producer = camelctx.createProducerTemplate();
Record[] record = producer.requestBodyAndHeader("direct:start", null, DnsConstants.DNS_NAME, "wildfly.org", Record[].class);
6.11. camel-dozer
The camel-dozer component provides the ability to map between Java beans using the Dozer mapping framework. Camel also supports the ability to trigger Dozer mappings as a type converter.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start").convertBodyTo(CustomerB.class);
}
});
DozerBeanMapperConfiguration mconfig = new DozerBeanMapperConfiguration();
mconfig.setMappingFiles(Arrays.asList(new String[] { "mappings.xml" }));
new DozerTypeConverterLoader(camelctx, mconfig);
6.12. camel-ejb
Covered by EJB.
6.13. camel-elasticsearch
The camel-elasticsearch component allows you to interface with an ElasticSearch server.
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:index")
.to("elasticsearch://local?operation=INDEX&indexName=twitter&indexType=tweet");
}
});
Map<String, String> indexedData = new HashMap<>();
indexedData.put("content", "test");
ProducerTemplate template = camelContext.createProducerTemplate();
template.sendBody("direct:index", indexedData);
6.14. camel-file2
The camel-file component provides access to file systems, allowing files to be processed by any other Camel Components or messages from other components to be saved to disk.
Here is a simple route that prepends the message with 'Hello' and writes the result to a file in WildFly’s data directory.
final String datadir = System.getProperty("jboss.server.data.dir");
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start").transform(body().prepend("Hello ")).
to("file:" + datadir + "?fileName=camel-file.txt");
}
});
6.15. camel-ftp
The camel-ftp component provides access to remote file systems over the FTP and SFTP protocols.
CamelContext camelctx = new DefaultCamelContext();
Endpoint endpoint = camelctx.getEndpoint("ftp://localhost:21000/foo?username=admin&password=admin");
camelctx.createProducerTemplate().sendBodyAndHeader(endpoint, "Hello", "CamelFileName", "test.txt");
6.16. camel-hl7
The camel-hl7 component is used for working with the HL7 MLLP protocol and HL7 v2 messages using the HAPI library.
final String msg = "MSH|^~\\&|MYSENDER|MYRECEIVER|MYAPPLICATION||200612211200||QRY^A19|1234|P|2.4\r";
final HL7DataFormat format = new HL7DataFormat();
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.marshal(format)
.unmarshal(format)
.to("mock:result");
}
});
camelctx.start();
HapiContext context = new DefaultHapiContext();
Parser p = context.getGenericParser();
Message hapimsg = p.parse(msg);
ProducerTemplate producer = camelctx.createProducerTemplate();
Message result = (Message) producer.requestBody("direct:start", hapimsg);
Assert.assertEquals(hapimsg.toString(), result.toString());
6.17. camel-http4
The camel-http component provides HTTP based endpoints for calling external HTTP resources.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.to("http4://somehost:8080/simple/myservlet");
}
});
6.18. camel-hystrix
The camel-hystrix EIP provides integration with Netflix Hystrix to be used as circuit breaker in Camel routes.
6.19. camel-infinispan
This camel-infinispan component allows you to interact with Infinispan distributed data grid / caches.
You can interact with container managed Infinispan caches by referring to their JNDI lookup within your Camel route. For example, to write a cache entry.
DefaultCamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:put")
.to("infinispan://localhost?cacheContainer=#java:jboss/infinispan/container/myCache&command=PUT");
}
});
Map<String, Object> headers = new HashMap<>();
headers.put(InfinispanConstants.KEY, "name");
headers.put(InfinispanConstants.VALUE, "kermit");
ProducerTemplate template = camelctx.createProducerTemplate();
template.sendBodyAndHeaders("direct:put", null, headers);
Or you can interact with external Infinispan caches.
DefaultCamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:put")
.to("infinispan://my.cache.host?command=PUT");
}
});
Map<String, Object> headers = new HashMap<>();
headers.put(InfinispanConstants.KEY, "name");
headers.put(InfinispanConstants.VALUE, "kermit");
ProducerTemplate template = camelctx.createProducerTemplate();
template.sendBodyAndHeaders("direct:put", null, headers);
6.20. camel-irc
6.21. camel-jasypt
The camel-jasypt component provides a simplified encryption library which makes encryption and decryption easy. Camel integrates with Jasypt to allow sensitive information in Properties files to be encrypted.
JasyptPropertiesParser jasypt = new JasyptPropertiesParser();
jasypt.setPassword("secret");
PropertiesComponent pc = new PropertiesComponent();
pc.setLocation("classpath:mysecrets.properties");
pc.setPropertiesParser(jasypt);
context.addComponent("properties", pc);
6.22. camel-jaxb
Covered by JAXB.
6.23. camel-jdbc
The camel-jdbc component provides access to SQL databases via JDBC.
6.24. camel-jgroups
The camel-jgroups component provides reliable multicast communication via the JGroups toolkit.
6.25. camel-jms
Covered by JMS.
6.26. camel-jmx
Covered by JMX.
6.27. camel-jpa
Covered by JPA.
6.28. camel-jsch
The camel-jsch component enables secure file transfer using the SCP protocol.
CamelContext camelctx = new DefaultCamelContext();
Endpoint endpoint = camelctx.getEndpoint("scp://localhost:22/my/directory?username=admin&password=admin");
camelctx.createProducerTemplate().sendBodyAndHeader(endpoint, "Hello", "CamelFileName", "test.txt");
6.29. camel-kafka
The camel-kafka component is used for communicating with Apache Kafka message broker.
6.30. camel-ldap
The camel-ldap component provides the capability to perform LDAP queries.
6.31. camel-linkedin
The camel-linkedin component provides access to the LinkedIn REST APIs.
You must have a valid developer account in order to use this component.
6.32. camel-lucene
The camel-lucene component is based on the Apache Lucene project. Apache Lucene is a powerful high-performance, full-featured text search engine library written entirely in Java.
6.33. camel-mail
Interaction with email is provided by the camel-mail component.
By default, Camel will create its own mail session and use this to interact with your mail server. Since WildFly already provides a mail subsystem with all of the relevant support for secure connections, username / password encryption etc, it is recommended to configure your mail sessions within the WildFly configuration and use JNDI to wire them into your Camel endpoints.
6.33.1. WildFly configuration
First we configure the WildFly mail subsystem for our Mail server. This example adds configuration for Google Mail IMAP and SMTP .
An additional mail-session is configured after the 'default' session.
<subsystem xmlns="urn:jboss:domain:mail:2.0">
<mail-session name="default" jndi-name="java:jboss/mail/Default">
<smtp-server outbound-socket-binding-ref="mail-smtp"/>
</mail-session>
<mail-session debug="true" name="gmail" jndi-name="java:jboss/mail/gmail">
<smtp-server outbound-socket-binding-ref="mail-gmail-smtp" ssl="true" username="your-username-here" password="your-password-here"/>
<imap-server outbound-socket-binding-ref="mail-gmail-imap" ssl="true" username="your-username-here" password="your-password-here"/>
</mail-session>
</subsystem>
Note that we configured outbound-socket-binding-ref
values of 'mail-gmail-smtp' and 'mail-gmail-imap'. The next step is to configure these socket bindings. Add aditional bindings to the socket-binding-group
configuration like the following.
<outbound-socket-binding name="mail-gmail-smtp">
<remote-destination host="smtp.gmail.com" port="465"/>
</outbound-socket-binding>
<outbound-socket-binding name="mail-gmail-imap">
<remote-destination host="imap.gmail.com" port="993"/>
</outbound-socket-binding>
This configures our mail session to connect to host smtp.gmail.com on port 465 and imap.gmail.com on port 993. If you’re using a different mail host, then this detail will be different.
6.33.2. POP3 Configuration
If you need to configure POP3 sessions, the principals are the same as defined in the examples above.

<pop3-server outbound-socket-binding-ref="mail-pop3" ssl="true" username="your-username-here" password="your-password-here"/>

<outbound-socket-binding name="mail-gmail-imap">
<remote-destination host="pop3.gmail.com" port="993"/>
</outbound-socket-binding>
6.33.3. Camel route configuration
Mail producer
This example uses the SMTPS protocol, together with CDI in conjunction with the camel-cdi component. The Java mail session that we configured within the WildFly configuration is injected into a Camel RouteBuilder through JNDI.
Route builder SMTPS example
The GMail mail session is injected into a Producer class using the @Resource
annotation with a reference to the jndi-name
attribute that we previously configured. This allows us to reference the mail session on the camel-mail endpoint configuration.
public class MailSessionProducer {
@Resource(lookup = "java:jboss/mail/greenmail")
private Session mailSession;
@Produces
@Named
public Session getMailSession() {
return mailSession;
}
}
public class MailRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:start")
.to("smtps://smtp.gmail.com?session=#mailSession");
}
}
To send an email we can create a ProducerTemplate and send an appropriate body together with the necessary email headers.
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("To", "destination@test.com");
headers.put("From", "sender@example.com");
headers.put("Subject", "Camel on Wildfly rocks");
String body = "Hi,\n\nCamel on Wildfly rocks!.";
ProducerTemplate template = camelContext.createProducerTemplate();
template.sendBodyAndHeaders("direct:start", body, headers);
Mail consumer
To receive email we use an IMAP MailEndpoint. The Camel route configuration looks like the following.
public void configure() throws Exception {
from("imaps://imap.gmail.com?session=#mailSession")
.to("log:email");
}
6.33.4. Security
SSL configuration
WildFly can be configured to manage Java mail sessions and their associated transports using SSL / TLS. When configuring mail sessions you can configure SSL or TLS on server types:
-
smtp-server
-
imap-server
-
pop-server
By setting attributes ssl="true"
or tls="true"
.
Securing passwords
Writing passwords in clear text within configuration files is never a good idea for obvious reasons. The WildFly Vault provides tooling to mask sensitive data.
Camel security
Camel endpoint security documentation can be found on the camel-mail component guide. Camel also has a security summary page.
6.33.5. Code examples on GitHub
An example camel-mail application is available on GitHub for you to try out sending / receiving email.
6.34. camel-metrics
The camel-metrics component allows you to define, publish and collect metrics from Camel routes.
from("direct:start")
.to("metric:counter:simple.counter?increment=3")
6.35. camel-mina2
The camel-mina2 component is a transport for working with Apache MINA.
6.36. camel-mongodb
The camel-mongodb component provides the capabilty to interact with MongoDB servers.
6.37. camel-mqtt
The camel-mqtt component is used for communicating with MQTT compliant message brokers, like Apache ActiveMQ or Mosquitto.
6.38. camel-mvel
The camel-mvel component allows you to process a message using an MVEL template.
A simple template
Hello @{request.body}
can be used like this
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start").to("mvel:template.mvel");
}
});
camelctx.start();
ProducerTemplate producer = camelctx.createProducerTemplate();
String result = producer.requestBody("direct:start", "Kermit", String.class);
Assert.assertEquals("Hello Kermit", result);
6.39. camel-nats
The camel-nats component is used for communicating with the NATS messaging platform.
6.40. camel-netty4
Netty client / server support in Camel is provided by the camel-netty4 component.
WildFly 8 and EAP 6.4 are bundled with module libraries supporting the Netty project version 4. Therefore, the standard camel-netty component will not work since it is compatible with Netty version 3 only.
6.40.1. Simple Netty Client / Server Test
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("netty4:tcp://localhost:7666?textline=true")
.transform(simple("Hello ${body}"))
.to("direct:end");
}
});
camelContext.start();
PollingConsumer pollingConsumer = camelContext.getEndpoint("direct:end").createPollingConsumer();
pollingConsumer.start();
Socket socket = new Socket("localhost", 7666);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
try {
out.write("Kermit\n");
} finally {
out.close();
socket.close();
}
String result = pollingConsumer.receive().getIn().getBody(String.class);
Assert.assertEquals("Hello Kermit", result);
camelContext.stop();
6.41. camel-ognl
OGNL expression support in Camel is provided by the camel-ognl component.
6.41.1. Simple Camel OGNL Use Case
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.choice()
.when()
.ognl("request.body.name == 'Kermit'").transform(simple("Hello ${body.name}"))
.otherwise()
.to("mock:dlq");
}
});
camelContext.start();
Person person = new Person();
person.setName("Kermit");
ProducerTemplate producer = camelContext.createProducerTemplate();
String result = producer.requestBody("direct:start", person, String.class);
Assert.assertEquals("Hello Kermit", result);
camelContext.stop();
6.42. camel-olingo2
The camel-olingo2 component provides the capability to interact with OData 2.0 and 3.0 compliant services via Apache Olingo.
6.43. camel-pdf
The camel-pdf component provides the ability to create, modify or extract content from PDF documents. This component uses Apache PDFBox as underlying library to work with PDF documents.
6.44. camel-quartz2
The camel-quartz component provides a scheduled delivery of messages using the Quartz Scheduler 2.x.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
public void configure() throws Exception {
from("quartz2://mytimer?trigger.repeatCount=3&trigger.repeatInterval=100")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
latch.countDown();
}})
.to("mock:result");
}
});
6.45. camel-rest
The camel-rest component allows you to define REST endpoints using the Rest DSL and plugin to other Camel components as the REST transport.
|
The WildFly Camel Subsystem only supports the camel-servlet and camel-undertow components for use with the REST DSL. Attempts to configure other components will not work. |
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
restConfiguration().component("servlet").contextPath("camel/rest").port(8080);
rest("/hello").get("/{name}").to("direct:hello");
from("direct:hello").transform(simple("Hello ${header.name}"));
}
});
6.46. camel-rss
The camel-rss component is used for polling RSS feeds.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
public void configure() throws Exception {
from("rss://https://developer.jboss.org/blogs/feeds/posts?splitEntries=true&consumer.initialDelay=200&consumer.delay=1000")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
latch.countDown();
}})
.to("mock:result");
}
});
6.47. camel-salesforce
The camel-salesforce component provides producer and consumer endpoints to communicate with Salesforce.
In order to use the component, you will need a valid Salesforce account together with credentials for accessing the Salesforce API:
-
Client ID
-
Client Secret
-
Password
-
Username
You’ll want to generate the necessary Salesforce DTO objects before starting. This can be automated with the Camel Salesforce Maven plugin.
mvn camel-salesforce:generate -DcamelSalesforce.clientId=<clientid> -DcamelSalesforce.clientSecret=<clientsecret> -DcamelSalesforce.userName=<username> -DcamelSalesforce.password=<password>
This example queries Salesforce 'Opportunity' objects.
SalesforceLoginConfig loginConfig = new SalesforceLoginConfig();
loginConfig.setClientId("your-client-id");
loginConfig.setPassword("your-password");
loginConfig.setClientSecret("your-client-secret");
loginConfig.setUserName("your-username");
SalesforceComponent component = new SalesforceComponent();
// The package path to the generated DTO classes
component.setPackages("org.wildfly.camel.test.salesforce.dto");
component.setLoginConfig(loginConfig);
CamelContext camelctx = new DefaultCamelContext();
camelctx.addComponent("salesforce", component);
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:query")
.to("salesforce:query?sObjectQuery=SELECT id,name from Opportunity&sObjectClass=" + QueryRecordsOpportunity.class.getName())
.to("log:salesforce?showAll=true");
}
});
camelctx.start();
ProducerTemplate producer = ctx.createProducerTemplate();
QueryRecordsOpportunity queryRecords = producer.requestBody("direct:query", null, QueryRecordsOpportunity.class);
6.48. camel-sap
camel-sap is a package consisting of ten different SAP components.
There are remote function call (RFC) components that support the sRFC, tRFC, and qRFC protocols; and there are IDoc components that facilitate communication using messages in IDoc format. The component uses the SAP Java Connector (SAP JCo) library to facilitate bidirectional communication with SAP and the SAP IDoc library to facilitate the transmission of documents in the Intermediate Document (IDoc) format.
|
A prerequisite for using the Camel SAP component is that the SAP Java Connector (SAP JCo) libraries and the SAP IDoc library are available for the WildFly Camel Subsytem to use. The subsystem distribution does not include these libraries. You will need access to the SAP Service Marketplace in order to obtain them. |
6.48.1. Configuring the camel-sap module
Before using camel-sap, an additional WildFly / EAP modules needs to be configured so that the subsystem can discover the new functionality.
Your application server should be stopped before making the following changes.
Modify module com.sap.conn.jco
Download the SAP JCo libraries and the SAP IDoc library from the SAP Service Marketplace, making sure to choose the appropriate library versions for your operating system.
-
From a terminal session, change into the application server installation root directory
-
Change into directory
modules/system/layers/fuse
-
Copy
sapjco3.jar
andsapidoc3.jar
intocom/sap/conn/jco/main
-
Create an appropriate native library directory within
com/sap/conn/jco/main
. For example, if your target platform is Linux x86_64 you would createlib/linux-x86_64
. For information relating to other operating systems and architectures see the WildFly Native Libraries documentation -
Copy the JCO native library (i.e the
.so
,.dll
or.jnilib file
) into the native library directory you created in the previous step
The file and directory structure for module com.sap.conn.jco
should now look something like this:
com/sap/conn/jco
com/sap/conn/jco/main
com/sap/conn/jco/main/sapidoc3.jar
com/sap/conn/jco/main/sapjco3.jar
com/sap/conn/jco/main/module.xml
com/sap/conn/jco/main/lib
com/sap/conn/jco/main/lib/linux-x86_64
com/sap/conn/jco/main/lib/linux-x86_64/libsapjco3.so
Activate camel-sap component module
-
From a terminal session change into the application server installation root directory
-
Change into directory
modules/system/layers/fuse/org/wildfly/camel/extras/main
-
Edit
module.xml
and uncomment theorg.fusesource.camel.component.sap
module dependency. Save the modifed file when finished
The module definition should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.wildfly.camel.extras">
<dependencies>
<module name="org.fusesource.camel.component.sap" export="true" services="export" />
</dependencies>
</module>
Start your application server and camel-sap will be available for use.
6.48.2. Example SAP Camel Route
This example uses XML files containing serialized SAP requests to query Customer records in the Flight Data Application within SAP.
These files are consumed by Camel and their contents are then converted to string message bodies. These messages are then routed to an sap-srfc-destination
endpoint which converts and sends them to SAP as BAPI_FLCUST_GETLIST
requests to query Customer records.
First we configure a destination data store.
DestinationData destinationData = new DestinationDataImpl();
destinationData.setAshost("example.com");
destinationData.setSysnr("00");
destinationData.setClient("000");
destinationData.setUser("user");
destinationData.setPasswd("password");
destinationData.setLang("en");
Map<String, DestinationData> destinationDataStore = new HashMap<>();
destinationDataStore.put("quickstartDest", destinationData);
Next wire the destinationDataStore into a SapConnectionConfiguration.
SapConnectionConfiguration configuration = new SapConnectionConfiguration();
configuration.setDestinationDataStore(destinationDataStore);
The Camel RouteBuilder looks like this.
@ApplicationScoped
@ContextName("camel-sap-cdi-context")
@Startup
public class SAPRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("file:src/data")
.convertBodyTo(String.class)
.to("log:sap?showAll=true")
.to("sap-srfc-destination:quickstartDest:BAPI_FLCUST_GETLIST")
.to("log:sap?showAll=true");
}
}
The XML request looks like the following and is consumed from a file within src/data.
<?xml version="1.0" encoding="ASCII"?>

<BAPI_FLCUST_GETLIST:Request xmlns:BAPI_FLCUST_GETLIST="http://sap.fusesource.org/rfc/XXX/BAPI_FLCUST_GETLIST" CUSTOMER_NAME="*" MAX_ROWS="10" WEB_USER="*"/>
When the Camel route runs, the request XML data is consumed from src/data and sent to SAP as a BAPI_FLCUST_GETLIST
request. The results of the SAP request are output to the console.
You should see an XML structure like the following containing customer records.
<?xml version="1.0" encoding="ASCII"?>
<BAPI_FLCUST_GETLIST:Response xmlns:BAPI_FLCUST_GETLIST="http://sap.fusesource.org/rfc/JBF/BAPI_FLCUST_GETLIST">
<CUSTOMER_LIST>
<row CUSTOMERID="00004715" CUSTNAME="Fred Flintstone" FORM="Mr." STREET="123 Flintstone Lane" POBOX="" POSTCODE="01234" CITY="Bedrock" COUNTR="US" COUNTR_ISO="US" REGION="" PHONE="800-555-1212" EMAIL=""/>
<row CUSTOMERID="00004716" CUSTNAME="Wilma Flintstone" FORM="Mr." STREET="123 Flintstone Lane" POBOX="" POSTCODE="01234" CITY="Bedrock" COUNTR="US" COUNTR_ISO="US" REGION="" PHONE="800-555-1212" EMAIL=""/>
</CUSTOMER_LIST>
<CUSTOMER_RANGE/>
<EXTENSION_IN/>
<EXTENSION_OUT/>
<RETURN>
<row TYPE="S" ID="BC_IBF" NUMBER="000" MESSAGE="Method was executed successfully" LOG_NO="" LOG_MSG_NO="000000" MESSAGE_V1="" MESSAGE_V2="" MESSAGE_V3="" MESSAGE_V4="" PARAMETER="" FIELD="" SYSTEM="DEVQKCLNT"/>
</RETURN>
</BAPI_FLCUST_GETLIST:Response>
6.48.3. Further Reading
The example above only scratches the surface of the functionality provided by the camel-sap component. For comprehensive component documentation visit the Camel SAP Component Reference.
6.49. camel-saxon
The camel-saxon component supports XQuery to allow an Expression or Predicate to be used in the DSL or Xml Configuration.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
Namespaces ns = new Namespaces("ns", "http://org/wildfly/test/jaxb/model/Customer");
from("direct:start").transform().xquery("/ns:customer/ns:firstName", String.class, ns)
.to("mock:result");
}
});
6.50. camel-script
The camel-script component supports a number of scripting languages which can be used to create an Expression or Predicate via the standard JSR 223
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start").choice()
.when(script("beanshell", "request.getHeaders().get(\"foo\").equals(\"bar\")")).to("mock:result")
.otherwise().transform(body().append(" unmatched")).to("mock:unmatched");
}
});
6.51. camel-servicenow
The camel-servicenow component provides access to the ServiceNow REST APIs.
6.52. camel-servlet
The camel-servlet component provides HTTP based endpoints for consuming HTTP requests that arrive at a HTTP endpoint that is bound to a published Servlet.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("servlet://hello?servletName=CamelServletTest&matchOnUriPrefix=true")
.process(new Processor() {
@Override
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody("Hello Kermit");
}
});
}
});
6.53. camel-smpp
The camel-smpp component enables SMSC over the SMPP protocol in order to send and receive SMS.
6.54. camel-spring
Camel contexts can be configured with Spring via the camel-spring component.
6.54.1. Camel Spring XML example
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="hello-camel-context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="timer:hello?period=5000" />
<log message="Hello world" />
</route>
</camelContext>
</beans>
6.54.2. Deployment
Spring Camel contexts can be deployed either as part of the camel subsystem configuration or by deploying a '-camel-context.xml' suffixed file.
For more information see the features.
6.55. camel-sql
The camel-sql component allows you to work with databases using JDBC queries. The difference between this component and JDBC component is that in case of SQL the query is a property of the endpoint and it uses message payload as parameters passed to the query.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("sql:select name from information_schema.users?dataSource=java:jboss/datasources/ExampleDS")
.to("direct:end");
}
});
|
The JNDI datasource lookup shown above works only when configuring a |
When used in conjunction with the camel-cdi component, Java EE annotations can make a datasource available to Camel.
This example uses the @Named
annotation so that Camel can discover the desired datasource.
public class DatasourceProducer {
@Resource(name = "java:jboss/datasources/ExampleDS")
DataSource dataSource;
@Produces
@Named("wildFlyExampleDS")
public DataSource getDataSource() {
return dataSource;
}
}
Now the datasource can be referenced through the dataSource
parameter on the camel-sql endpoint configuration.
@ApplicationScoped
@ContextName("camel-sql-cdi-context")
@Startup
public class CdiRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
from("sql:select name from information_schema.users?dataSource=wildFlyExampleDS")
.to("direct:end");
}
}
When using camel-spring the route configuration would look like:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<jee:jndi-lookup id="wildFlyExampleDS" jndi-name="java:jboss/datasources/ExampleDS"/>
<camelContext id="sql-spring-context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="sql:select name from information_schema.users?dataSource=#wildFlyExampleDS" />
<to uru="direct:end" />
</route>
</camelContext>
</beans>
6.55.1. Spring JDBC XML namespace support
Support for the following Spring JDBC XML configurations is supported
jdbc:embedded-database
Only H2 databases are supported by default as WildFly has native support for this. If you want to use other embedded database providers, you will need to install the appropriate database driver.
<jdbc:embedded-database id="datasource" type="H2">
<jdbc:script location="db-schema.sql"/>
</jdbc:embedded-database>
jdbc:initialize-database
<jdbc:initialize-database data-source="datasource">
<jdbc:script location="classpath:db-init.sql"/>
</jdbc:initialize-database>
6.56. camel-stream
The camel-stream component provides access to the System.in
, System.out
and System.err
streams as well as allowing streaming of file and URL.
6.57. camel-swagger
The camel-swagger module is used for exposing the REST services and their APIs using Swagger.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
restConfiguration().component("servlet").contextPath("swagger-tests/rest").port(8080);
rest("/hello").get("/{name}").to("direct:hello");
from("direct:hello").transform(simple("Hello ${header.name}"));
}
});
camelctx.start();
6.58. camel-twitter
The camel-twitter component provides the capability to interact with the Twitter API in order to create and consume tweets, timelines, users, trends, and direct messages.
6.59. camel-undertow
The camel-undertow component provides HTTP-based endpoints for consuming and producing HTTP requests. That is, the Undertow component behaves as a simple Web server. Undertow can also be used as a http client which mean you can also use it with Camel as a producer.
The Undertow component integrates with the Undertow server provided by WildFly.
6.60. camel-velocity
The camel-velocity component allows you to process a message using an Apache Velocity template.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start").to("velocity:" + VELOCITY_TEMPLATE);
}
});
camelctx.start();
6.61. camel-vertx
The camel-vertx component is for working with the Vertx EventBus. The Vertx EventBus sends and receives JSON events.
6.62. camel-weather
The camel-weather component provides integration with the Open Weather Map API.
As an example, we can consume the current weather for Madrid in Spain and make some decisions based upon the humidity percentage:
CamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("weather:foo?location=Madrid,Spain")
.choice()
.when().jsonpath("$..[?(@humidity > 90)]")
.to("direct:veryhumid")
.when().jsonpath("$..[?(@humidity > 70)]")
.to("direct:humid")
.otherwise()
.to("direct:nothumid");
}
});
camelContext.start();
6.63. camel-xstream
The camel-xstream component provides the XStream Data Format which uses the XStream library to marshal and unmarshal Java objects to and from XML.
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.marshal().xstream();
}
});
camelctx.start();
try {
ProducerTemplate producer = camelctx.createProducerTemplate();
String customer = producer.requestBody("direct:start", new Customer("John", "Doe"), String.class);
} finally {
camelctx.stop();
}
6.64. camel-zipkin
The camel-zipkin component is used for tracing and timing incoming and outgoing Camel messages using zipkin. Events are captured for incoming and outgoing messages being sent to/from Camel.
6.65. camel-zookeeper
The camel-zookeeper component allows interaction with a ZooKeeper cluster and exposes the following features to Camel:
-
Creation of nodes in any of the ZooKeeper create modes.
-
Get and Set the data contents of arbitrary cluster nodes.
-
Create and retrieve the list the child nodes.
-
A Distributed RoutePolicy that leverages a Leader election.
7. Adding Components
Adding support for additional Camel Components is easy
Add your modules.xml definition
A modules.xml descriptor defines the class loading behavior for your component. It should be placed together with the component’s jar in modules/system/layers/fuse/org/apache/camel/component
. Module dependencies should be setup for direct compile time dependencies.
Here is an example for the camel-ftp component
<module xmlns="urn:jboss:module:1.1" name="org.apache.camel.component.ftp">
<resources>
<resource-root path="camel-ftp-2.14.0.jar" />
</resources>
<dependencies>
<module name="com.jcraft.jsch" />
<module name="javax.xml.bind.api" />
<module name="org.apache.camel.core" />
<module name="org.apache.commons.net" />
</dependencies>
</module>
Please make sure you don’t duplicate modules that are already available in WildFly and can be reused.
Add a reference to the component
To make this module visible by default to arbitrary JavaEE deployments add a reference to modules/system/layers/fuse/org/apache/camel/component/main/module.xml
<module xmlns="urn:jboss:module:1.3" name="org.apache.camel.component">
<dependencies>
...
<module name="org.apache.camel.component.ftp" export="true" services="export"/>
</dependencies>
</module>
8. Data Formats
9. Languages
The following lists supported scripting languages
10. Cloud Integration
This chapter details information about cloud integration
10.1. Docker
This chapter gets you started on WildFly-Camel on Docker
10.1.1. Installing Docker
SSH into your instance and type
$ sudo yum install -y docker
$ sudo service docker start
to install and start Docker.
Giving non-root access
The docker daemon always runs as the root user, and the docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root, and so, by default, you can access it with sudo.
If you have a Unix group called docker
and add users to it, then the docker daemon will make the ownership of the Unix socket read/writable by the docker
group when the daemon starts. The docker daemon must always run as the root user, but if you run the docker client as a user in the docker
group then you don’t need to add sudo to all the client commands.
$ sudo usermod -a -G docker ec2-user
$ sudo service docker restart
|
You may have to logout/login for this change to take effect |
In my case I also had to add a host mapping like this
[ec2-user@ip-172-30-0-233 ~]$ sudo cat /etc/hosts
<IP_ADDRESS> localhost localhost.localdomain
<IP_ADDRESS> ip-172-30-0-233
and make the docker daemon bind to a number of sockets
[ec2-user@ip-172-30-0-217 ~]$ cat /etc/sysconfig/docker
# Additional startup options for the Docker daemon
OPTIONS="-H tcp://<IP_ADDRESS>:2375 -H unix:///var/run/docker.sock"
10.1.2. Running WildFly-Camel
With every WildFly-Camel release we also publish the latest wildflyext/wildfly-camel image.
You can run the standalone container like this
$ docker run --rm -ti -e WILDFLY_MANAGEMENT_USER=admin -e WILDFLY_MANAGEMENT_PASSWORD=admin -p 8080:8080 -p 9990:9990 wildflyext/wildfly-camel
and access the admin console like this: http://<IP_ADDRESS>:9990/console
The Hawt.io console is available at: http://<IP_ADDRESS>:8080/hawtio
10.2. OpenShift Origin
Here we follow the instructions on Try Origin. We use the all-in-one VM approach through a Vagrant VirtualBox VM
After having installed Vagrant and VirtualBox, we run:
$ vagrant init openshift/origin-all-in-one
$ vagrant up --provider=virtualbox
...
Successfully started and provisioned VM with 2 cores and 5 G of memory.
To modify the number of cores and/or available memory modify your local Vagrantfile
We can now access the OpenShift console on: https://<IP_ADDRESS>:8443/console
Configured users are:
admin/admin
user/user
This should now also allow us to ssh into the VM
$ vagrant ssh
Last login: Mon Feb 8 09:06:26 2016 from <IP_ADDRESS>
and use the OpenShift command line client.
10.2.1. Client Tools
The client tools are available from the console.
10.2.2. Docker access
The docker deamon running in the Vagrant VM needs be exposed on the network. The easiest way to do this is to use the provided Vagrantfile.
The provided Vagrantfile adds port forwarding, a few docker deamon options and restarts the docker deamon.
config.vm.network "forwarded_port", guest: 8080, host: 8080
config.vm.network "forwarded_port", guest: 8443, host: 8443
config.vm.network "forwarded_port", guest: 2375, host: 2375
[vagrant@localhost ~]$ sudo vi /etc/sysconfig/docker
# Additional startup options for the Docker daemon
OPTIONS="-H tcp://<IP_ADDRESS>:2375 -H unix:///var/run/docker.sock"
[vagrant@localhost ~]$ sudo systemctl restart docker
On you local machine, setup a route to the Vagrant VM
$ sudo cat /etc/hosts
<IP_ADDRESS> origin
and export a few Docker related environment variables for maven builds.
export DOCKER_HOST=tcp://origin:2375
export DOCKER_IP=origin
10.2.3. Create an OpenShift project
Here we run a set of WildFly Camel servers on OpenShift Origin. The target platform is the local OpenShift instance that we created above.
The example architecture consists of a set of three high available (HA) servers running REST endpoints. For server replication and failover we use Kubernetes. Each server runs in a dedicated Pod that we access via Services.
A project allows us to create deployments, pods, services, routes, etc. under our own custom 'wildfly-camel' namespace.
$ oc new-project wildfly-camel
Create a new application
Now, lets create a new appliction from an existing wildfly-camel based image.
$ oc new-app wildflyext/example-camel-rest -l name=camel
and scale it up
$ oc scale --replicas=3 dc example-camel-rest
After a while you should see the pod running
The pods running the JAX-RS endpoints are however not yet exposed to the world.
Exposing the container externally
Now, lets expose the HTTP root context of the running wildlfy server.
$ oc expose service example-camel-rest -l name=camel
From a remote client, you should now be able to access the service like this
Hello Kermit from <IP_ADDRESS>
10.3. Source To Image
WildFly-Camel provides a Source-To-Image (S2I) Docker image which enables you to build reproducable images from source.
10.3.1. Example S2I build
First you’ll need to download and install the S2I tooling from here.
Then you can build and run a Docker image from source. For example, to build the WildFly-Camel CDI quickstart:
$ s2i build https://github.com/wildfly-extras/wildfly-camel-examples.git -r 4.4.0 --context-dir camel-cdi wildflyext/s2i-wildfly-camel:4.4.0 wildfly-camel-example-cdi
$ docker run -p 8080:8080 wildfly-camel-example-cdi
10.3.2. S2I with OpenShift Origin
For convenience, WildFly-Camel provides an OpenShift ImageStream template and an application template which enable you to to perform S2I build and deployments in OpenShift origin.
First add the WildFly-Camel S2I ImageStream.
$ oc apply -f https://raw.githubusercontent.com/wildfly-extras/wildfly-camel/master/docs/guide/sources/wildfly-camel-image-streams.json
Then add the application template.
$ oc apply -f https://raw.githubusercontent.com/wildfly-extras/wildfly-camel/master/docs/guide/sources/wildfly-camel-template.json
When you select 'Add to Project' in the OpenShift web console you should see a new catalog item named 's2i-wildfly-camel'. Choose this option, provide the required template parameters and click 'Create' to start the build process.
You’ll then be able to monitor your application S2I build and deployment in OpenShift. Eventually you should see your application with 1 pod running.
11. Security
Security in WildFly is a broad topic. Both WildFly and Camel have well documented, stadardised methods of securing configuration, endpoints and payloads.
11.1. JAX-RS Security
The following topics explain how to secure JAX-RS endpoints.
11.2. JAX-WS Security
The following topics explain how to secure JAX-WS endpoints.
11.3. JMS Security
The following topics explain how to secure JMS endpoints.
In addition to that, we use Camel’s notion of Route Policies to integrate with the WildFly security system.
11.4. Route Policy
Camel supports the notion of RoutePolicies, which can be used to integrate with the WildFly security system. There are currently two supported scenarios for security integration.
11.4.1. Camel calls into JavaEE
When a camel route calls into a secured JavaEE component, it acts as a client and must provide appropriate credentials associated with the call.
The route can be decorated with a ClientAuthorizationPolicy
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.policy(new ClientAuthorizationPolicy())
.to("ejb:java:module/AnnotatedSLSB?method=doSelected");
}
});
This does actually no do any authentication/authorization as part of the Camel message processing. Instead it associates the credentials that come with the Camel Exchange with the call into the EJB3 layer.
The client that calls the message consumer must provide appropriate credentials in the AUTHENTICATION header like this:
ProducerTemplate producer = camelctx.createProducerTemplate();
Subject subject = new Subject();
subject.getPrincipals().add(new DomainPrincipal(domain));
subject.getPrincipals().add(new EncodedUsernamePasswordPrincipal(username, password));
producer.requestBodyAndHeader("direct:start", "Kermit", Exchange.AUTHENTICATION, subject, String.class);
Authentication and authorization will happen in the JavaEE layer.
11.4.2. Securing a Camel Route
In order to secure a Camel Route, we can associate a DomainAuthorizationPolicy
with the route. This policy requires a successful authentication against the given security domain and authorization for "Role2".
CamelContext camelctx = new DefaultCamelContext();
camelctx.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.policy(new DomainAuthorizationPolicy().roles("Role2"))
.transform(body().prepend("Hello "));
}
});
camelctx.start();
Again, the client that calls the message consumer must provide appropriate credentials in the AUTHENTICATION header like this:
ProducerTemplate producer = camelctx.createProducerTemplate();
Subject subject = new Subject();
subject.getPrincipals().add(new DomainPrincipal(domain));
subject.getPrincipals().add(new EncodedUsernamePasswordPrincipal(username, password));
producer.requestBodyAndHeader("direct:start", "Kermit", Exchange.AUTHENTICATION, subject, String.class);
12. Developer Info
Source
Issues
Jenkins
Downloads
Forums, Lists, IRC
#wildfly-camel channel on irc.freenode.net


Home
Career
Bio
News Feed
Extras
Where in the world is Vin Diesel?
What's new in the Dieselverse?
Box Office: The ‘Fast & Furious’ Franchise Is Just As Profitable As Marvel’s Cinematic Universe
Vin Diesel Grateful For Time Filming Fast And Furious Movies While F9 Is On Hold
Vin Diesel's Car Collection Isn't Just Muscle Cars
‘The Fast and the Furious’: Vin Diesel Net Worth and How He Became Famous
The Fast & Furious Films Ranked From Worst To Best
More News!
Social Media Feeds
"Stay diesel, Ponyboy. Stay diesel." ~ S. E. Hinton


John is an avid fruit grower based in the south of France.
Jónína is an avid fruit grower based on the northpole.
Teddi has been eating fruit’s since he was baby.


@Singleton
public class BookDB
extends java.lang.Object
| Modifier and Type | Field and Description |
|---|---|
protected CommonConstants.BookStatus |
status |
| Constructor and Description |
|---|
BookDB(com.google.firebase.firestore.FirebaseFirestore db) |
| Modifier and Type | Method and Description |
|---|---|
boolean |
deleteBook(java.lang.String bookId)
Attempts to delete a book
|
java.util.ArrayList<Book> |
findBooks(java.lang.String keywords)
Searches book by querying keywords
|
java.util.List<Book> |
getAcceptedWithBorrower(java.lang.String borrower) |
java.util.ArrayList<Book> |
getAllBooks()
gets all books from the DB
|
Book |
getBook(java.lang.String bookID)
Get Book using BookID
|
Book |
getBookById(java.lang.String bid)
Get book by id
|
java.util.Map<Book,java.util.List<BookRequest>> |
getBooksWithRequestList(java.util.List<BookRequest> BookRequestList)
returns book and the bookrequest accompanying it
|
java.util.ArrayList<Book> |
getOwnerAcceptedBooks(java.lang.String owner)
Get books that owner owns that are accepted to borrow
|
java.util.ArrayList<Book> |
getOwnerAvailableBooks(java.lang.String owner)
Get books that owner owns and are available
|
java.util.ArrayList<Book> |
getOwnerBorrowedBooks(java.lang.String owner)
Gets books that are owned by the owner and are borrowed
|
java.util.ArrayList<Book> |
getOwnerBorrowingBooks(java.lang.String username)
This method returns a list of books that user is borrowing from other owners.
|
java.util.ArrayList<Book> |
getOwnerRequestedBooks(java.lang.String owner)
Get owner requested books
|
java.util.ArrayList<Book> |
getUsersOwnedBooks(java.lang.String username)
Attempts to get all books owned by the user
|
Book |
pushBook(Book book)
Attempts to push a book to the database
|
protected CommonConstants.BookStatus status
public java.util.ArrayList<Book> getUsersOwnedBooks(java.lang.String username)
username
- The username of the authenticated usernamepublic boolean deleteBook(java.lang.String bookId)
bookId
- The uuid of the book in firestore.public java.util.List<Book> getAcceptedWithBorrower(java.lang.String borrower)
public Book pushBook(Book book)
book
- The book object the pushpublic java.util.ArrayList<Book> findBooks(java.lang.String keywords)
keywords
- keywords to search forpublic Book getBook(java.lang.String bookID)
bookID
- id of the bookpublic java.util.ArrayList<Book> getAllBooks()
public java.util.ArrayList<Book> getOwnerRequestedBooks(java.lang.String owner)
owner
- id of the ownerpublic java.util.ArrayList<Book> getOwnerBorrowedBooks(java.lang.String owner)
owner
- id of the ownerpublic java.util.ArrayList<Book> getOwnerAcceptedBooks(java.lang.String owner)
owner
- id of the ownerpublic java.util.ArrayList<Book> getOwnerAvailableBooks(java.lang.String owner)
owner
- id of the ownerpublic Book getBookById(java.lang.String bid)
bid
- id of the bookpublic java.util.Map<Book,java.util.List<BookRequest>> getBooksWithRequestList(java.util.List<BookRequest> BookRequestList)
BookRequestList
- List of bookspublic java.util.ArrayList<Book> getOwnerBorrowingBooks(java.lang.String username)
username
- id of the user


Item 3.
Navigate in and Edit the Document:
Delete last character backspace
-
To move around the document without speech thumb-keys
Move forward one display advance thumb-key
Move backward one display back thumb-key
Move to top of document space + dots123
Move to end of document space + dots456
Move cursor within display cursor routing keys
At the cursor, you insert text by writing.
Delete the character tot he left of the cursor backspace