diff --git a/pom.xml b/pom.xml index 75403dd..6d96c87 100644 --- a/pom.xml +++ b/pom.xml @@ -137,6 +137,17 @@ json-simple 1.1.1 + + + + org.springframework.amqp + spring-rabbit-test + test + + + org.springframework.boot + spring-boot-starter-amqp + diff --git a/src/main/java/com/palnet/Application.java b/src/main/java/com/palnet/Application.java index 49eb900..70c54dc 100644 --- a/src/main/java/com/palnet/Application.java +++ b/src/main/java/com/palnet/Application.java @@ -1,7 +1,9 @@ package com.palnet; +import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @@ -12,4 +14,9 @@ public class Application { SpringApplication.run(Application.class, args); } + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } + } diff --git a/src/main/java/com/palnet/biz/config/MessageConfig.java b/src/main/java/com/palnet/biz/config/MessageConfig.java new file mode 100644 index 0000000..e7533dd --- /dev/null +++ b/src/main/java/com/palnet/biz/config/MessageConfig.java @@ -0,0 +1,74 @@ +package com.palnet.biz.config; + +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +public class MessageConfig { + private final Environment env; + + public MessageConfig(Environment env) { + this.env = env; + } + +// @Bean +// public CachingConnectionFactory cachingConnectionFactory() { +// return new CachingConnectionFactory(); +// } + + @Bean + public Jackson2JsonMessageConverter converter() { + return new Jackson2JsonMessageConverter(); + } + + @Bean + public DirectExchange appDroneExchange() { + return new DirectExchange(env.getProperty("message.app.exchange-name")); + } + + @Bean + public DirectExchange websocketDroneExchange() { + return new DirectExchange(env.getProperty("message.websocket.exchange-name")); + } + + @Bean + public Queue appDroneQueue() { + return new Queue(env.getProperty("message.app.queue-name"), false); + } + + @Bean + public Queue websocketDroneQueue() { + return new Queue(env.getProperty("message.websocket.queue-name"), false); + } + + @Bean + public Binding appDroneBinding(Queue appDroneQueue, DirectExchange appDroneExchange) { + return BindingBuilder.bind(appDroneQueue) + .to(appDroneExchange) + .with(env.getProperty("message.app.routing-key")); + } + + @Bean + public Binding websocketDroneBinding(Queue websocketDroneQueue, DirectExchange websocketDroneExchange) { + return BindingBuilder.bind(websocketDroneQueue) + .to(websocketDroneExchange) + .with(env.getProperty("message.websocket.routing-key")); + } + + @Bean + public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, Jackson2JsonMessageConverter converter) { + RabbitTemplate rabbitTemplate = new RabbitTemplate(); + + rabbitTemplate.setConnectionFactory(connectionFactory); + rabbitTemplate.setMessageConverter(converter); + + return rabbitTemplate; + } + +} diff --git a/src/main/java/com/palnet/biz/message/consumer/MessageConsumer.java b/src/main/java/com/palnet/biz/message/consumer/MessageConsumer.java new file mode 100644 index 0000000..03b806d --- /dev/null +++ b/src/main/java/com/palnet/biz/message/consumer/MessageConsumer.java @@ -0,0 +1,34 @@ +package com.palnet.biz.message.consumer; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.palnet.biz.message.service.MessageService; +import com.palnet.comn.model.GPDatabaseModel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@Slf4j +public class MessageConsumer { + + private final MessageService messageService; + private final ObjectMapper objectMapper; + + public MessageConsumer(MessageService messageService, ObjectMapper objectMapper) { + this.messageService = messageService; + this.objectMapper = objectMapper; + } + + @RabbitHandler + @RabbitListener(queues = {"app.drone.queue"}) + public void receivedDroneMessage(final GPDatabaseModel model) { + messageService.insert(model); + } + +} diff --git a/src/main/java/com/palnet/biz/message/model/MessageDataShareContext.java b/src/main/java/com/palnet/biz/message/model/MessageDataShareContext.java new file mode 100644 index 0000000..581ce0c --- /dev/null +++ b/src/main/java/com/palnet/biz/message/model/MessageDataShareContext.java @@ -0,0 +1,30 @@ +package com.palnet.biz.message.model; + +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class MessageDataShareContext { + + private Map idntfKey; + + public MessageDataShareContext() { + this.idntfKey = new ConcurrentHashMap<>(); + } + + public void putIdntfKey(String key, String value) { + idntfKey.put(key, value); + } + + public void removeIdntfKey(String key) { + idntfKey.remove(key); + } + + public String getIndtfKey(String key) { + return idntfKey.get(key); + } + +} diff --git a/src/main/java/com/palnet/biz/message/service/MessageService.java b/src/main/java/com/palnet/biz/message/service/MessageService.java new file mode 100644 index 0000000..9e1568f --- /dev/null +++ b/src/main/java/com/palnet/biz/message/service/MessageService.java @@ -0,0 +1,10 @@ +package com.palnet.biz.message.service; + +import com.palnet.comn.model.GPDatabaseModel; +import com.palnet.comn.model.GPModel; + +public interface MessageService { + + void insert(GPDatabaseModel model); + +} diff --git a/src/main/java/com/palnet/biz/message/service/impl/MessageServiceImpl.java b/src/main/java/com/palnet/biz/message/service/impl/MessageServiceImpl.java new file mode 100644 index 0000000..4115482 --- /dev/null +++ b/src/main/java/com/palnet/biz/message/service/impl/MessageServiceImpl.java @@ -0,0 +1,87 @@ +package com.palnet.biz.message.service.impl; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.palnet.biz.jpa.entity.CtrCntrlHstry; +import com.palnet.biz.jpa.repository.pty.PtyDronQueryRepository; +import com.palnet.biz.jpa.service.ctr.CtrCntrlJpaService; +import com.palnet.biz.message.model.MessageDataShareContext; +import com.palnet.biz.message.service.MessageService; +import com.palnet.comn.model.GPDatabaseModel; +import com.palnet.comn.model.GPModel; +import com.palnet.comn.utils.DateUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Objects; +import java.util.UUID; + +@Service +@RequiredArgsConstructor +@Slf4j +public class MessageServiceImpl implements MessageService { + + private final CtrCntrlJpaService ctrCntrlJpaService; + private final PtyDronQueryRepository ptyDronQueryRepository; + private final MessageDataShareContext shareContext; + private final RabbitTemplate rabbitTemplate; + private final Environment env; + private final ObjectMapper objectMapper; + + + @Override + @Transactional + public void insert(GPDatabaseModel model) { + if(!model.getMessageType().equals("OPENSKY")) { + if(shareContext.getIndtfKey(model.getObjectId()) == null) { + String controlID = UUID.randomUUID().toString(); + + model.setControlId(controlID); + model.setTypeCd("01"); + model.setAreaTrnsYn("N"); + model.setControlStartDt(DateUtils.getCurrentTime()); + + shareContext.putIdntfKey(model.getObjectId(), controlID); + } else { + model.setControlId(shareContext.getIndtfKey(model.getObjectId())); + model.setTypeCd("02"); + model.setAreaTrnsYn("E"); + } + + /* 메세지 서버에게 위임 */ + this.sendToWebsocket(model); + +// if(model.getTypeCd().equals("01")) { +// //마스터 정보에저장 +// //식별번호로 제작번호 알아오기 +// String prodNumber = ptyDronQueryRepository.findIdntfNumByProdNumber(model.getObjectId()); +// model.setProdNumber(prodNumber); +// +// ctrCntrlJpaService.insertCtrCntrlBas(model); +// } +// if(model.getTypeCd().equals("99")) { +// //마스터 정보에 종료 처리 저장 +// model.setEndTypeCd("01"); +// ctrCntrlJpaService.updateCtrCntrlBas(model); +// } +// +// CtrCntrlHstry ctrCntrlHstry = ctrCntrlJpaService.insertCtrCntrlHstry(model); +// +// if(model.getTypeCd().equals("01") || model.getTypeCd().equals("99")) { +// ctrCntrlJpaService.insertCtrCntrlHstryArea(model, ctrCntrlHstry.getHstrySno()); +// } + } + } + + public void sendToWebsocket(GPDatabaseModel model) { + /* Websocket 서버로 전달 할 드론 데이터 */ + rabbitTemplate.convertAndSend( + Objects.requireNonNull(env.getProperty("message.websocket.queue-name")), + model + ); + } +} diff --git a/src/main/java/com/palnet/server/SocketServer.java b/src/main/java/com/palnet/server/SocketServer.java index 93cc68a..dc1cf38 100644 --- a/src/main/java/com/palnet/server/SocketServer.java +++ b/src/main/java/com/palnet/server/SocketServer.java @@ -47,14 +47,14 @@ public class SocketServer { @PostConstruct public void postConstruct(){ - start(); +// start(); } @PreDestroy public void preDestroy(){ - stop(); +// stop(); } public void start(){ diff --git a/src/main/java/com/palnet/server/WebServer.java b/src/main/java/com/palnet/server/WebServer.java index fa7380e..00ec80d 100644 --- a/src/main/java/com/palnet/server/WebServer.java +++ b/src/main/java/com/palnet/server/WebServer.java @@ -50,14 +50,14 @@ public class WebServer { @PostConstruct public void postConstruct(){ - start(); +// start(); } @PreDestroy public void preDestroy(){ - stop(); +// stop(); } public void start(){ diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c9465be..085a50f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -45,6 +45,11 @@ spring: show_sql: false # format_sql: true format_sql: false + rabbitmq: + host: localhost + port: 5672 + username: guest + password: guest server: port: 8080 @@ -65,6 +70,16 @@ netty: thread: boss: 1 worker: 1 +message: + app: + queue-name: app.drone.queue + exchange-name: app.drone.exchange + routing-key: app.drone.routing.# + websocket: + queue-name: websocket.drone.queue + exchange-name: websocket.drone.exchange + routing-key: websocket.drone.routing.# + --- spring: