How should a Spring JMS listener handle a message

2019-08-11 08:01发布

I'm working on a error queue monitoring tool for a company I work for and I have got this thing up and running using Spring Boot doing all my bean set up using annotations (as opposed to using any xml). The tool works (so far) as intended except for the fact that on our error queue (which is IBM's MQ series) some xml messages contain a new line which my JMS listener picks up as its own thing. In fact it would seem it exclusively processes xml message line by line as opposed as a whole message (though it processes entire HL7 messages just fine). This functionality is beyond my knowledge but that's its own question.-

When my JMS Listener grabs this newline character it tosses an exception stating that message payload cannot be empty and then rabbles about something at index zero. It initiates a rollback and calls my JMSErrorhandler, problem is though it stays in this loop (forever...). From the debugger it looks like this exception happens somewhere in the Spring code right before it steps into my processOrder() method as it never gets to my breakpoints. I'm not on the worksite so I don't have access to the code, nor a stacktrace (hopefully my terrible explanation of the error is sufficient), but I can say the listener is modeled directly from this, from the Spring site:

@Component
public class MyService {

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

So is there anything I have access to; to prevent the rollback from occurring should something like a newline character be picked up? Also, just as a general statement, the newline character could be caused by another application that puts these messages onto the queue, but I want to cover all my bases, and gain some knowledge.

EDIT: To clarify an exception is thrown somewhere in the Spring code before my listener is able to handle the message. I get this:

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

Not sure how to resolve this. Suggestions?

1条回答
甜甜的少女心
2楼-- · 2019-08-11 08:31

This has enough views to incline me to post this answer. I basically re-asked this question in a more direct manner with this post: Spring JMSListener - How should it handle empty payloads?, and came to a conclusion. Took someone else's suggestion from the comments and simply changed the parameter type from String to javax.jms.Message. This allows messages with an otherwise empty payload (i.e. empty strings, and even newline characters), to not affect the flow of the listener and it will just process them.

Now all you have to do is extract the string from the incoming Message and then you can check its contents and decide what to do with it. So the listener ends up looking like this: (or at least what I did)

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

duffymo was correct in that there is no magic going on. And as you can see in the other post, if you didn't want to use a solution such as this, you could implement your own message converter to do what you want with the message.

查看更多
登录 后发表回答