[Spring] Spring Integration - Message

2016. 12. 27. 18:32Spring/Spring Integration

Spring Integration - Message



Spring Integration 에서 메시지는 포괄적인 데이터 컨테이너를 의미한다. 메시지는 헤더와 페이로드로 구성된다. 어떤 타입의 오브젝트도 메시지의 페이로드가 될 수 있고, 각각의 메시지 헤더는 추가 가능한 키-값 형태의 프로퍼티들로 구성된다.



Message Interface


메시지 인터페이스는 다음과 같다.


public interface Message<T> {


    T getPayload(); 

    MessageHeaders getHeaders();


}




Message Headers


페이로드가 어떤 타입이던 관계없듯이 헤더의 값도 어떤 값이던 관계없다. MessageHeaders 클래스는 java.util.Map 인터페이스를 구현했기 때문이다.


public final class MessageHeaders implements Map<String, Object>, Serializable {

    ...

}


MessageHeaders 클래스가 Map 인터페이스를 구현하기는 했지만, MessageHeaders 타입의 객체는 읽기 전용이다. 따라서 이 객체의 put/remove/clear 메소드를 호출하려고 할 경우 UnsupportedOperationException 예외가 발생할 것이다. 메시지는 여러 메시지 소비자들에게 전달되기 때문에 맵의 구조가 변경될 수 없다. 페이로드도 최초 생성 이후에는 변경 될 수 없다.


메시지 헤더의 정보는 다음과 같은 방법으로 조회 할 수 있다.


Object someValue = message.getHeaders().get("someKey");

CustomerId customerId = message.getHeaders().get("customerId", CustomerId.class);

Long timestamp = message.getHeaders().getTimestamp();


아래 헤더 정보는 디폴트로 정의되어 있는 것들이다.


 Header Name

 Header Type

 ID

 java.util.UUID

 TIMESTAMP

 java.lang.Long

 CORRELATION_ID

 java.lang.Object

 REPLY_CHANNEL

 java.lang.Object ( can be a String or MessageChannel )

 ERROR_CHANNEL

 java.lang.Object ( can be a String or MessageChannel )

 SEQUENCE_NUMBER

 java.lang.Integer

 SEQUENCE_SIZE

 java.lang.Integer

 EXPIRATION_DATE

 java.lang.Long

 PRIORITY

 java.lang.Integer


많은 인바운드 또는 아웃바운드 어댑터 구현들이 위의 디폴트로 정의된 헤더 정보를 참조하고 있거나 사용한다. 추가적인 헤더 정보도 설정할 수 있다.



Message Implementations


Message  인터페이스를 잘 살펴보면 페이로드와 헤더를 가져오는 메소드는 존재한다는데 이런 정보를 설정하는 메소드는 제공하고 있지 않다. 헤더 정보와 페이로드는 최초 생성 이후에는 변경되서는 안되기 때문이다.


GenericMessage  클래스의 생성자로 페이로드나 헤더 정보를 넘겨 메시지를 생성하는 대신 MessageBuilder 라는 것을 사용해서 편리하게 메시지를 생성할 수 있다. 두 가지 팩토리 메소드를 제공하는데 하나는 기존 메시지로부터 메시지를 생성하기 위한 것이고 다른 하나는 페이로드 오브젝트로 부터 메시지를 생성하기 위한 것이다. 기존 메시지로 부터 메시지를 생성할 경우 헤더 정보와 페이로드 정보는 새로운 메시지로 복사된다는 것을 기억하자. 참조하는 것이 아니다.


Message<String> message1 = MessageBuilder.withPayload("test")

        .setHeader("foo", "bar")

        .build();

Message<String> message2 = MessageBuilder.fromMessage(message1).build();

assertEquals("test", message2.getPayload());

assertEquals("bar", message2.getHeaders().get("foo"));


페이로드로 메시지를 만들면서 이 메시지의 헤더 정보는 기존의 메시지의 헤더 정보를 복사해 사용하고자 한다면 다음처럼 copy 메소드를 사용할 수 있다.


Message<String> message3 = MessageBuilder.withPayload("test3")

        .copyHeaders(message1.getHeaders())

        .build();

Message<String> message4 = MessageBuilder.withPayload("test4")

    .setHeader("foo", 123)

    .copyHeadersIfAbsent(message1.getHeaders())

    .build();

assertEquals("bar", message3.getHeaders().get("foo"));

assertEquals(123, message4.getHeaders().get("foo"));


copyHeaderslfAbsent 메소드는 헤더 값이 존재할 경우 기존 값을 덮어 쓰지 않다는 점을 기억하자. 위의 두 번째 예제에는 setHeader 메소드로 신규 헤더 값을 추가하는 방법을 보여주고 있다.


Message<Integer> importantMessage = MessageBuilder.withPayload(99)

        .setPriority(5)

        .build();

assertEquals(5, importantMessage.getHeaders().getPriority());

Message<Integer> lessImportantMessage = MessageBuilder.fromMessage(importantMessage)

    .setHeaderIfAbsent(MessageHeaders.PRIORITY, 2)

    .build();

assertEquals(2, lessImportantMessage.getHeaders().getPriority());









































'Spring > Spring Integration' 카테고리의 다른 글

[Spring Integration] Spring-integration-samples  (0) 2017.01.11