Spring Boot RabbitTemplate Example Without Bean/Component Annotations

Cem Yasar
2 min readAug 28, 2021

Hi,

In this story I will share an example of RabbitMQ usage on Spring Boot environment without using “bean” annotations. In the internet, you can see many RabbitTemplate examples, but all of them are implemented in same manner, by using “bean” annotations. The main purpose is to start consumer and producer applications seperately within same Spring project. As you know, in a Spring Boot application, all bean,component,configuration annotations are scanned and initialized at startup and we do not want this behaviour in this example.

This example has been implemented by Visual Studio Code, so to give command-line arguments, you can use launch.json configuration file.

Here is producer class, SpringTask.java:

package com.demo;import java.util.Scanner;import org.springframework.amqp.rabbit.core.RabbitTemplate;public class SpringTask {   RabbitTemplate rabbitTemplate;   String SFG_MESSAGE_QUEUE = "SFG_MESSAGE_QUEUE";   public SpringTask(RabbitTemplate rabbitTemplate){
System.out.println("**** SpringTask STARTED");
this.rabbitTemplate = rabbitTemplate;
}
public void start(){
Scanner scanner = new Scanner(System.in);
String input = "";
while(true){
input = scanner.nextLine();
if(!input.equals("quit")){
rabbitTemplate.convertAndSend(SFG_MESSAGE_QUEUE, input);
System.out.println("Message sent. Enter 'quit' to exit the program.");
}
else{
break;
}
}
scanner.close();
System.out.println("SpringTask EXIT");
}
}

Consumer class, SpringWorker.java:

package com.demo;import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
public class SpringWorker {
String SFG_MESSAGE_QUEUE = "SFG_MESSAGE_QUEUE";
ConnectionFactory connectionFactory;
Queue queue;
TopicExchange exchange;
Binding binding;
public SpringWorker(ConnectionFactory connectionFactory){
this.connectionFactory = connectionFactory;
queue = new Queue(SFG_MESSAGE_QUEUE, false);
exchange = new TopicExchange("spring-boot-exchange");
binding = bindingBuilder.bind(queue).to(exchange).with(SFG_MESSAGE_QUEUE);
System.out.println("**** SpringWorker STARTED");
}
public SimpleMessageListenerContainer createContainer(/*ConnectionFactory connectionFactory*/) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(SFG_MESSAGE_QUEUE); container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {
byte[] messageBody = message.getBody();
String messageResult = new String(messageBody, "UTF-8");
System.out.println(" [x] Received '" + messageResult + "'");
try {
doWork(messageResult);
} finally {
System.out.println(" [x] Done");
}});
return container;
}
private void doWork(String task) {
for (char ch : task.toCharArray()) {
if (ch == '.') {
try {
Thread.sleep(1000);
}
catch (InterruptedException _ignored) {
Thread.currentThread().interrupt();
}
}
}
}
}

RabbitTemplate and ConnectionFactory initializer component, RabbitInitializer.java:

package com.demo;import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
public class RabbitInitializer{ @Autowired
RabbitTemplate rabbitTemplate;
@Autowired
private ConnectionFactory connectionFactory;
public RabbitTemplate getRabbitTemplate(){
return rabbitTemplate;
}
public ConnectionFactory getConnectionFactory(){
return connectionFactory;
}
}

SpringBootApplication class, DemoApplication.java:

package com.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.support.GenericApplicationContext;
@SpringBootApplication
//We need to implement CommandLineRunner to use non-static instances
public class DemoApplication implements CommandLineRunner {
@Autowired
private GenericApplicationContext context;
private String SFG_MESSAGE_QUEUE = "SFG_MESSAGE_QUEUE";
public DemoApplication(){
System.out.println(" ***** DemoApplication");
}
@Override
public void run(String... args) throws Exception {
if(args.length > 0){
context.registerBean(RabbitInitializer.class, () -> new BeanManager());//RabbitInitializer could be a component
RabbitInitializer rbi = context.getBean(RabbitInitializer.class);
if(args[0].equals("1")){//1 to start producer
new SpringTask(rbi.getRabbitTemplate()).start();
}else{//to start consumer
new SpringWorker(rbi.getConnectionFactory()).createContainer().start();
}
System.out.println("DemoApplication EXIT");
return;
}
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

launch.json. I pereferred to use externalTerminal as console configuration.

{"type": "java",
"name": "Launch DemoApplication",
"cwd": "${workspaceFolder}",
"console": "externalTerminal",
"request": "launch",
"mainClass": "com.bvp.demo.DemoApplication",
"projectName": "demo",
"args": ["1"]
}

Thanks for reading,

Cem Yaşar

--

--