Routing Camel messages to Artemis embedded in WildFly

This is the second tutorial about Camel 3. In the first one (Getting started with Camel 3) we have discussed how to set up a basic Camel 3 projects and run a simple demo with it. Now we will show how to use the messasing API to connect to a remote ArtemisMQ embedded in a WildFly distribution.

Assumed that you have already set up a basic Camel project, let’s create the Route class which does the work to send JMS messages to the Queue named “demoQueue”:

package com.mastertheboss.camel;

import org.apache.camel.builder.RouteBuilder;

public class MyJMSRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("timer:foo?period=3s")
                .transform(constant("Hello World"))
                .to("jms:queue:demoQueue");

        from("jms:queue:demoQueue").to("log:demoQueue");
    }
}

The RouteBuilder class will send JMS messages containing “Hello World” every 3 seconds.

Now the Camel Main class to start the route:

package com.mastertheboss.camel;

import org.apache.camel.main.Main;

/**
 * A Camel Application
 */
public class MainApp {

    /**
     * A main() so we can easily run these routing rules in our IDE
     */
    public static void main(String... args) throws Exception {
        // use Camels Main class
        Main main = new Main();

        // and add the routes (you can specify multiple classes)
        main.addRouteBuilder(MyJMSRouteBuilder.class);
        // now keep the application running until the JVM is terminated (ctrl + c or sigterm)
        main.run(args);


    }

}

That’s all. Within our application.properties we will setup JMS component with connection to ActiveMQ Artemis broker:

camel.main.name = CamelJMSHelloWorld

# properties used in the route
myCron = 0/2 * * * * ?

# setup JMS component with connection to ActiveMQ Artemis broker
camel.component.jms.connection-factory.brokerURL=tcp://localhost:61616
camel.component.jms.connection-factory.target-connection-factory.user=guest
camel.component.jms.connection-factory.target-connection-factory.password=guest

Now let’s move to the WildFly side. Start by creating a JMS remote acceptor which is bound to port 61616:

/socket-binding-group=standard-sockets/socket-binding=artemis-server:add(port=61616)

/subsystem=messaging-activemq/server=default/remote-acceptor=artemis-acceptor:add(socket-binding=artemis-server)

Within the messaging susbsytem you should be able to see:

        <subsystem xmlns="urn:jboss:domain:messaging-activemq:8.0">
            <server name="default">
                <!-- default configuration here -->
               
                  <remote-acceptor name="artemis-acceptor" socket-binding="artemis-server"/>
            </server>
        </subsystem>

In turn, the remote-acceptor references a socket-binding bound to port 61616:

<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
	<socket-binding name="artemis-server" port="61616"/>
    <!-- Other bindings --> 
</socket-binding-group>

Next, let’s create as well the JMS Queue named demoQueue from the CLI:

jms-queue add --queue-address=demoQueue --entries=queues/demoQueue

Finally, we need to create an user which is allowed to connect to the JMS server. Within our Camel configuration we have already configured it to be guest/guest therefore we will add this user with the shell script add-user.sh:

$ ./add-user.sh 

What type of user do you wish to add? 
 a) Management User (mgmt-users.properties) 
 b) Application User (application-users.properties)
(a): b

Enter the details of the new user to add.
Using realm 'ApplicationRealm' as discovered from the existing property files.
Username : guest
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should be different from the username
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
Password : 
WFLYDM0098: The password should be different from the username
Are you sure you want to use the password entered yes/no? yes
Re-enter Password : 
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]: guest
About to add user 'guest' for realm 'ApplicationRealm'
Is this correct yes/no? yes
Added user 'guest' to file '/home/francesco/jboss/wildfly-18.0.1.Final/standalone/configuration/application-users.properties'
Added user 'guest' to file '/home/francesco/jboss/wildfly-18.0.1.Final/domain/configuration/application-users.properties'
Added user 'guest' with groups guest to file '/home/francesco/jboss/wildfly-18.0.1.Final/standalone/configuration/application-roles.properties'
Added user 'guest' with groups guest to file '/home/francesco/jboss/wildfly-18.0.1.Final/domain/configuration/application-roles.properties'
Is this new user going to be used for one AS process to connect to another AS process? 
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes

We are done! On before launching the Camel Main, we need to generate autowiring for the dependencies found in our project, so we will run:

mvn camel-main:generate

Now we can finally run the Camel main with:

mvn exec:java

You should be able to see, from the CLI or Web console that messages are being received in the Queue demoQueue:

/subsystem=messaging-activemq/server=default/jms-queue=demoQueue:read-resource(include-runtime=true)
{
    "outcome" => "success",
    "result" => {
        "consumer-count" => 1,
        "dead-letter-address" => "jms.queue.DLQ",
        "delivering-count" => 0,
        "durable" => true,
        "entries" => ["queues/demoQueue"],
        "expiry-address" => "jms.queue.ExpiryQueue",
        "legacy-entries" => undefined,
        "message-count" => 0L,
        "messages-added" => 24L,
        "paused" => false,
        "queue-address" => "jms.queue.demoQueue",
        "scheduled-count" => 0L,
        "selector" => undefined,
        "temporary" => false
    }
}