5.2. Examples of JBoss Fuse on EAP

This section includes the working examples that demonstrate various features of JBoss on Fuse EAP. These examples will help you get started with the EAP Camel subsystem.
Note
You can access the $JBOSS_HOME/quickstarts/camel directory to view the full source code of all the examples.
To run the given examples, ensure that you install the following on your machine:
  • Maven 3.2.3 or greater
  • Java 1.7 or greater
  • Red Hat JBoss Fuse 6.3
  • Red Hat JBoss EAP 6.4

5.2.1. Camel ActiveMQ

The following example describes how to use the camel-activemq component with JBoss Fuse on EAP, to produce and consume JMS messages.
In this example, a camel route consumes files from the ${JBOSS_HOME}/standalone/data/orders directory and place the content to an external ActiveMQ JMS queue. A second route consumes messages from the OrdersQueue and then via a content based router, it sorts the directory of each country that are located within the $JBOSS_HOME/standalone/data/orders/processed directory.
Note
The CLI script automatically configure the ActiveMQ resource adapter. These scripts are located within the src/main/resources/cli directory.

5.2.1.1. Running the Application

Before you start running the application, make sure that the following are installed on your machine:
  • Maven 3.2.3 or greater
  • JBoss Fuse on EAP
  • An ActiveMQ broker

Procedure 5.1. To run the application

Perform the following steps:
  1. Start the application server in standalone mode.
    ${JBOSS_HOME}/bin/standalone.sh -c standalone-full.xml
    
  2. Run the following command to build and deploy the project.
    mvn install -Pdeploy
    

5.2.1.2. Configuring ActiveMQ

Here are the details to configure the ActiveMQ component:
@Startup
@CamelAware
@ApplicationScoped
public class ActiveMQRouteBuilder extends RouteBuilder {

    /**
     * Inject the ActiveMQConnectionFactory that has been configured through the ActiveMQ Resource Adapter
     */
    @Resource(mappedName = "java:/ActiveMQConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Override
    public void configure() throws Exception {

        /**
         * Configure the ActiveMQ component
         */
        ActiveMQComponent activeMQComponent = ActiveMQComponent.activeMQComponent();
        activeMQComponent.setConnectionFactory(connectionFactory);
        getContext().addComponent("activemq", activeMQComponent);

        /**
         * This route reads files placed within $JBOSS_HOME/standalone/data/orders
         * and places them to ActiveMQ queue 'ordersQueue'
         */
        from("file://{{jboss.server.data.dir}}/orders")
        .convertBodyTo(String.class)
        // Remove headers to ensure we end up with unique file names being generated in the next route
        .removeHeaders("*")
        .to("activemq:queue:OrdersQueue");

        /**
         * This route consumes messages from the 'ordersQueue'. Then, based on the
         * message payload XML content it uses a content based router to output
         * orders into appropriate country directories
         */
        from("activemq:queue:OrdersQueue")
            .choice()
                .when(xpath("/order/customer/country = 'UK'"))
                    .log("Sending order ${file:name} to the UK")
                    .to("file:{{jboss.server.data.dir}}/orders/processed/UK")
                .when(xpath("/order/customer/country = 'US'"))
                    .log("Sending order ${file:name} to the US")
                    .to("file:{{jboss.server.data.dir}}/orders/processed/US")
                .otherwise()
                    .log("Sending order ${file:name} to another country")
                    .to("file://{{jboss.server.data.dir}}/orders/processed/Others");
    }
    }

5.2.1.3. Undeploy the Application

Run the following command to undeploy the application:
mvn clean -Pdeploy

It removes the ActiveMQ resource adapter configuration. However, you need to restart the application after you execute the undeploy command.

5.2.2. Camel CDI

The following example describes how to use the camel-cdi component with JBoss Fuse on EAP, to integrate CDI beans with camel routes.
In this example, a camel route takes a message payload from a servlet HTTP GET request and passes it to the direct endpoint. However, you can pass the payload to a Camel CDI bean invocation to produce a message response. It displays the message response on the web browser page.

5.2.2.1. Running the Application

Before you start running the application, make sure that the following are installed on your machine:
  • Maven 3.2.3 or greater
  • JBoss Fuse on EAP

Procedure 5.2. To run the application

Perform the following steps:
  1. Start the application server in standalone mode.
    ${JBOSS_HOME}/bin/standalone.sh -c standalone-full.xml
    
