将消息路由到单独的errorQueue的问题

时间:2014-06-10 07:31:01

标签: java glassfish jms openmq

我有一个从队列中读取的MessageBean,我们将其命名为 MainQ。 如果onMessage代码的执行引发了一个基于用户的Exception,其类型我们将命名为 UserException ,我想抓住这个并将此消息放在名为 UserErrorQ 的单独Queue上。 如果异常不属于此类型,则抛出异常以由DMQ处理。

这是我的问题:

  • 在我的catch块中,我尝试通过ErrorQueueHandler将此新消息放在UserErrorQ上。当我尝试连接到connectionFactory以将消息发送到UserErrorQ时,这会导致错误。
  • 显然创建与QueueConnectionFactory(javax.jms.ConnectionFactory)的新连接导致问题

错误:

com.sun.messaging.jms.JMSException: MQRA:DCF:allocation failure:createConnection:Error in allocating a connection. Cause: javax.transaction.RollbackException 
at com.sun.messaging.jms.ra.DirectConnectionFactory._allocateConnection(DirectConnectionFactory.java:548)
at com.sun.messaging.jms.ra.DirectConnectionFactory.createConnection(DirectConnectionFactory.java:265)
at com.sun.messaging.jms.ra.DirectConnectionFactory.createConnection(DirectConnectionFactory.java:244)`

MessageBean:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void onMessage(Message message) {
   try{
    .
    .
   }catch(Exception e){
       if(isUserExceptionWrappedInException(e){
           errorQueueHandler.sendToErrorQueue(message);
       }
   }
}

private boolean isUserExceptionWrappedInException(Throwable t) {
    if (t == null)
        return false;
    else if (t instanceof UserException)
        return true;
    else
        return isUserExceptionWrappedInException(t.getCause());
}

ErrorQueueHandler:

public void sendToErrorQueue(Message message) {
    try {
        createConnection();
        send((TextMessage)message);
    } finally {
        closeConnection();
    }
}

private void createConnection() throws Exception {
    try {
        connection = connectionfactory.createConnection();
        connection.start();
    } catch (JMSException e) {
        String msg = "Error while attempting to initialize connection to jms destination " + ERROR_QUEUE;
        throw new OperationalException(msg, e, OperationalExceptionType.APPLIKASJONSTJENER);
    }
}

如上所述,尝试建立连接时会发生错误。有没有人解决这个问题?

1 个答案:

答案 0 :(得分:0)

所以,我已经找到了自己问题的答案。 connectionException的原因是ErrorQueueHandler不是EJB,而是通过CDI注入。回滚状态中不允许新的实例化,因为容器会丢弃bean实例,这就是失败的原因。我的REQUIRES_NEW注释也被忽略了,因为它属于javax api,它不会影响注入CDI的bean。

以下是一些需要注意的事项:

  1. 确保EJB具有构造函数或 public 构造函数。修饰符很重要,因为容器需要这些修饰符才能实例化EJB。

  2. 这种方法存在一些问题。

    • 当我尝试将消息写入单独的错误队列而不是DMQ时,我将不得不使用该消息而不是之后抛出错误。由于MDB处于回滚状态,因此JMS规范明确指出这将导致重新传递消息。您将体验到的是,在向您自定义errorQueue之后,该消息将立即反弹回队列,您现在拥有无限循环。
  3. 幸运的是,我也有一个解决方案: 这里的主要问题是控制您的交易。对于这种情况,我需要3个交易:

    1. MDB的一个事务,以便它能够确认消息事件,尽管我有一个RuntimeException。
    2. onMessage方法逻辑的一个事务,这样我可以在遇到异常时进行回滚,但仍然可以写入ErrorQueue。
    3. 在回滚状态下连接和写入ErrorQueue的一个事务。
    4. <强>代码:

      <强> MessageBean:

      @EJB
      QueueService queueService;
      
      @TransactionAttribute(TransactionAttributeType.REQUIRED)
      public void onMessage(Message message) {
        try{
          queueService.processMessageInNewTrasaction(message);
        }catch(Exception e){
          throw e;
        }
      }
      

      <强> QueueService:

      import javax.jms.Message;
      @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
      @Stateless
      public class QueueService {
      
        @EJB
        ErrorQueueHandler errorQueueHandler;
      
        public void processMessageInNewTransaction(Message message){
          try {
          .
          .
          } catch(Exception e) {
            if(isUserExceptionWrappedInException(e)
              errorQueueHandler.sendToErrorQueue(message);
          }
        }
      
        private boolean isUserExceptionWrappedInException(Throwable t) {
          if (t == null)
            return false;
          else if (t instanceof UserException)
            return true;
          else
            return isUserExceptionWrappedInException(t.getCause());
        }
      
      }
      

      <强> ErrorQueueHandler:

      @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
      @Stateless
      public class ErrorQueueHandler{
         public void sendToErrorQueue(Message message){
         .
         .
         }
      }
      

      有用的资源:http://weblogic-wonders.com/weblogic/2011/01/10/working-with-jms-and-the-standard-issues-in-jms/