【问题标题】:Using a @JmsListener to handle sendAndReceive and just send使用 @JmsListener 处理 sendAndReceive 并发送
【发布时间】:2016-05-12 21:34:40
【问题描述】:

我有一个带有@JmsListener 方法的spring 服务。它被客户端调用,通过 JmsMessagingTemplate.convertSendAndReceive() 发送消息。这很好用。

@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);

我正在尝试在客户端上实现仅用于进行convertSend 调用的功能。也就是说,客户端将发送并忘记,而不是等待响应。我打了这样一个电话,它确实在服务器端得到处理

 jmsMessagingTemplate.convertAndSend(myDestination, myObj);

但是,我在服务器端收到一个错误,表明请求消息不包含回复目标。这对我来说很有意义,因为我没有通过 jmsMessageTemplate 进行“接收”方法调用。但是,我不确定该怎么做。是否可以为同一个目的地使用另一个 JmsListener 方法,但专门处理“发送而不回复”请求,还是我必须创建一个单独的目的地和 ActiveMQQueue?基本上,我希望我的服务器/jms 侦听器能够在不需要时不发回响应。

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

【问题讨论】:

    标签: java jms activemq spring-jms


    【解决方案1】:

    您可以使用两个@JmsListeners 和selector 属性将不同的消息类型定向到每个侦听器。

    这需要发送者设置一个消息属性,然后在选择器表达式中使用。

    使用消息模板时会稍微复杂一些,因为您必须使用基本的JmsTemplate 构建新消息:

    jmsTemplate.convertSendAndReceive(dest, object, messagePostProcessor);
    

    messagePostProcessor 有一个方法

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

    然后在选择器中使用requiresReply=yes/no

    如果您想避免演员表并使用消息模板,则需要在(不同的)MessagePostProcessor 中使用MessageBuilder.fromMessage(message).setHeader(...).build()。在这种情况下,它是一个弹簧消息 Message 而不是 JMS Message

    编辑

    但是,如果您的听众可以从数据中判断是否需要回复,并且对于不需要回复的消息只返回 null,那么您真的不需要任何这些。

    【讨论】:

    • 好的,我查看了 MessagePostProcessor,但我认为这是一种异步接收响应的方法。 MessagePostProcessor 将在 JMS 发送之前执行吗?这似乎很有希望。
    • 是的;它是一种机制,允许您在将转换创建的 JMS 消息发送到 JMS 之前对其进行修改。
    • 好的,您指定的 convertSendAndReceive 似乎不存在。我想我需要指定目标类类型。
    • 我新建了一个org.springframework.messaging.core.MessagePostProcessor,但是org.springframework.messaging.Message上没有名为setStringProperty的方法
    • 请仔细阅读答案 - 根据您使用的是JmsTemplate 还是JmsMessagingTemplate,有两种不同的回调。较旧的 JmsTemplate 不支持泛型,因此您必须转换回复,但在这种情况下,它会更有效,因为您可以避免中间的 spring-messaging Message
    猜你喜欢
    • 2014-04-08
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多