  2. Run the following command to build and deploy the project.
    mvn install -Pdeploy
    

5.2.2.2. Configuring Camel CDI

Here are the details to configure the camel-cdi component:
@Startup
@CamelAware
@ApplicationScoped
public class MyRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
    	from("direct:start").bean("helloBean");
    }
}

@SuppressWarnings("serial")
@WebServlet(name = "HttpServiceServlet", urlPatterns = { "/*" }, loadOnStartup = 1)
public class SimpleServlet extends HttpServlet
{
	@Inject
	private CamelContext camelctx;

    @Override
	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        String name = req.getParameter("name");
    	ServletOutputStream out = res.getOutputStream();
        ProducerTemplate producer = camelctx.createProducerTemplate();
        String result = producer.requestBody("direct:start", name, String.class);
    	out.print(result);
    }
}

5.2.2.3. Undeploy the Application

Run the following command to undeploy the application:
mvn clean -Pdeploy

5.2.3. Camel JMS

The following example describes how to use the camel-jms component with JBoss Fuse on EAP to produce and consume JMS messages.
In this example, a Camel route consumes files from the ${JBOSS_HOME}/standalone/data/orders directory and place the content in the OrdersQueue. A second route consumes messages from the OrdersQueue and through a content based router.

5.2.3.1. Running the Application

Before you start running the application, make sure that the following are installed on your machine:
  • Maven 3.2.3 or greater
  • JBoss Fuse on EAP

Procedure 5.3. To run the application

Perform the following steps:
  1. Start the application server in standalone mode.
    ${JBOSS_HOME}/bin/standalone.sh -c standalone-full.xml
    
  2. Run the following command to build and deploy the project.
    mvn install -Pdeploy
    

5.2.3.2. Configuring Camel JMS

Here are the details to configure the camel-jms component.
@Startup
@CamelAware
@ApplicationScoped
public class JmsRouteBuilder extends RouteBuilder {

    @Resource(mappedName = "java:/ConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Override
    public void configure() throws Exception {
        /**
         * Configure the JMSComponent to use the connection factory
         * injected into this class
         */
        JmsComponent component = new JmsComponent();
        component.setConnectionFactory(connectionFactory);

        getContext().addComponent("jms", component);

        /**
         * This route reads files placed within $JBOSS_HOME/standalone/data/orders
         * and places them onto JMS queue 'ordersQueue' within the WildFly
         * internal HornetQ broker.
         */
        from("file://{{jboss.server.data.dir}}/orders")
        .convertBodyTo(String.class)
        // Remove headers to ensure we end up with unique file names being generated in the next route
        .removeHeaders("*")
        .to("jms:queue:OrdersQueue");

        /**
         * This route consumes messages from the 'ordersQueue'. Then, based on the
         * message payload XML content it uses a content based router to output
         * orders into appropriate country directories
         */
        from("jms:queue:OrdersQueue")
            .choice()
                .when(xpath("/order/customer/country = 'UK'"))
                    .log("Sending order ${file:name} to the UK")
                    .to("file:{{jboss.server.data.dir}}/orders/processed/UK")
                .when(xpath("/order/customer/country = 'US'"))
                    .log("Sending order ${file:name} to the US")
                    .to("file:{{jboss.server.data.dir}}/orders/processed/US")
                .otherwise()
                    .log("Sending order ${file:name} to another country")
                    .to("file://{{jboss.server.data.dir}}/orders/processed/others");
    }
}

5.2.3.3. Undeploy the Application

Run the following command to undeploy the application:
mvn clean -Pdeploy

5.2.4. Camel JPA

The following example describes how to use the camel-jpa component with JBoss Fuse on EAP to persist entities to the in-memory database.
In this example, a camel route consumes XML files from the ${JBOSS_HOME}/standalone/data/customers directory. Camel then uses JAXB to unmarshal the data to a Customer entity. However, the entity is then passed to the JPA endpoint and is persisted to the customer database.

5.2.4.1. Running the Application

Before you start running the application, make sure that the following are installed on your machine:
  • Maven 3.2.3 or greater
  • JBoss Fuse on EAP

Procedure 5.4. To run the application

Perform the following steps:
  1. Start the application server in standalone mode.
    ${JBOSS_HOME}/bin/standalone.sh -c standalone-full.xml
    
