2012-05-07 2 views
2

동일한 'main'스레드에서 DefaultMessageListenerContainer를 실행하려는 경우가 있습니다. 지금은 SimpleAsyncTaskExecutor를 사용하여 메시지를받을 때마다 새 스레드를 생성합니다.'main'스레드에서 DefaultMessageListenerContainer를 실행하는 방법

우리는 다른 분산 시스템에 연결하여 처리를 수행하고 결국에는 몇 가지 것을 주장하는 테스트 케이스를 가지고 있습니다. DefaultMessageListenerContainer는 별도의 스레드에서 실행되므로 DefaultMessageListenerContainer가 완료되기 전에 주 스레드가 반환하고 실행을 시작합니다. 이로 인해 테스트 케이스가 실패하게됩니다. 해결 방법으로 주 스레드를 몇 초 동안 잠자기 상태로 만들었습니다.

샘플 설정

<int-jms:message-driven-channel-adapter 
     id="mq.txbus.publisher.channel.adapter" 
     container="defaultMessageListenerContainer" 
     channel="inbound.endpoint.publisher" 
     acknowledge="transacted" 
     extract-payload="true" /> 

    <beans:bean id="defaultMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> 
    <beans:property name="connectionFactory" ref="mockConnectionFactory"/> 
    <beans:property name="destination" ref="publisherToTxmQueue"/> 
    <beans:property name="taskExecutor" ref="taskExecutor"/> 
    <beans:property name="maxMessagesPerTask" value="10"/> 
    <beans:property name="sessionTransacted" value="true"/> 
</beans:bean> 

<beans:bean id="taskExecutor" class="org.springframework.scheduling.timer.TimerTaskExecutor" /> 

나는 그것이 하나의 스레드를 만들지 만 문제가 해결되지 않은, 그래서 그 스레드가 메인 스레드가 아닌 별도이기 때문에 여기 TimerTaskExecutor를 사용하는 것을 시도하고있다. SyncTaskExecutor를 사용하여 시도했지만 그 중 하나가 작동하지 않습니다 (또는 dint가 올바른 속성 값을 제공 할 수 있습니까?).

답변 :
우리는 SimpleMessageListenerContainer를 사용하여이 문제를 해결했다. 이 새로운 설정

 <int-jms:message-driven-channel-adapter 
     id="mq.txbus.publisher.channel.adapter" 
     container="messageListenerContainer" 
     channel="inbound.endpoint.publisher" 
     acknowledge="transacted" 
     extract-payload="true" /> 

<beans:bean id="messageListenerContainer" class="org.springframework.jms.listener.SimpleMessageListenerContainer">  
    <beans:property name="connectionFactory" ref="mockConnectionFactory"/>  
    <beans:property name="destination" ref="publisherToTxmQueue"/> 
    <beans:property name="sessionTransacted" value="true"/> 
    <beans:property name="exposeListenerSession" value="false"/> 
</beans:bean> 

답변

1

먼저 은 본질적으로 비동기 및 차단하지 않는다는 것을 이해해야에게 있습니다. 즉, 대기열에 메시지를 보내면 다른 시스템에서 다른 스레드에 의해 처리되고, 그렇지 않은 경우 몇 분 또는 몇 시간 후에 메시지가 처리됩니다.

테스트 사례에 대한 설명을 읽으면 일부 시스템/통합 테스트를 수행하는 것처럼 보입니다. 불행히도 기다리지 않고 할 수있는 일은 많지 않습니다. 그러나 테스트가 느려지지만 안정적이지 않기 때문에 맹목적으로 기다려서는 안됩니다. 아무리 오래 기다리더라도 바쁜 시스템이나 긴 GC 과정에서 테스트가 아직 시간이 걸릴 수도 있습니다. 오류가없는 경우에도 오류가 없습니다.

그래서 고정 된 시간 (예 : 수면) 동안자는 대신. ~ 100 밀리 초 및 메시지 처리가 완료되었을 때 만 충족되는 일부 조건을 확인하십시오. 예를 들어 메시지 처리 중 일부 레코드를 데이터베이스에 삽입하는 경우 데이터베이스를 주기적으로 확인하십시오.

구현 방법은 request/repply pattern을 구현하는 것이 훨씬 더 세련된 방법입니다. 자세한 내용은 How should I implement request response with JMS?을 참조하십시오. 기본적으로 메시지를 보낼 때 응답 대기열을 정의하고 대기열에서 메시지 대기를 차단합니다. 원래 메시지 처리가 끝나면 소비자는 정의 된 큐로 응답 메시지를 보내야합니다. 그 메시지를 받으면 모든 단언을 수행하십시오.

+0

감사합니다. 토마스! 이것은 매우 도움이됩니다. 또한 Mark Fisher가 메인 스레드에서이 리스너를 실행할 수 없다는 것을 분명히 한 곳에서 springforum에이 내용을 게시했습니다. http://forum.springsource.org/showthread.php?126158-How-to-run-DefaultMessageListenerContainer-on-the-main-thread –

0

테스트 목적으로 사용하는 경우 jms 활동이 완료되면 어설 션을 실행하는 CyclicBarrier를 사용하지 않는 것이 좋습니다.

관련 문제