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

时间:2016-04-09 15:13:29

标签: java spring spring-boot ibm-mq spring-annotations

我正在为我工​​作的公司开发一个错误队列监控工具,我已经使用Spring Boot运行这个东西,并使用注释完成我的所有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

不确定如何解决此问题。建议?

1 个答案:

答案 0 :(得分:1)

这有足够的观点可以让我发布这个答案。我基本上用这个帖子Spring JMSListener - How should it handle empty payloads?以更直接的方式重新提出这个问题,并得出结论。从评论中获取了其他人的建议,只是将参数类型从String更改为javax.jms.Message。这允许具有其他空载荷的消息(即空字符串,甚至是换行符)不会影响监听器的流程,它只会处理它们。

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

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

duffymo是正确的,因为没有魔法发生。正如您在其他帖子中所看到的,如果您不想使用此类解决方案,您可以实现自己的消息转换器,以便根据消息执行所需的操作。