  2. Run the following command to build and deploy the project.
    mvn install -Pdeploy
    

5.2.4.2. Configuring Camel JPA

Here are the details to configure the camel-jpa component.
@Startup
@CamelAware
@ApplicationScoped
public class JpaRouteBuilder extends RouteBuilder {

    @Inject
    private EntityManager em;

    @Inject
    UserTransaction userTransaction;

    @Override
    public void configure() throws Exception {
        // Configure our JaxbDataFormat to point at our 'model' package
        JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
        jaxbDataFormat.setContextPath(Customer.class.getPackage().getName());

        EntityManagerFactory entityManagerFactory = em.getEntityManagerFactory();

        // Configure a JtaTransactionManager by looking up the JBoss transaction manager from JNDI
        JtaTransactionManager transactionManager = new JtaTransactionManager(userTransaction);
        transactionManager.afterPropertiesSet();

        // Configure the JPA endpoint to use the correct EntityManagerFactory and JtaTransactionManager
        JpaEndpoint jpaEndpoint = new JpaEndpoint();
        jpaEndpoint.setCamelContext(getContext());
        jpaEndpoint.setEntityType(Customer.class);
        jpaEndpoint.setEntityManagerFactory(entityManagerFactory);
        jpaEndpoint.setTransactionManager(transactionManager);

        /*
         *  Simple route to consume customer record files from directory input/customers,
         *  unmarshall XML file content to a Customer entity and then use the JPA endpoint
         *  to persist the it to the 'ExampleDS' datasource (see standalone.camel.xml for datasource config).
         */
        from("file://{{jboss.server.data.dir}}/customers")
                .unmarshal(jaxbDataFormat)
                .to(jpaEndpoint)
                .to("log:input?showAll=true");
    }
}


public class CustomerRepository {
    
    @Inject
    private EntityManager em;

    /**
     * Find all customer records
     *
     * @return A list of customers
     */
    public List<Customer> findAllCustomers() {

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Customer> query = criteriaBuilder.createQuery(Customer.class);
        query.select(query.from(Customer.class));

        return em.createQuery(query).getResultList();
    }
}

5.2.4.3. Undeploy the Application

Run the following command to undeploy the application:
mvn clean -Pdeploy

5.2.5. Camel Mail

The following example describes how to use the camel-mail component with JBoss Fuse on EAP to send and receive email.
In this example, you can configure a local mail server on your machine. This eliminates the need to use any external mail services. You can access the src/main/resources/cli directory to see the EAP mail subsystem configuration.
Note
Here the mail session used is bound to JNDI at the java:jboss/mail/ location. You can configure the server entries for SMTP and POP3 protocols.

5.2.5.1. Running the Application

Before you start running the application, make sure that the following are installed on your machine:
  • Maven 3.2.3 or greater
  • JBoss Fuse on EAP

Procedure 5.5. To run the application

Perform the following steps:
  1. Start the application server in standalone mode.
    ${JBOSS_HOME}/bin/standalone.sh -c standalone-full.xml
    
