diff --git a/boot-rabbitmq-thymeleaf/README.md b/boot-rabbitmq-thymeleaf/README.md
index 720d62c4f..c411068f6 100644
--- a/boot-rabbitmq-thymeleaf/README.md
+++ b/boot-rabbitmq-thymeleaf/README.md
@@ -12,7 +12,16 @@ Demonstrates a message producer and consumer setup with RabbitMQ, plus a simple
---
-Source Code : https://sivalabs.in/2018/02/springboot-messaging-rabbitmq/
+[Source Code](https://sivalabs.in/2018/02/springboot-messaging-rabbitmq/)
+
+---
+
+## Important links
+
+* Home Page : http://localhost:8080
+* RabbitMq : http://localhost:15672 (guest/guest default)
+
+---
## Installing Rabbit MQ
@@ -22,8 +31,3 @@ Windows
https://www.rabbitmq.com/which-erlang.html
http://www.erlang.org/downloads
Video - https://www.youtube.com/watch?v=gKzKUmtOwR4
-
-# Important links
-
-Home Page : http://localhost:8080
-RabbitMq : http://localhost:15672 (guest/guest default)
diff --git a/boot-rabbitmq-thymeleaf/docker-compose.yml b/boot-rabbitmq-thymeleaf/docker-compose.yml
index 5e4b57847..edc37a49d 100644
--- a/boot-rabbitmq-thymeleaf/docker-compose.yml
+++ b/boot-rabbitmq-thymeleaf/docker-compose.yml
@@ -1,4 +1,3 @@
-version: "3.2"
services:
rabbitmq:
container_name: rabbitmq
@@ -20,6 +19,25 @@ services:
retries: 10
networks:
- rabbitmq_go_net
+
+ postgresqldb:
+ image: postgres:17.2-alpine
+ hostname: postgresqldb
+ extra_hosts: [ 'host.docker.internal:host-gateway' ]
+ environment:
+ - POSTGRES_USER=appuser
+ - POSTGRES_PASSWORD=secret
+ - POSTGRES_DB=appdb
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U appuser -d appdb"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ ports:
+ - "5432:5432"
+ networks:
+ - rabbitmq_go_net
+
networks:
rabbitmq_go_net:
driver: bridge
\ No newline at end of file
diff --git a/boot-rabbitmq-thymeleaf/pom.xml b/boot-rabbitmq-thymeleaf/pom.xml
index 75d6d57da..6ab711adc 100644
--- a/boot-rabbitmq-thymeleaf/pom.xml
+++ b/boot-rabbitmq-thymeleaf/pom.xml
@@ -63,6 +63,11 @@
h2
runtime
+
+ org.postgresql
+ postgresql
+ runtime
+
org.springframework.boot
spring-boot-devtools
@@ -74,11 +79,6 @@
org.webjars
webjars-locator-core
-
- org.glassfish.jaxb
- jaxb-runtime
- provided
-
org.webjars
bootstrap
@@ -90,10 +90,11 @@
3.7.1
- org.projectlombok
- lombok
- true
+ org.webjars
+ popper.js
+ 2.11.7
+
org.springframework.boot
@@ -115,6 +116,11 @@
rabbitmq
test
+
+ org.testcontainers
+ postgresql
+ test
+
diff --git a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitListenerConfig.java b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitListenerConfig.java
new file mode 100644
index 000000000..76662167a
--- /dev/null
+++ b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitListenerConfig.java
@@ -0,0 +1,23 @@
+package com.poc.boot.rabbitmq.config;
+
+import org.springframework.amqp.rabbit.annotation.EnableRabbit;
+import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer;
+import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
+
+@EnableRabbit
+@Configuration(proxyBeanMethods = false)
+public class RabbitListenerConfig implements RabbitListenerConfigurer {
+
+ private final MessageHandlerMethodFactory messageHandlerMethodFactory;
+
+ public RabbitListenerConfig(MessageHandlerMethodFactory messageHandlerMethodFactory) {
+ this.messageHandlerMethodFactory = messageHandlerMethodFactory;
+ }
+
+ @Override
+ public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
+ registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory);
+ }
+}
diff --git a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitMQConfig.java b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitMQConfig.java
index 94e8c05db..2ea556673 100644
--- a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitMQConfig.java
+++ b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitMQConfig.java
@@ -1,6 +1,5 @@
package com.poc.boot.rabbitmq.config;
-import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
@@ -8,11 +7,8 @@
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
-import org.springframework.amqp.rabbit.annotation.EnableRabbit;
-import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
-import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -22,10 +18,8 @@
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;
-@EnableRabbit
-@Configuration
-@Slf4j
-public class RabbitMQConfig implements RabbitListenerConfigurer {
+@Configuration(proxyBeanMethods = false)
+public class RabbitMQConfig {
public static final String DLX_ORDERS_EXCHANGE = "DLX.ORDERS.EXCHANGE";
@@ -39,7 +33,7 @@ public class RabbitMQConfig implements RabbitListenerConfigurer {
private final RabbitTemplateConfirmCallback rabbitTemplateConfirmCallback;
- public RabbitMQConfig(RabbitTemplateConfirmCallback rabbitTemplateConfirmCallback) {
+ RabbitMQConfig(RabbitTemplateConfirmCallback rabbitTemplateConfirmCallback) {
this.rabbitTemplateConfirmCallback = rabbitTemplateConfirmCallback;
}
@@ -57,10 +51,8 @@ DirectExchange ordersExchange() {
/* Binding between Exchange and Queue using routing key */
@Bean
- Binding bindingMessages() {
- return BindingBuilder.bind(ordersQueue())
- .to(ordersExchange())
- .with(ROUTING_KEY_ORDERS_QUEUE);
+ Binding bindingMessages(DirectExchange ordersExchange, Queue ordersQueue) {
+ return BindingBuilder.bind(ordersQueue).to(ordersExchange).with(ROUTING_KEY_ORDERS_QUEUE);
}
@Bean
@@ -83,8 +75,8 @@ Queue deadLetterQueue() {
/* Binding between Exchange and Queue for Dead Letter */
@Bean
- Binding deadLetterBinding() {
- return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
+ Binding deadLetterBinding(Queue deadLetterQueue, FanoutExchange deadLetterExchange) {
+ return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange);
}
/* Bean for rabbitTemplate */
@@ -116,15 +108,11 @@ MappingJackson2MessageConverter consumerJackson2MessageConverter() {
}
@Bean
- MessageHandlerMethodFactory messageHandlerMethodFactory() {
+ MessageHandlerMethodFactory messageHandlerMethodFactory(
+ MappingJackson2MessageConverter consumerJackson2MessageConverter) {
DefaultMessageHandlerMethodFactory messageHandlerMethodFactory =
new DefaultMessageHandlerMethodFactory();
- messageHandlerMethodFactory.setMessageConverter(consumerJackson2MessageConverter());
+ messageHandlerMethodFactory.setMessageConverter(consumerJackson2MessageConverter);
return messageHandlerMethodFactory;
}
-
- @Override
- public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
- registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
- }
}
diff --git a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitTemplateConfirmCallback.java b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitTemplateConfirmCallback.java
index 5f56bf37d..8ec414778 100644
--- a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitTemplateConfirmCallback.java
+++ b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/config/RabbitTemplateConfirmCallback.java
@@ -2,20 +2,23 @@
import com.poc.boot.rabbitmq.entities.TrackingState;
import com.poc.boot.rabbitmq.repository.TrackingStateRepository;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
-@Slf4j
@Component
-@RequiredArgsConstructor
public class RabbitTemplateConfirmCallback implements RabbitTemplate.ConfirmCallback {
+ private static final Logger log = LoggerFactory.getLogger(RabbitTemplateConfirmCallback.class);
private final TrackingStateRepository trackingStateRepository;
+ public RabbitTemplateConfirmCallback(TrackingStateRepository trackingStateRepository) {
+ this.trackingStateRepository = trackingStateRepository;
+ }
+
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
Assert.notNull(correlationData, () -> "correlationData can't be null");
@@ -27,6 +30,8 @@ public void confirm(CorrelationData correlationData, boolean ack, String cause)
log.debug(
"persisted correlationId in db : {}",
this.trackingStateRepository.save(
- new TrackingState(null, correlationData.getId(), "processed")));
+ new TrackingState()
+ .setCorrelationId(correlationData.getId())
+ .setStatus("processed")));
}
}
diff --git a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/controller/MessageController.java b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/controller/MessageController.java
index 88c25b68e..3f7464348 100644
--- a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/controller/MessageController.java
+++ b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/controller/MessageController.java
@@ -3,7 +3,6 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.poc.boot.rabbitmq.model.Order;
import com.poc.boot.rabbitmq.service.OrderMessageSender;
-import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -12,14 +11,16 @@
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
-@RequiredArgsConstructor
-public class MessageController {
+class MessageController {
private final OrderMessageSender orderMessageSender;
+ MessageController(OrderMessageSender orderMessageSender) {
+ this.orderMessageSender = orderMessageSender;
+ }
+
@PostMapping("/sendMsg")
- public String handleMessage(
- @ModelAttribute Order order, RedirectAttributes redirectAttributes) {
+ String handleMessage(@ModelAttribute Order order, RedirectAttributes redirectAttributes) {
try {
this.orderMessageSender.sendOrder(order);
redirectAttributes.addFlashAttribute("message", "Order message sent successfully");
diff --git a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/entities/TrackingState.java b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/entities/TrackingState.java
index 7b10b1158..eb0dd3e9c 100644
--- a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/entities/TrackingState.java
+++ b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/entities/TrackingState.java
@@ -1,14 +1,12 @@
package com.poc.boot.rabbitmq.entities;
-import jakarta.persistence.*;
-import lombok.*;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
@Entity
-@AllArgsConstructor
-@NoArgsConstructor
-@ToString
-@Setter
-@Getter
public class TrackingState {
@Id
@@ -19,4 +17,33 @@ public class TrackingState {
private String correlationId;
private String status = "processed";
+
+ public TrackingState() {}
+
+ public Long getId() {
+ return id;
+ }
+
+ public TrackingState setId(Long id) {
+ this.id = id;
+ return this;
+ }
+
+ public String getCorrelationId() {
+ return correlationId;
+ }
+
+ public TrackingState setCorrelationId(String correlationId) {
+ this.correlationId = correlationId;
+ return this;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public TrackingState setStatus(String status) {
+ this.status = status;
+ return this;
+ }
}
diff --git a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/OrderMessageListener.java b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/OrderMessageListener.java
index 0f4d6aa5c..e6080851b 100644
--- a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/OrderMessageListener.java
+++ b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/OrderMessageListener.java
@@ -5,16 +5,17 @@
import com.poc.boot.rabbitmq.model.Order;
import com.poc.boot.rabbitmq.repository.TrackingStateRepository;
-import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
-@Slf4j
@Configuration(proxyBeanMethods = false)
public class OrderMessageListener {
+ private static final Logger log = LoggerFactory.getLogger(OrderMessageListener.class);
private final TrackingStateRepository trackingStateRepository;
public OrderMessageListener(TrackingStateRepository trackingStateRepository) {
diff --git a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/impl/OrderMessageSenderImpl.java b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/impl/OrderMessageSenderImpl.java
index 22dbcf5dd..78f66df7b 100644
--- a/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/impl/OrderMessageSenderImpl.java
+++ b/boot-rabbitmq-thymeleaf/src/main/java/com/poc/boot/rabbitmq/service/impl/OrderMessageSenderImpl.java
@@ -6,7 +6,6 @@
import com.poc.boot.rabbitmq.model.Order;
import com.poc.boot.rabbitmq.service.OrderMessageSender;
import java.util.UUID;
-import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
@@ -15,13 +14,18 @@
import org.springframework.stereotype.Service;
@Service
-@RequiredArgsConstructor
public class OrderMessageSenderImpl implements OrderMessageSender {
private final RabbitTemplate templateWithConfirmsEnabled;
private final ObjectMapper objectMapper;
+ public OrderMessageSenderImpl(
+ RabbitTemplate templateWithConfirmsEnabled, ObjectMapper objectMapper) {
+ this.templateWithConfirmsEnabled = templateWithConfirmsEnabled;
+ this.objectMapper = objectMapper;
+ }
+
@Override
public void sendOrder(Order order) throws JsonProcessingException {
// this.rabbitTemplate.convertAndSend(RabbitConfig.QUEUE_ORDERS, order);
diff --git a/boot-rabbitmq-thymeleaf/src/main/resources/application.properties b/boot-rabbitmq-thymeleaf/src/main/resources/application.properties
index ec5dc9a51..84ef385bc 100644
--- a/boot-rabbitmq-thymeleaf/src/main/resources/application.properties
+++ b/boot-rabbitmq-thymeleaf/src/main/resources/application.properties
@@ -1,3 +1,5 @@
+spring.application.name=boot-rabbitmq-theymeleaf
+
logging.level.com.poc.boot.rabbitmq=debug
#spring.rabbitmq.host=localhost
@@ -14,6 +16,35 @@ spring.rabbitmq.listener.simple.retry.initial-interval=1s
spring.rabbitmq.listener.simple.retry.max-attempts=3
spring.rabbitmq.listener.simple.retry.multiplier=2
spring.rabbitmq.listener.simple.retry.max-interval=2s
+spring.rabbitmq.listener.simple.acknowledge-mode=auto
+spring.rabbitmq.listener.simple.observation-enabled=true
+
+spring.mvc.problemdetails.enabled=true
+spring.threads.virtual.enabled=true
+
+spring.testcontainers.beans.startup=parallel
+
+################ Actuator #####################
+management.endpoints.web.exposure.include=configprops,env,health,info,logfile,loggers,metrics,prometheus,sbom
+management.endpoint.health.show-details=always
+
+################ Database #####################
+spring.jpa.show-sql=false
+spring.jpa.open-in-view=false
+spring.data.jpa.repositories.bootstrap-mode=deferred
+spring.datasource.hikari.auto-commit=false
+spring.datasource.hikari.pool-name=HikariPool-${spring.application.name}
+spring.datasource.hikari.data-source-properties.ApplicationName=${spring.application.name}
+spring.jpa.hibernate.ddl-auto=validate
+#spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.properties.hibernate.jdbc.time_zone=UTC
+spring.jpa.properties.hibernate.generate_statistics=false
+spring.jpa.properties.hibernate.jdbc.batch_size=25
+spring.jpa.properties.hibernate.order_inserts=true
+spring.jpa.properties.hibernate.order_updates=true
+spring.jpa.properties.hibernate.query.fail_on_pagination_over_collection_fetch=true
+spring.jpa.properties.hibernate.query.in_clause_parameter_padding=true
+spring.jpa.properties.hibernate.query.plan_cache_max_size=4096
+spring.jpa.properties.hibernate.connection.provider_disables_autocommit=true
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
-spring.mvc.problemdetails.enabled=true
-spring.threads.virtual.enabled=true
\ No newline at end of file
diff --git a/boot-rabbitmq-thymeleaf/src/main/resources/db/changelog/01-create-tables.xml b/boot-rabbitmq-thymeleaf/src/main/resources/db/changelog/01-create-tables.xml
index 82e1b2d2d..3f48ac73d 100644
--- a/boot-rabbitmq-thymeleaf/src/main/resources/db/changelog/01-create-tables.xml
+++ b/boot-rabbitmq-thymeleaf/src/main/resources/db/changelog/01-create-tables.xml
@@ -1,9 +1,12 @@
+ https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.20.xsd">
+
+
+
@@ -23,10 +26,10 @@
-
+
-
+
diff --git a/boot-rabbitmq-thymeleaf/src/test/java/com/poc/boot/rabbitmq/common/ContainerConfiguration.java b/boot-rabbitmq-thymeleaf/src/test/java/com/poc/boot/rabbitmq/common/ContainerConfiguration.java
index fd8f3bbac..97e88b7fc 100644
--- a/boot-rabbitmq-thymeleaf/src/test/java/com/poc/boot/rabbitmq/common/ContainerConfiguration.java
+++ b/boot-rabbitmq-thymeleaf/src/test/java/com/poc/boot/rabbitmq/common/ContainerConfiguration.java
@@ -4,6 +4,7 @@
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
+import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.containers.RabbitMQContainer;
import org.testcontainers.utility.DockerImageName;
@@ -16,4 +17,10 @@ public class ContainerConfiguration {
RabbitMQContainer rabbitMQContainer() {
return new RabbitMQContainer(DockerImageName.parse("rabbitmq").withTag("4.0.5-management"));
}
+
+ @Bean
+ @ServiceConnection
+ PostgreSQLContainer> postgreSQLContainer() {
+ return new PostgreSQLContainer<>(DockerImageName.parse("postgres").withTag("17.2-alpine"));
+ }
}