RabbitMQ with Spring MVC Micro Service Architecture

Rabbitmq

RabbitMQ is the most widely deployed open source message broker that can use to communicate data between services of micro service architecture. It’s a queue type message broker and exchange the data using routing key and queue. First you need to download the RabbitMQ server and configure the environment Home and path.

Rabbitmq Home path
Rabbitmq sbin path
right click and click start

rabbitmq-plugins enable rabbitmq_management — online

Then go to http://localhost:15672 in browser and login using username = guest and password = guest

Rabbit Overview page

Spring MVC Project

First you need to create Two Spring MVC project.In my example I will create Customer and Product applications and communicate data between these two application using RabbitMQ. You can get the source code from here. I will use maven to build my Spring MVC applications and add every dependency to pom.xml as below and use mariaDB as my database connection and use hibernate, jacksonJson, RabbiMQ and few more libraries.

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.11.Final</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.2.11.Final</version>
</dependency>

<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.7</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>1.5.7</version>
</dependency>

<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>

<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>4.8.0</version>
</dependency>

<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp</artifactId>
<version>1.7.10.RELEASE</version>
</dependency>
</dependencies>
# MariaDB properties
mariadb.url=jdbc:mariadb://localhost:3306/customer
mariadb.username=root
mariadb.password=toor
mariadb.driver=org.mariadb.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create-drop

# Hibernate properties
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

#C3P0 properties
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.acquire_increment=1
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=150

#Rabbitmq properties
rabbitmq.hostName=localhost
rabbitmq.portNumber=5672
rabbitmq.username=guest
rabbitmq.password=guest
rabbitmq.virtualHost=/
rabbitmq.exchange=customer.direct
rabbitmq.routingkey=customer.routingkey
rabbitmq.queue=customer.queue
project structure
@Configuration
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.customer.spring.dao"),
@ComponentScan("com.customer.spring.service")})
public class AppConfig {

@Autowired
Environment env;

@Bean
public LocalSessionFactoryBean getSessionFactory()
{
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();

Properties props = new Properties();

// Setting JDBC properties
props.put(DRIVER, env.getProperty("mariadb.driver"));
props.put(URL, env.getProperty("mariadb.url"));
props.put(USER, env.getProperty("mariadb.username"));
props.put(PASS, env.getProperty("mariadb.password"));

// Setting Hibernate properties
props.put(SHOW_SQL, env.getProperty("hibernate.show_sql"));
props.put(HBM2DDL_AUTO, env.getProperty("hibernate.hbm2ddl.auto"));
props.put(DIALECT, env.getProperty("hibernate.dialect"));

// Setting C3P0 properties
props.put(C3P0_MIN_SIZE, env.getProperty("hibernate.c3p0.min_size"));
props.put(C3P0_MAX_SIZE, env.getProperty("hibernate.c3p0.max_size"));
props.put(C3P0_ACQUIRE_INCREMENT,
env.getProperty("hibernate.c3p0.acquire_increment"));
props.put(C3P0_TIMEOUT, env.getProperty("hibernate.c3p0.timeout"));
props.put(C3P0_MAX_STATEMENTS, env.getProperty("hibernate.c3p0.max_statements"));

factoryBean.setHibernateProperties(props);
factoryBean.setPackagesToScan("com.customer.spring.model");

return factoryBean;
}

@Bean
public HibernateTransactionManager getTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getSessionFactory().getObject());
return transactionManager;
}
}
@Configuration
@EnableRabbit
public class MqConfig {
@Autowired
private Environment environment;
@Bean
public ConnectionFactory connectionFactory()
{
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setUsername( environment.getProperty( "rabbitmq.username" ) );
connectionFactory.setPassword( environment.getProperty( "rabbitmq.password" ) );
connectionFactory.setVirtualHost( environment.getProperty( "rabbitmq.virtualHost" ) );
connectionFactory.setHost( environment.getProperty( "rabbitmq.hostName" ) );
connectionFactory.setPort( Integer.parseInt( environment.getProperty( "rabbitmq.portNumber" ) ) );
return connectionFactory;
}
@Bean
public AmqpAdmin amqpAdmin()
{
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory() );
rabbitAdmin.setIgnoreDeclarationExceptions(true);
return rabbitAdmin;
}

@Bean
public RabbitTemplate rabbitTemplate()
{
RabbitTemplate rabbitTemplate = new RabbitTemplate( connectionFactory() );
rabbitTemplate.setMessageConverter( jsonMessageConverter() );
return rabbitTemplate;
}

@Bean(name = "rabbitListenerContainerFactory")
public SimpleRabbitListenerContainerFactory listenerFactory()
{
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory( connectionFactory() );
factory.setMessageConverter( jsonMessageConverter() );


factory.setConcurrentConsumers(3);
factory.setMaxConcurrentConsumers(10);
return factory;
}
@Bean
public Jackson2JsonMessageConverter jsonMessageConverter()
{
ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
return new Jackson2JsonMessageConverter( mapper );
}
@Bean
public Queue queue()
{
return new Queue( environment.getProperty( "rabbitmq.queue" ) );
}

@Bean
public DirectExchange directExchange()
{
return new DirectExchange(environment.getProperty( "rabbitmq.exchange" ));
}

@Bean
public Binding binding()
{
return BindingBuilder.bind(queue()).to(directExchange())
.with(environment.getProperty( "rabbitmq.routingkey" ));
}
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class , MqConfig.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { com.customer.spring.config.WebConfig.class };
}

@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.customer.spring.controller"})
public class WebConfig extends WebMvcConfigurerAdapter {

}
@Service
@Transactional(readOnly = true)
public class ProducerServiceImp implements ProducerService {
@Autowired
private AmqpTemplate amqpTemplate;

@Value( "${rabbitmq.exchange}" )
private String exchange;

@Value( "${rabbitmq.routingkey}" )
private String routingkey;

@Override
public Object sendMsg(Long proId) throws Exception{
Object response = amqpTemplate.convertSendAndReceive(exchange,routingkey,proId);
System.out.println("============== Response ==================");
System.out.println(response);
System.out.println("==========================================");
return response;
}
}
@Override
@RabbitListener(queues = "${rabbitmq.queue}")
public Object consumerMessage(Long proId) throws AmqpIOException {
System.out.println("=============== Message ==================");
System.out.println(proId);
System.out.println("==========================================");
Product product=productService.getProduct(proId);
if(product==null){
return null;
}
else{
ObjectMapper obj = new ObjectMapper();
try {
String pro = obj.writeValueAsString(product);
return pro;
}catch(JsonProcessingException e){
return null;
}
}
}

Graduated Computer Science Student at University Of Colombo School of Computing & Still working as Senior Software Engineer at Scicom Msc Bhd.