1
votes

I have a spring service that has @JmsListener method. It gets invoked by a client send out a message via JmsMessagingTemplate.convertSendAndReceive(). This works fine.

@Service
public class JmsMessageProcessor {
    @JmsListener(destination = "myDestination")
    protected Message<MyResponseObj> handleRequest(final MyInputObj myObj) {
        return MessageBuilder.withPayload(processObj(myObj)).build();
    }

}

.

// client
 MyResponseObj response = jmsMessagingTemplate.convertSendAndReceive(myDestination, myObj,
                MyResponseObj.class);

I'm attemptign to implement on the client, functionality for just doing a convertSend call. That is, the client will send and forget, and not wait for a response. I have made such a call, and it does get processed on the server side

 jmsMessagingTemplate.convertAndSend(myDestination, myObj);

But, I get an error on the server side indicating that the request message does not contain a reply-to destination. This makes some sense to me, because i'm not doing a "receive" method call via the jmsMessageTemplate. But, I'm not sure what to do about this. Is it possible to have another JmsListener method for the same destination, but handle specificaly the "send without reply" requests, or do i have to create a seperate destination and ActiveMQQueue? Basically, I want my server / jms listener to be able to not send back a response if it doesn't need to.

javax.jms.InvalidDestinationException: Cannot determine response destination: Request message does not contain reply-to destination, and no default response destination set.
org.springframework.jms.listener.adapter.ReplyFailureException: Failed to send reply with payload [GenericMessage [payload=MyResponseObj@51c082ec, headers={timestamp=1462996638601, id=41877e45-b220-a320-f07a-64f9d50d98ae}]]; nested exception is javax.jms.InvalidDestinationException: Cannot determine response destination: Request message does not contain reply-to destination, and no default response destination set.
        at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.handleResult(AbstractAdaptableMessageListener.java:249) ~[spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:68) ~[spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:721) ~[spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:681) [spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:651) [spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:315) [spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:253) [spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1150) [spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1142) [spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1039) [spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at java.lang.Thread.run(Thread.java:745) [?:1.7.0_99]
Caused by: javax.jms.InvalidDestinationException: Cannot determine response destination: Request message does not contain reply-to destination, and no default response destination set.
        at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.getResponseDestination(AbstractAdaptableMessageListener.java:343) ~[spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.getResponseDestination(AbstractAdaptableMessageListener.java:316) ~[spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener.handleResult(AbstractAdaptableMessageListener.java:245) ~[spring-jms-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        ... 10 more
1

1 Answers

4
votes

You can use two @JmsListeners and the selector property to direct the different message types to each listener.

This requires the sender to set a message property that is then used in the selector expression.

It's a bit more complicated when using the messaging template because you have to build a new message but with the basic JmsTemplate:

jmsTemplate.convertSendAndReceive(dest, object, messagePostProcessor);

where messagePostProcessor has a method

public Message postProcessMessage(Message message) {
    message.setStringProperty("requiresReply", "yes");
    return message;
}

Then use requiresReply=yes/no in the selector.

If you want to avoid the cast and use the messaging template, you need to use MessageBuilder.fromMessage(message).setHeader(...).build() in the (different) MessagePostProcessor). In this case it's a spring-messaging Message not a JMS Message.

EDIT

You really don't need any of this, though, if your listener can tell from the data whether a reply is expected and simply returns null for messages that don't need a reply.