Apache Camel: ActiveMQ
Recently we saw how to make an integration with WSO2 and ActiveMQ, which you can see here. This time we will see the same example but with Apache Camel and Spring Boot. Where we will also add the complexity of using queues that require authentication. For the example we will use the following versions:
- Apache Camel 3.11.0
- Spring Boot 2.5.1
- Active MQ 5.16.2
Docker Compose and configurations
activemq:
image: rmohr/activemq
mem_limit: 1G
hostname: sandbox-activemq
container_name: sandbox-activemq
ports:
- 8161:8161
- 61616:61616
volumes:
- ./activemq.xml:/opt/apache-activemq-5.15.6/conf/activemq.xml
On this configuration we can indicate the following:
- Port 8161 is the administration port and the one that will allow us to access the management console through the URL http://localhost:8161/admin/index.jsp.
- Port 61616 is the TCP port used for communication with ActiveMQ.
- The activemq.xml file, which can be found inside the same image, is the file that will allow us to configure ActiveMQ’s behavior. Among other things, the management of the users that have access to the queues or topics.
If we want authentication to make use of the queues we must include the following piece of code in the activemq.xml file:
With this code we are configuring the following:
- simpleAuthenticationPlugin: It allows us to manually configure users, passwords and the groups to which they are associated. The other option to secure the access, more professional, would be through the JAAS plugin.
- anonymousAccessAllowed: Allows us to indicate that we will also allow anonymous access. This way we can have some queues secured and others not. The user and group associated by default is anonymous.
- authorizationEntries: It is the configuration that we want to apply to the queues in a generic or specific way. In this configuration we allow:
- Create, write or read in the queue ‘privateQueue’ only to the administrator users.
- Create, write or read from any queue. The symbol ‘>’ indicates ‘all’. This configuration is associated to the lower one, which allows the creation of advisory channels to any user, ‘ActiveMQ.Advisory.>’.
To finish the configuration, regarding Apache Camel/Spring Boot, as we use the camel-activemq-starter dependency, we will not need to configure anything special. Simply what is the broker’s communication path:
camel.component.activemq.brokerUrl=tcp://localhost:61616
Send messages
Now that we have it correctly configured we can proceed to create the resource that allows us to send messages. The idea is to create a REST service that stores the information it receives in the ActiveMQ queue.
As we can see in the configuration, we need to tell Apache not to wait for a response, since it will not receive any from ActiveMQ. This can be done through the configuration ‘exchangePattern=InOnly’. Otherwise, in each call, we would receive an error message similar to the following:
org.apache.camel.ExchangeTimedOutException: The OUT message was not received
within: 20000 millis due reply message with correlationID
Now if we were to make the following invocation we could send a message to the public queue.
curl --location --request POST 'http://localhost:8080/camel/activemq/public' \
--header 'Content-Type: application/json' \
--data-raw '{"prop":"value"}'
And for the private queue it will be a bit more complicated. First we create a connection of type ActiveMQConnectionFactory that allows to configure a user and password. By default it uses SingleConnectionFactory and it does not support authentication.
@Bean
private ConnectionFactory activeMQConnectionFactory() {
return new ActiveMQConnectionFactory();
}
And second, it will be to indicate in the connection string the user and password. If we wanted it in a general way we could configure it at the level of the application.properties file. But in this case we only want to apply it to a route.
Receive messages
Now we will see how to make an API resource that allows us to read from the queue. This is the simplest part, because it will be simply to change the method to that allows us to produce, for the method from that allows us to consume. The configuration will be the same.
Security known errors
To avoid problems when you make any operation through the Admin Console, with the following message:
SecurityException: User name [system] or password is invalid.
You need to include the System user in the SystemAuthenticationPlugin:
<authenticationUser username="system" password="manager" groups="admins,publishers,consumers"/>
And that’s all, I hope it has been useful. And as always, you can see all the code here.