Spring JMS 侦听器应如何处理负载为空的消息?

How should a Spring JMS listener handle a message with an empty payload?

我正在为我工​​作的公司开发一个错误队列监控工具,我已经搞定了这个东西,运行 使用 Spring 引导使用注释设置我的所有 bean (而不是使用任何 xml)。该工具(到目前为止)按预期工作,除了在我们的错误队列(这是 IBM 的 MQ 系列)中,一些 xml 消息包含一个新行,我的 JMS 侦听器将其作为自己的东西拾取。事实上,它似乎专门逐行处理 xml 消息,而不是处理整个消息(尽管它处理整个 HL7 消息都很好)。此功能超出了我的知识范围,但这是它自己的问题。-

当我的 JMS 侦听器抓取这个换行符时,它会抛出一个异常,说明消息有效负载不能为空,然后在索引零处大吵大闹。它启动回滚并调用我的 JMSErrorhandler,问题是尽管它停留在这个循环中(永远......)。从调试器来看,这个异常似乎发生在 Spring 代码中的某处,就在它进入我的 processOrder() 方法之前,因为它永远不会到达我的断点。我不在工作现场,所以我无法访问代码,也无法访问堆栈跟踪(希望我对错误的可怕解释就足够了),但我可以说监听器是直接从 Spring 站点:

@Component
public class MyService {

    @JmsListener(destination = "myDestination")
    public void processOrder(String data) { ... }
}

那么有什么我可以访问的吗?为了防止回滚发生,应该选择换行符之类的东西吗?此外,正如一般性陈述,换行符可能是由将这些消息放入队列的另一个应用程序引起的,但我想涵盖我的所有基础,并获得一些知识。

编辑:为了澄清,在我的侦听器能够处理消息之前,Spring 代码中某处抛出了异常。我明白了:

Caused by: org.springframework.messaging.converter.MessageConversionException: No converter found to convert to class java.lang.String, message=GenericMessage [payload=
  JMSMessage class: jms_none
  JMSType:          null
  JMSDeliveryMode:  2
  JMSExpiration:    0
  JMSPriority:      5
  JMSMessageID:     ID:414d5120514d5f4445565f595731202056d7ea6b28797f6b
  JMSTimestamp:     1460469585820
  JMSCorrelationID: null
  JMSDestination:   null
  JMSReplyTo:       null
  JMSRedelivered:   false
    JMSXAppID: perl                        
    JMSXDeliveryCount: 1
    JMSXUserID: cisadm      
    JMS_IBM_Character_Set: ISO-8859-1
    JMS_IBM_Encoding: 273
    JMS_IBM_Format: MQSTR   
    JMS_IBM_MsgType: 8
    JMS_IBM_PutApplType: 6
    JMS_IBM_PutDate: 20160412
    JMS_IBM_PutTime: 13594582, headers={JMS_IBM_Character_Set=ISO-8859-1, JMS_IBM_MsgType=8, JMSXUserID=cisadm      , jms_priority=5, JMS_IBM_Encoding=273, jms_timestamp=1460469585820, JMSXAppID=perl                        , JMS_IBM_PutApplType=6, JMS_IBM_Format=MQSTR   , jms_redelivered=false, JMS_IBM_PutDate=20160412, jms_deliveryMode=2, JMSXDeliveryCount=1, JMS_IBM_PutTime=13594582, id=1dfefda3-49cb-dfcc-1a31-b8087e3d6ebd, jms_expiration=0, jms_messageId=ID:414d5120514d5f4445565f595731202056d7ea6b28797f6b, timestamp=1460469638210}]
    at org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver.resolveArgument(PayloadArgumentResolver.java:118) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:139) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:108) ~[spring-messaging-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:90) ~[spring-jms-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    ... 10 more

不知道如何解决这个问题。建议?

这个观点足以让我倾向于 post 这个答案。我基本上用这个 post: 以更直接的方式重新问了这个问题,并得出了结论。从评论中吸取了别人的建议,简单地将参数类型从 String 更改为 javax.jms.Message。这允许具有空负载(即空字符串,甚至换行符)的消息不影响侦听器的流程,它只会处理它们。

现在您所要做的就是从传入的 Message 中提取字符串,然后您可以检查其内容并决定如何处理它。所以听众最终看起来像这样:(或者至少是我所做的)

@JmsListener
public void processOrder(Message message) throws JMSException {
     String convertedMessage = ((TextMessage) message).getText();
     :
     :
}

duffymo 是正确的,因为没有魔法在发生。正如您在另一个 post 中看到的那样,如果您不想使用这样的解决方案,您可以实现自己的消息转换器来处理消息。