블로그 이미지
Max.

calendar

          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            

Notice

2008.02.04 17:51 이전글(~2009)
최근 JMS관련 일을 하게 될것 같다. 미리 예제를 만들어 보기 위해서 테스트 해본다.


JMS 모델중 Point-to-point 메시징 모델인 Queue 방식에 대한 예제를 만들어 본다.
물론 예제는 Spring 기반이다.

1. 메시지 서비스 구조

보내는이(Sender)  -- Message --> 큐(Queue)  --Message-->  받는이(Receiver)

보내는이와 받는이는 구현해야 한다. 물론 Spring의 편리한 Template 클래스를 이용해서 말이다.
큐에 쌓이거나 주고 받는것은 아파치의 ActiveMQ가 알아서 해준다.
구현하는것은 ActiveMQ에 잘 보내고, 잘 가져오는 것이다. 코딩하기전에 위의 구조를 먼저 이해한 후 코딩에 들어가면 쉽게 이해할수 있다.


2. 브로커 설치 (Apache의 ActiveMQ를 사용한다.)
    메시지 브로커는 ActiveMQ를 사용한다.
    - 다운 받아 원하는 디렉토리에 압축을 풀고 activemq.bat(Window일경우)를 실행한다.
사용자 삽입 이미지

    - 3개의 리스닝 프로토콜을 볼수 있다. (tcp,ssl,stomp)
    - 이제 해당 URL로 메시지를 브로킹 할수 있다.

3. ActiveMQ 와 연동하기 Bean 설정

순서적으로 한다면, 기본적인 XML 설정후 클래스 하나씩 생성후 XML과 매핑해야 하나, 한꺼번에 봐도 그리 헷깔리지 않는다. 그래서 그냥 쭉 내려 보자.

<!--  Autowired -->

    <context:component-scan base-package="net.max.msg" />
   
<!-- ActiveMQ factory -->
   
    <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616" />
    </bean>
: ActiveMQ와 Connection 정보를 가져오게 한다.

<!-- Destination - Queue Model -->

    <bean id="maxDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg index="0" value="net.max.msg.queue" />
    </bean>   
: destination을 설정한다.

<!-- JMS Template -->

    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="defaultDestination" ref="maxDestination"/>
        <!-- <property name="receiveTimeout" ref="60000"/> -->
        <property name="messageConverter" ref="memberConverter"/>
    </bean>
:jmsTemplate를 설정한다. 3개의 property값을 눈여겨 봐야 한다.

<!-- client sender
    <bean id="clientSender" class="net.max.msg.impl.ClientSenderImpl">
        <property name="jmsTemplate" ref="jmsTemplate"/>
    </bean>     
     
    <bean id="serverReceiver" class="net.max.msg.impl.ServerReceiverImpl">
        <property name="jmsTemplate" ref="jmsTemplate"/>
    </bean>       
-->
: component-scan 으로 인해 이것들은 필요 없어진다.

<!-- Converter -->
    <bean id="memberConverter" class="net.max.msg.impl.MemberMessageConverter"/>   
: converter는 Sender와 Receiver를 더욱 단순화 시킬수 있다. 만약 컨퍼터가 없으면 아래 Sender와 Receiver 클래스가 좀더 복잡해 진다.


4. 관련 Class 파일

ClientSenderImpl.java
@Service
public class ClientSenderImpl implements ClientSender {

    @Autowired
    private JmsTemplate jmsTemplate;
   
    @Override
    public void sendInfo(final Member member) {
        jmsTemplate.convertAndSend(member);
    }
}


ServerReceiverImpl.java
@Service
public class ServerReceiverImpl implements ServerReceiver {
    @Autowired
    private JmsTemplate jmsTemplate;
      
    public Member receive(){
         return (Member) jmsTemplate.receiveAndConvert();
    }
}


MemberMessageConverter.java
public class MemberMessageConverter implements MessageConverter {
 
    @Override
    public Object fromMessage(Message message) throws JMSException,
            MessageConversionException {
        if(!(message instanceof MapMessage)){
            throw new MessageConversionException("Messaeg isn't a MapMessage");
        }
       
        MapMessage mapMessage = (MapMessage) message;
        Member member = new Member();
        member.setName(mapMessage.getString("name"));
        member.setEmail(mapMessage.getString("email"));
        return member;
    }

    @Override
    public Message toMessage(Object object, Session session) throws JMSException,
            MessageConversionException {
        if(!(object instanceof Member)){
            throw new MessageConversionException("Messaeg isn't a Member");
        }
       
        Member member = (Member) object;
        MapMessage message = session.createMapMessage();
        message.setString("name", member.getName());
        message.setString("email", member.getEmail());
        return message;
    }



ClientSenderTest.java
public class ClientSenderTest {

    @Autowired
    private ClientSender clientSender;
    @Autowired
    private ServerReceiver serverReceiver;
       
    @Test
    public void testClientSender() throws Exception {
        Member member = new Member();
        member.setName("TaeHee1");
        member.setEmail("TaeHee@gmail.com");
        clientSender.sendInfo(member);
        member.setName("TaeHee2");
        clientSender.sendInfo(member);
        member.setName("TaeHee3");
        clientSender.sendInfo(member);
        member.setName("TaeHee4");
        clientSender.sendInfo(member);
        member.setName("TaeHee5");
        clientSender.sendInfo(member);
        member.setName("TaeHee6");
        clientSender.sendInfo(member);
        member.setName("TaeHee7");
        clientSender.sendInfo(member);
       
        Member sm1 = serverReceiver.receive();
        System.out.println("=========>"+sm1.getName());
        assertEquals(member.getEmail(),sm1.getEmail());
    }
}


5. Test 결과
큐에 의해 입력된 순차적으로 메시지를 가져오는것을 확인할수 있었다.
사용자 삽입 이미지

6. Resources
            Spring in Action CHAPTER10 Spring messaging

다음에는 Message-Driven(Listener) 기반으로 만들어 본다.
(과거 기선님이 테스트 해본것이 있지만 다시 해본다.)

(소스파일)
신고

'이전글(~2009)' 카테고리의 다른 글

처음부터 다시 만들기(과연...)  (0) 2008.02.12
Spring JMS 기본예제-2  (6) 2008.02.11
Spring JMS 기본예제-1  (6) 2008.02.04
Spring OSGi 학습하기 좋은곳은?  (7) 2008.01.29
먹기엔 덜익은 DDD 와 Rich Domain Model  (4) 2008.01.28
새해다짐  (2) 2008.01.11
posted by Max.
TAG ,