6

I asked basically the same thing a few months ago with this post: How should a Spring JMS listener handle a message with an empty payload?, but all I got was a measly comment suggesting I "re-write my listener to do what I want". Valid statement, but unclear in my eyes as I'm still coming to grips with Spring-Boot. I've learned since then and want to re-ask this question more directly (as opposed to placing a bounty on the old one).

I set up an annotated bean class with @Configuration and @EnableJms and my container factory looks like:

@Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(mqConnectionFactory());
        factory.setDestinationResolver(destinationResolver());
        factory.setConcurrency("1");
        factory.setErrorHandler(errorHandler());
        factory.setSessionTransacted(true);
        factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
        return factory;
    }

And the listener looks like:

@JmsListener(id = "qID", destination = "qName")
    public void processOrder(String message) {. . .}

As I understand it, once the annotated bean class gets ran through, the JMSListener basically kicks off (unless I set autoStartup to false), so I fail to understand where and when I have control over what or how the JmsListener handles things. From my perspective it "just runs". So if a queue has "\n" on it or just an empty string, the listener is going to throw an exception. Specifically org.springframework.messaging.converter.MessageConversionException: No converter found to convert to class java.lang.String. And this exception is thrown behind the scenes. I never get the chance to execute anything inside the listener

I looked into SimpleMessageConverter but didn't seem to see anything that would allow me to say something like setIgnoreStringPattern(). That obviously doesn't exist, but that's what I need. What am I missing? Is there a way to tell the JmsListener to ignore certain strings?

Community
  • 1
  • 1
LumberSzquatch
  • 1,054
  • 3
  • 23
  • 46
  • Can you explain a little bit more about why you need to support empty messages? – John K Aug 04 '16 at 16:59
  • @JohnK Sure. So we have IBM WebSphere MQ queues that other applications write to. My listener needs to keep tabs on the error queues. The error queues contain very strange messages. My app aims to rectify that by identifying useless messages. Like newline characters that get on queues that shouldn't be. – LumberSzquatch Aug 04 '16 at 17:03
  • I know that this doesn't answer your question but if you have control over what the other apps write to the queue, maybe the best answer is to make sure that the other apps write valid messages? Unless you don't have control over them in which case, nevermind. – John K Aug 04 '16 at 17:06
  • One other thing, have you tried changing processOrder to accept a byte array instead of a string? it might get around the failed conversion. – John K Aug 04 '16 at 17:11
  • @JohnK Yes I do have access to them and that is also part of my task, but we have many queues with thousands of messages. I got to have all my bases covered. And no I have not tried changing the parameter type. That didn't come to mind actually. – LumberSzquatch Aug 04 '16 at 17:17
  • 2
    Instead of `String` use the plain `javax.jms.Message` and do the extracting and converting yourself. – M. Deinum Aug 05 '16 at 07:22

3 Answers3

3

I took M. Deinum's suggestion (as it seemed quick and clean) and simply made the parameter type javax.jms.Message then converted the incoming message into a string. So my Listener now looks like

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

This may throw a JMSException, but I'm not too concerned with that as now when my implemented ErrorHandler class is called, I'll now know why and can do something more specific to handle a failed conversion. This does exactly what I need it to.

Edit: And in response to Jonh K's suggestion, the listener did not like having byte[] as a parameter. It basically wanted a converter to convert from byte array to string. Opted out of implementing my own custom converter.

LumberSzquatch
  • 1,054
  • 3
  • 23
  • 46
  • This is not valid for the latest version of Spring. – Michael Rountree Apr 22 '20 at 20:08
  • @MichaelRountree considering spring 5.2.7 uses [SimpleMessageConverter.fromMessage(Message message)](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jms/support/converter/SimpleMessageConverter.html), what is leading you to believe that this is invalid code? – Brad Aug 06 '20 at 15:58
3
@JmsListener(destination = "stompmessage")
public void receiveStomp(byte[] data, @Headers Map<Object, Object> allHeaders) {
   System.out.println("Stomp message: "+ new String(data));
}

Version for spring in 2019-2020

M. Dicon
  • 41
  • 2
1

You can add a custom message converter to the listener container factory and do whatever you want with the incoming message.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179