  2. Run the following command to build and deploy the project.
    mvn install -Pdeploy
    
Note
If you want to deploy the application multiple times, ensure that you run the undeploy command and restart the application server.

5.2.5.2. Configuring Camel Mail

Here are the configurations details to configure the camel-mail component.
public class MailSessionProducer {
    @Resource(lookup = "java:jboss/mail/greenmail")
    private Session mailSession;

    @Produces
    @Named
    public Session getMailSession() {
        return mailSession;
    }
}
@Startup
@CamelAware
@ApplicationScoped
public class MailRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        // Configure routes and endpoints to send and receive email over SMTP and POP3
        from("direct:sendmail").to("smtp://localhost:10025?session=#mailSession");

        from("pop3://user2@localhost:10110?consumer.delay=30000&session=#mailSession").to("log:emails?showAll=true&multiline=true");
    }
}

5.2.5.3. Undeploy the Application

Run the following command to undeploy the application:
mvn clean -Pdeploy

5.2.6. Camel REST

The following example describes how to write the JAX-RS REST routes with JBoss Fuse on EAP.
It includes two methods of implementing Camel REST consumers. Requests made to paths under the /example-camel-rest/camel are handled by the Camel REST DSL and requests made to paths >/example-camel-rest/rest are handled by the EAP JAX-RS subsystem along with the CamelProxy.

5.2.6.1. Running the Application

Before you start running the application, make sure that the following are installed on your machine:
  • Maven 3.2.3 or greater
  • JBoss Fuse on EAP

Procedure 5.6. To run the application

Perform the following steps:
  1. Start the application server in standalone mode.
    ${JBOSS_HOME}/bin/standalone.sh -c standalone-full.xml
    
  2. Run the following command to build and deploy the project.
    mvn install -Pdeploy
    

5.2.6.2. Configuring Camel REST

Here are the configurations details to configure the Camel REST routes.
@Startup
@CamelAware
@ApplicationScoped
public class RestConsumerRouteBuilder extends RouteBuilder {

    /**
     * Inject a service for interacting with the EAP exampleDS in-memory database.
     */
    @Inject
    private CustomerRepository customerRepository;

    @Override
    public void configure() throws Exception {
        /**
         * Configure the Camel REST DSL to use the camel-servlet component for handling HTTP requests.
         *
         * Whenever a POST request is made to /customer it is accompanied with a JSON string representation
         * of a Customer object. Note that the binding mode is set to RestBindingMode.json. This will enable
         * Camel to unmarshal JSON to the desired object type.
         *
         * Note that the contextPath setting below has no effect on how the application server handles HTTP traffic.
         * The context root and required servlet mappings are configured in WEB-INF/jboss-web.xml and WEB-INF/web.xml.
         *
         */
        restConfiguration().component("servlet").contextPath("/camel-example-rest/camel").port(8080).bindingMode(RestBindingMode.json);

        /**
         * Handles requests to a base URL of /camel-example-rest/camel/customer
         */
        rest("/customer")
            /**
             * Handles GET requests to URLs such as /camel-example-rest/camel/customer/1
             */
            .get("/{id}")
                /**
                 * Marshalls the response to JSON
                 */
                .produces(MediaType.APPLICATION_JSON)
                .to("direct:readCustomer")
            /**
             * Handles POST requests to /camel-example-rest/camel/customer
             */
            .post()
                /**
                 * Unmarshalls the JSON data sent with the POST request to a Customer object.
                 */
                .type(Customer.class)
                .to("direct:createCustomer");

        /**
         * This route returns a JSON representation of any customers matching the id
         * that was sent with the GET request.
         *
         * If no customer was found, an HTTP 404 response code is returned to the calling client.
         */
        from("direct:readCustomer")
            .bean(customerRepository, "readCustomer(${header.id})")
            .choice()
                .when(simple("${body} == null"))
                    .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(404));

        /**
         * This route handles persistence of new customers.
         */
        from("direct:createCustomer")
            .bean(customerRepository, "createCustomer");


