add spring-rabbitmq example

Signed-off-by: Mohammad Sadegh Sheikh Zahedi <sheikhoo.iran@gmail.com>
This commit is contained in:
Mohammad Sadegh Sheikh Zahedi
2023-01-02 14:47:16 +03:30
parent 3746d65ad1
commit b670c71c4a
12 changed files with 391 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# syntax=docker/dockerfile:1.4
FROM --platform=$BUILDPLATFORM maven:3.8.5-eclipse-temurin-17 AS builder
WORKDIR /workdir/server
COPY pom.xml /workdir/server/pom.xml
RUN mvn dependency:go-offline
COPY src /workdir/server/src
RUN mvn install
FROM builder AS dev-envs
RUN <<EOF
apt-get update
apt-get install -y --no-install-recommends git
EOF
RUN <<EOF
useradd -s /bin/bash -m vscode
groupadd docker
usermod -aG docker vscode
EOF
# install Docker tools (cli, buildx, compose)
COPY --from=gloursdocker/docker / /
CMD ["mvn", "spring-boot:run"]
FROM builder as prepare-production
RUN mkdir -p target/dependency
WORKDIR /workdir/server/target/dependency
RUN jar -xf ../*.jar
FROM eclipse-temurin:17-jre-focal
EXPOSE 8080
VOLUME /tmp
ARG DEPENDENCY=/workdir/server/target/dependency
COPY --from=prepare-production ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=prepare-production ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=prepare-production ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.company.project.Application"]

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.company</groupId>
<artifactId>spring-rabbitmq</artifactId>
<version>0.0.1</version>
<name>spring-rabbitmq</name>
<description>Demo project for Spring Boot and Rabbitmq</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</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>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,12 @@
package com.company.project;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -0,0 +1,33 @@
package com.company.project.config;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.company.project.model.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class QueueConsumer {
private final RabbitTemplate rabbitTemplate;
@Value("${queue.name}")
private String queueName;
@Autowired
public QueueConsumer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
private String receiveMessage() {
String message = (String) rabbitTemplate.receiveAndConvert(queueName);
return message;
}
public Message processMessage() throws JsonProcessingException {
String message = receiveMessage();
return new ObjectMapper().readValue(message, Message.class);
}
}

View File

@@ -0,0 +1,29 @@
package com.company.project.config;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.company.project.model.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class QueueProducer {
@Value("${fanout.exchange}")
private String fanoutExchange;
private final RabbitTemplate rabbitTemplate;
@Autowired
public QueueProducer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}
public void produce(Message message) throws JsonProcessingException {
rabbitTemplate.setExchange(fanoutExchange);
rabbitTemplate.convertAndSend(new ObjectMapper().writeValueAsString(message));
}
}

View File

@@ -0,0 +1,33 @@
package com.company.project.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitConfiguration {
@Value("${fanout.exchange}")
private String fanoutExchange;
@Value("${queue.name}")
private String queueName;
@Bean
Queue queue() {
return new Queue(queueName, true);
}
@Bean
FanoutExchange fanoutExchange() {
return new FanoutExchange(fanoutExchange);
}
@Bean
Binding binding(Queue queue, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(queue).to(fanoutExchange);
}
}

View File

@@ -0,0 +1,36 @@
package com.company.project.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.company.project.config.QueueConsumer;
import com.company.project.config.QueueProducer;
import com.company.project.model.Message;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/")
public class MessageController {
private final QueueProducer queueProducer;
private final QueueConsumer queueConsumer;
public MessageController(QueueProducer queueProducer, QueueConsumer queueConsumer) {
this.queueProducer = queueProducer;
this.queueConsumer = queueConsumer;
}
@GetMapping("getMessage")
public ResponseEntity<?> getMessage() throws JsonProcessingException {
Message message = queueConsumer.processMessage();
return new ResponseEntity<Message>(message, HttpStatus.OK);
}
@PostMapping("sendMessage")
public ResponseEntity<?> sendMessage(@RequestBody Message message) throws JsonProcessingException {
queueProducer.produce(message);
return new ResponseEntity<Message>(HttpStatus.CREATED);
}
}

View File

@@ -0,0 +1,32 @@
package com.company.project.model;
public class Message {
private String title;
private String text;
private String sender;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
}

View File

@@ -0,0 +1,9 @@
server.port= 8080
spring.main.banner-mode= off
spring.rabbitmq.host= ${RABBITMQ_HOST:localhost}
spring.rabbitmq.port= 5672
spring.rabbitmq.username= guest
spring.rabbitmq.password= guest
queue.name= ${RABBITMQ_QUEUE_NAME:springboot-queue}
fanout.exchange= ${RABBITMQ_FANOUT_EXCHANGE:springboot-exchange}