ch10-1. Spring Messaging with JMS(Java Messaging Service)

yc999·2021년 1월 19일
0

java

목록 보기
4/6

시장에는 다양한 JMS provider가 있다(ex. RabbitMQ, ActiveMQ, etc..) 자바에서 이런 메세지 서버와 메세지를 주고받는 기능을 표준화 한 것이 JMS이다. 즉 JMS란 비동기식 메시징을 위한 표준 API이다. JMS와, JMS을 Spring framework에서 한 단계 더 추상화 한 ?에 대해서도 알아보자.

Prerequisite for spring framework

  • 예제를 실행하기 위해 ActiveMQ를 embeded 모드로 설정하여 사용할 수 있도록 한다. xmlns:amq를 정의하자.
  • JMSConnectionFactory 설정하기
    • JMS에서 connection~close 부준을 대신 해 주기 때문에 사용자는 JMS가 넘겨주는 session을 받아 원하는 작업을 하기만 하면 된다. session을 만들어서 넘겨주는 JMSConnectionFactory를 DI를 통해 넘겨받기 위한 설정을 하자.
    1. JMSConnectionFactory Bean을 생성한다.
    2. JMSConnectionFactory를 ref하는 JmsTemplate Bean을 생성한다.

Send JMS message within transaction

  • DB 작업 뿐이 아니라 메세지 서비스를 이용할 때도 트랜잭션을 사용할수 있다. 트랜잭션 안의 send 과정중에서 문제가 생기면 만들어진 모든 메시지가 파괴되고, 트랜잭션 안의 receive 과정중에 문제가 생기면 소비한 메시지는 다시 롤백된다.
  • 트랜잭션 안에서 JMS 메시지를 보내기 위해서는 JMSTransactionManager가 connection factory를 ref한 뒤, @Transactional annotation을 통해 사용하는 방법과, TransactionalTemplate를 사용해서 직접 트랜잭션을 생성하는 방법이 있다.

Queue & Topic in JMS

JMS endpoint type에는 Queue, Topic 등이 있다. 다른 타입은 제쳐두고 이 두 녀석을 알아보자.

  • Queue : static endpoint
  • Topic : dynamic endpoint, runtime에 client가 직접 생성할 수 있다.

Queue에서 메세지를 가져가면 사라진다. 따라서 1명의 consumer만 데이터에 접근할 수 있다. enqueue되는 시점에 consumer가 없어도 된다. 시간적인 여유가 있다. 하지만 Topic은 topic을 sub 하고 있는 모든 consumer가 message를 받게 되고, publish 순간에 sub하고 있지 않은 consumer는 데이터를 받을 수 없다.

Topic을 사용하기 위해서는 JMSTemplate의 pubSubDomain property를 true로 설정해 주어야 한다. 그렇게 하면 session안에서 Topic을 생성할 수 있다.

JmsTemplate.send("createTopicRuntime", new MessageCreator() {
    public Message createMessage(Session session) throws JMSException {
        session.createTopic("dynamicTopic");
        Object objectMessage = session.createObjectMessage();
        objectMessage.setObject(someObject);
        return objectMessage; }
        }
    });

JMS로 메세지를 보내기 위해서는 보내고자 하는 객체 또는 문자열을 Message형식으로 변환해야 한다. JMS은 이런 serialize / deserialize method를 제공한다.

Sync / Async message receive

JmsTemplate.receive는 blocking method이다.

JMS 메세지를 비동기적으로 받기 위해서는

  • MessageListener interface를 구현하여 등록
  • @JmsListener annotation을 등록
    메시지 리스터 컨테이너가 트랜잭션과 자원 관리 측면을 처리해준다.

MessageListener interface

public class FixedDepositMessageListener implements MessageListener {
...

    @Override
    public void onMessage(Message message) {
        ObjectMessage objectMessage = (ObjectMessage) message;
        ...
    }
}

@JmsListener annotaion

@Component
public class MyAnnotatedJmsListener {
...
    @JmsListener(destination = "emailQueueDestination")
    public void processEmailMessage(Message message) { ... }
...
}
profile
꼬물꼬물 앞으로 가는 중

0개의 댓글