        /**
         * This route handles REST requests that have been made to the RESTful services defined within
         * CustomerServiceImpl.
         *
         * These services are running under the WildFly RESTEasy JAX-RS subsystem. A CamelProxy proxies the direct:rest
         * route so that requests can be handled from within a Camel route.
         */
        from("direct:rest")
            .process(new Processor() {
                @Override
                public void process(Exchange exchange) throws Exception {
                    /**
                     * Retrieve the message payload. Since we are using camel-proxy to proxy the direct:rest
                     * endpoint the payload will be of type BeanInvocation.
                     */
                    BeanInvocation beanInvocation = exchange.getIn().getBody(BeanInvocation.class);

                    /**
                     * Get the invoked REST service method name and build a response to send
                     * back to the client.
                     */
                    String methodName = beanInvocation.getMethod().getName();

                    if (methodName.equals("getCustomers")) {
                        /**
                         * Retrieve all customers and send back a JSON response
                         */
                        List<Customer> customers = customerRepository.findAllCustomers();
                        exchange.getOut().setBody(Response.ok(customers).build());
                    } else if(methodName.equals("updateCustomer")) {
                        /**
                         * Get the customer that was sent on this method call
                         */
                        Customer updatedCustomer = (Customer) beanInvocation.getArgs()[0];
                        Customer existingCustomer = customerRepository.readCustomer(updatedCustomer.getId());

                        if(existingCustomer != null){
                            if(existingCustomer.equals(updatedCustomer)) {
                                /**
                                 * Nothing to be updated so return HTTP 304 - Not Modified.
                                 */
                                exchange.getOut().setBody(Response.notModified().build());
                            } else {
                                customerRepository.updateCustomer(updatedCustomer);
                                exchange.getOut().setBody(Response.ok().build());
                            }
                        } else {
                            /**
                             * No customer exists for the provided id, so return HTTP 404 - Not Found.
                             */
                            exchange.getOut().setBody(Response.status(Response.Status.NOT_FOUND).build());
                        }
                    } else if(methodName.equals("deleteCustomer")) {
                        Long customerId = (Long) beanInvocation.getArgs()[0];

                        Customer customer = customerRepository.readCustomer(customerId);
                        if(customer != null) {
                            customerRepository.deleteCustomer(customerId);
                            exchange.getOut().setBody(Response.ok().build());
                        } else {
                            /**
                             * No customer exists for the provided id, so return HTTP 404 - Not Found.
                             */
                            exchange.getOut().setBody(Response.status(Response.Status.NOT_FOUND).build());
                        }
                    } else if(methodName.equals("deleteCustomers")) {
                        customerRepository.deleteCustomers();

                        /**
                         * Return HTTP status OK.
                         */
                        exchange.getOut().setBody(Response.ok().build());
                    }
                }
            });
    }
}
@Startup
@CamelAware
@ApplicationScoped
public class RestProducerRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        /**
         * This route demonstrates a JAX-RS producer using the camel-restlet component.
         *
         * Every 30 seconds, a call is made to the REST API for retrieving all customers at
         * the URL http://localhost:8080/example-camel-rest/rest/customer.
         *
         * The results of the REST service call are written to a file at:
         *
         * $JBOSS_HOME/standalone/data/customer-records/customers.json
         */
        from("timer://outputCustomers?period=30000")
        .to("restlet://http://localhost:8080/example-camel-rest/rest/customer")
        .choice()
            .when(simple("${header.CamelHttpResponseCode} == 200"))
                .log("Updating customers.json")
                .setHeader(Exchange.FILE_NAME, constant("customers.json"))
                .to("file:{{jboss.server.data.dir}}/customer-records/")
            .otherwise()
                .log("REST request failed. HTTP status ${header.CamelHttpResponseCode}");
    }
}

5.2.6.3. Undeploy the Application

Run the following command to undeploy the application:
mvn clean -Pdeploy

5.2.7. Camel Transacted JMS

