2012-07-16 3 views
3

요구 사항 :onMessage()이 성공적으로 실행될 때까지 메시지가 대기열에 남아 있기를 원합니다. onMessage() 실행 중에 예외가 발생하고 처리되지 않으면 메시지가 리스너에게 다시 전달되어야합니다.onMessage()가 호출되면 JMS 비동기 메시지 처리에서 메시지가 큐에서 삭제됩니다.

Glassfish v2를 응용 프로그램 서버로 사용하고 있습니다. 대기열에서 메시지를 보내려면 OpenMQConnectionFactory 및 JmsTemplate을 사용하고 있습니다. MDB를 사용하고 있지 않음에 유의하십시오. 예외 던진 메시지를 다시 전달되지 않을 때

<bean id="openMQConnectionFactory" 
    class="com.is.br.util.OpenMqConnectionFactoryBean"> 
    <property name="imqAddressList" value="mq://localhost:7676" /> 
    <property name="imqDefaultUsername" value="admin" /> 
    <property name="imqDefaultPassword" value="admin" /> 
</bean> 

나는 모드를 인정할하지만 리스너에 AUTO_ACKNOWLEDGE을 시도했다.

MessageProducer.java

공공 무효 sendMessage 첨부 (최종 문자열 responseStream) {

System.out.println("Enter into IsJmsProducer.sendMessage method"); 

    try { 
     MessageCreator creator = new MessageCreator() { 
      public Message createMessage(Session session) { 
       ObjectMessage message = null; 
       try { 
        message = session.createObjectMessage(responseStream); 
        } catch (Exception e) { 
        System.out.println("Unable create a JMSMessage"); 
       } 
       return message; 
      } 
     }; 

     System.out.println("Sending message to destination: " + this.destination.toString()); 
     this.jmsTemplate.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE); 

     this.jmsTemplate.send(this.destination, creator); 
     System.out.println("SendMessage to queue successfully.");   
    } catch (Exception ex) { 
     System.out.println("SendMessage to queue Fail." + ex); 
    } 
    System.out.println("Exit from IsJmsProducer.sendMessage method"); 

} 

SampleJMSConsumer.java

public class SampleJMSConsumer implements MessageListener { 

    @Override 
    public void onMessage(Message message) { 
     throw new RuntimeException(); 
    } 
} 
다음

내가 this.jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);로와 청취자의 I에 노력 message.acknowledge(); 그리고 블록에서 나는 여전히 session.recover()라고 불리는 메시지가 재전송되지 않습니다.

SampleJMSConsumer.java

public class SampleJMSConsumer implements MessageListener { 

    @Override 
    public void onMessage(Message message) { 

     ObjectMessage objectMessage = (ObjectMessage) message; 
     Object object; 
     try { 
      object = objectMessage.getObject(); 
      if (object instanceof String) { 
       System.out.println("Message received - " + object.toString()); 
       throw new JMSException("JMS exception"); 
      } 
      message.acknowledge(); 
     } catch (JMSException e) { 
       session.recover(); 
     } 
    } 

}

내가 디버그 모드에서 프로그램을 실행하고 나는 브로커 관리 콘솔에서 큐에 메시지를 보내 내가 메시지하지만 같은 수를 볼 수 있어요 때 곧 메시지의 수인 onMessage()가 1 씩 줄어 듭니다. 이는 메시지가 대기열에서 사용되고 삭제됨을 의미합니다. 그 메시지는 "배달 된"것으로 간주됩니까? 예외가 발생했을 때 메시지가 재전송되지 않는 이유를 이해하도록 도와주십시오.

미리 감사드립니다.

+0

안녕하세요 Ashwini. 나는 비슷한 것을하려고 노력하고있다. JMSTemplate을 사용하여 메시지를 보내고 Listener는 DefaultMessageListenerContainer에 의해 시작됩니다. 내 문제는 복구 할 onMessage 메서드에 세션 개체가 없습니다. 위 코드에서 세션 객체를 Listner에 어떻게 전달합니까? –

답변

1

이것은 의도적으로 설계된 것으로, onmessage가 호출 될 때 전달됩니다. 예외에 대해 뭔가를 원한다면 try catch를 사용하여 처리 할 수 ​​있습니다.

메시지가 다시 대기열에 있다고 가정하면 어쨌든 소비 될 때 동일한 예외가 발생할 가능성이 높습니다.

ack 메커니즘은 올바른 전달을 보장해야합니다. 아마도 당신은 prpoducerside에게 새로운 메시지를 보내달라고 요청하는 거부 메커니즘을 가지고있을 것입니다.

+0

감사합니다 Aksel. 많은 JMS 자습서를 살펴 보았는데 JMS 메시지가 확인 될 때까지 성공적으로 소비 된 것으로 간주되지 않습니다. onMessage()가 메시지 및 소비자 충돌을받는 시나리오를 고려할 수 있습니다. 이 시나리오에서는 메시지가 처리되지 않으며 승인되지 않습니다. 이 경우 메시지가 재전송되어야합니다. – Ashwini

0

OpenMQ의 기본 세션 모드가 무엇인지 확인하는 것이 좋습니다. 일단 연결을 열면 변경할 수 없으므로 연결을 통해 연결을 지정해야합니다.

1

고객 확인이 적합합니다. onMessage() 메서드에서 처리가 끝나면 Acknowledge를 호출해야합니다. 그렇지 않으면 예외가 있으면 Acknowledge()를 호출하지 않습니다.

Session.Recovery()는 메시지 배달을 중지했다가 다시 시작합니다.메시지 배달은 마지막 수신 확인되지 않은 메시지의 것입니다.

+0

고마워 Shashi, 동일한 해결책을 시도했지만 문제는 onMessage()가 대기열에서 메시지를 가져 오는 즉시 호출됩니다. 대기열에 메시지가없는 경우 어떻게 메시지를 재전송 할 수 있습니까? – Ashwini

+2

아니요, CLIENT_ACKNOWLEDGE 세션을 사용할 때 onMessage 메소드에서 Acknowledge()를 호출 할 때까지 메시지가 제거되지 않습니다. 나는 당신이 당신의 시험에 다시 확인하는 것이 좋습니다. – Shashi

0

세션 생성시 세션 모드를 AUTO_ACK/DUPS_OK_ACK으로 설정해야합니다. 소비자 시작을위한 코드를 공유하지 않았습니다. 프로듀서는 세션 모드를 설정하지만 소비자는 세션 모드를 설정하지 않습니다.