-
Notifications
You must be signed in to change notification settings - Fork 59
JMS with Spring Boot & Apache Camel
Source Folder: jms-camel
Tech Stack:
- Spring Boot
- Apache ActiveMQ
- Apache Camel
- log4j2 (slf4j impl)
- project lombok
This is a ready-to-use Maven Java project template with the above tech stack.
- Sending & Receiving messages from a message queue
- Implementing Camel Routes
Let’s start with JMS. What is JMS and what is it used for?
JMS is simply a Java messaging API for software components and it is mainly used for sending/receiving messages from one application to/from another.
- JMS is asynchronous. Clients don’t need to ask whether there is a message that they are subscribed to. They will be notified instead when a message is ready.
- JMS is reliable since it provides “guaranteed message delivery”.
- Point to Point Model
- Publish/Subscribe Model
With P2P model, messages sent by the “provider” is put into a named queue. A client listening that specific queue receives the message automatically. (Note that the code provided in this story is an example of this model)
With Pub/Sub model on the other hand, the provider sends messages to a specific “topic” (careful, not queue this time) and all subscribers which are registered to that specific “topic” automatically receive those messages.
MoMs are 3rd party products (or platform or middleware) that enable different software components to communicate via message sharing.
JMS is one standard to communicate with MoMs that support JMS (like Apache ActiveMQ).
Camel is an open-source integration framework that has several components for guess what… “integration” (implementations of Enterprise Integration Patterns). By defining very simple routes we can integrate different software components and make them communicate with each other.
See the "/java/jms" for a working example.
This example shows how to create a Camel route and receive messages from a specific ActiveMQ queue using Spring-Boot and JMS. Therefore, you need to install Apache ActiveMQ before testing this code on your own (http://activemq.apache.org/download.html)
Here is the POM.xml and required dependencies:
<project ...
<groupId>...
<artifactId>...
<version>...
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.22.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>2.22.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>
Below is the JMS configuration
import org.apache.camel.component.jms.JmsComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.connection.JmsTransactionManager;
import javax.jms.ConnectionFactory;
@Configuration
public class JmsConfig {
@Bean
public JmsTransactionManager jmsTransactionManager(final ConnectionFactory connectionFactory) {
JmsTransactionManager jmsTransactionManager = new JmsTransactionManager();
jmsTransactionManager.setConnectionFactory(connectionFactory);
return jmsTransactionManager;
}
@Bean
public JmsComponent jmsComponent(final ConnectionFactory connectionFactory,
final JmsTransactionManager jmsTransactionManager) {
JmsComponent jmsComponent = JmsComponent.jmsComponentTransacted(connectionFactory, jmsTransactionManager);
return jmsComponent;
}
}
And here is a sample Camel Route:
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class JmsSampleRouter extends RouteBuilder {
@Override
public void configure() throws Exception {
System.out.println("Configuring route");
from("{{input.queue}}")
.log(LoggingLevel.DEBUG, log, "New message received")
.process(exchange -> {
String convertedMessage = exchange.getMessage().getBody() + " is converted";
exchange.getMessage().setBody(convertedMessage);
})
.to("{{output.queue}}")
.log(LoggingLevel.DEBUG, log, "Message sent to the other queue")
.end();
}
}
Finally, below is the required configuration:
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=10
max.concurrent.consumers=2
input.queue=jms:MYINPUTQUEUE
output.queue=jms:MYPUTPUTQUEUE
Spring-boot has several ActiveMQ configurations by default which we can override by defining them in our own “application.properties” file. For example, we can enable pooled connection to improve performance with the following two configuration properties:
spring.activemq.pool.enabled=true
spring.activemq.pool.max-connections=100
“input.queue” and “output.queue” on the other hand are my own configuration properties which have corresponding queue names that I’ve created in my ActiveMQ.
Now, let’s read the route again from the start:
- Whenever a message is received from the queue named “MyInputQueue” (the value of “{{input.queue}}”) write a log “New message received”
- Then, process the message and set the body of the message to the converted message.
- Send the message to the “MyOutputQueue” (value of “{{output.queue}}”)
- Finally, write a log “Message sent to the output queue”
That’s it. I hope this helps you with the basics.
- Home
- JPA Specification
- JMS with Spring Boot
- JMS with Spring Boot & Apache Camel
- Caching with Spring Boot & Redis
- Netflix Eureka with Spring Boot
- Netflix Hystrix & Eureka with Redis Cache
- Netflix Zuul
- Authentication Types
- Separating Unit & Integration Tests Execution Phases with Maven
- Basic CSRF Attack Simulation & Protection
- Spring Batch
- Dagger
- Concurrency with Java
- Swagger2 with Spring Boot