The following example describes how to use the camel-jms component with JBoss Fuse on EAP to produce and consume JMS messages in a transacted session.
In this example, a camel route consumes files from the ${JBOSS_HOME}/standalone/data/orders directory and place the content in the OrdersQueue. A second route consumes messages from the OrdersQueue, converts the message body to the Order entity and persists it.

5.2.7.1. Running the Application

Before you start running the application, make sure that the following are installed on your machine:
  • Maven 3.2.3 or greater
  • JBoss Fuse on EAP

Procedure 5.7. To run the application

Perform the following steps:
  1. Start the application server in standalone mode.
    ${JBOSS_HOME}/bin/standalone.sh -c standalone-full.xml
    
  2. Run the following command to build and deploy the project.
    mvn install -Pdeploy
    
  3. When the server starts, navigate to the example-camel-transacted-jms/orders directory.
The application displays the Orders Received page. It includes the list of processed orders.

5.2.7.2. Configuring Transacted JMS

Here are the details to configure the camel-jms component in a transacted session.
@Startup
@CamelAware
@ApplicationScoped
public class JmsRouteBuilder extends RouteBuilder {

    /**
     * Inject the resources required to configure the JMS and JPA Camel
     * components. The JPA EntityManager, JMS TransactionManager and a JMS
     * ConnectionFactory bound to the JNDI name java:/JmsXA
     */
    @Inject
    private EntityManager entityManager;

    @Inject
    private JmsTransactionManager transactionManager;

    @Resource(mappedName = "java:/JmsXA")
    private ConnectionFactory connectionFactory;

    @Override
    public void configure() throws Exception {
        /**
         * Create an instance of the Camel JmsComponent and configure it to support JMS
         * transactions.
         */
        JmsComponent jmsComponent = JmsComponent.jmsComponentTransacted(connectionFactory, transactionManager);
        getContext().addComponent("jms", jmsComponent);

        /**
         * Create an instance of the Camel JpaComponent and configure it to support transactions.
         */
        JpaComponent jpaComponent = new JpaComponent();
        jpaComponent.setEntityManagerFactory(entityManager.getEntityManagerFactory());
        jpaComponent.setTransactionManager(transactionManager);
        getContext().addComponent("jpa", jpaComponent);

        /**
         * Configure JAXB so that it can discover model classes.
         */
        JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
        jaxbDataFormat.setContextPath(Order.class.getPackage().getName());

        /**
         * Configure a simple dead letter strategy. Whenever an IllegalStateException
         * is encountered this takes care of rolling back the JMS and JPA transactions. The
         * problem message is sent to the WildFly dead letter JMS queue (DLQ).
         */
        onException(IllegalStateException.class)
            .maximumRedeliveries(1)
            .handled(true)
            .to("jms:queue:DLQ")
            .markRollbackOnly();

        /**
         * This route consumes XML files from $JBOSS_HOME/standalone/data/orders and sends
         * the file content to JMS destination OrdersQueue.
         */
        from("file:{{jboss.server.data.dir}}/orders")
            .transacted()
                .to("jms:queue:OrdersQueue");

        /**
         * This route consumes messages from JMS destination OrdersQueue, unmarshalls the XML
         * message body using JAXB to an Order entity object. The order is then sent to the JPA
         * endpoint for persisting within an in-memory database.
         *
         * Whenever an order quantity greater than 10 is encountered, the route throws an IllegalStateException
         * which forces the JMS / JPA transaction to be rolled back and the message to be delivered to the dead letter
         * queue.
         */
        from("jms:queue:OrdersQueue")
                .unmarshal(jaxbDataFormat)
                .to("jpa:Order")
                .choice()
                .when(simple("${body.quantity} > 10"))
                    .log("Order quantity is greater than 10 - rolling back transaction!")
                    .throwException(new IllegalStateException())
                .otherwise()
                   .log("Order processed successfully");
    }
}

5.2.7.3. Undeploy the Application

Run the following command to undeploy the application:
mvn clean -Pdeploy