【问题标题】:Send message using spring integration to non jms client使用 spring 集成向非 jms 客户端发送消息
【发布时间】:2021-03-17 14:28:21
【问题描述】:

我需要通过 IBM MQ 将消息从 spring 集成发送到非 jms 应用程序

我已尝试发送消息,但不幸的是,接收方非 jms 应用程序无法使用,因为消息中包含不需要的 Jms 标头并获取数据格式异常

如何在使用 spring 集成向非 jms 应用程序发送消息之前删除 jms 标头

我在 IBM MQ 站点中找到了一些参考链接

https://www.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.dev.doc/q032140_.htm

【问题讨论】:

  • 我将其标记为 close as dup 的答案描述了如何“如何在使用 spring 集成向非 jms 应用程序发送消息之前删除 jms 标头”。下面提供的答案莫拉格是如何强制将它们从非 jms 应用程序消费的目标队列中删除。
  • @JoshMc 是对的。它很可能是重复的。但是链接问题中缺少的是对章节Creating destinations in a JMS application 的引用。通过本章的信息,很明显您可以在 Spring Integration 中配置您的请求队列,如下所示 queue:///YOUR.REQ.QUEUE?targetClient=1 以省略 RFH2 标头。

标签: spring-integration ibm-mq spring-jms


【解决方案1】:

为确保使用的 IBM MQ 应用程序不理解 JMS(以及使用消息属性的其他应用程序)添加的无关标头,请对非 JMS 应用程序从中获取的队列进行以下更改。

ALTER QLOCAL(queue-name) PROPCTL(NONE)

这样做的好处是,任何了解如何处理 JMS 标头的应用程序仍然可以接收它们。在放置时删除标头的其他解决方案会导致所有应用程序不接收标头。此解决方案允许那些可以接收它们的人以及那些不能接受它们的人不受它们的影响。

当您有多种应用程序时,这是一个非常好的解决方案。它还允许通过简单的管理命令进行“修复”,而不需要更改应用程序。

【讨论】:

  • 另一个选项是让获取应用程序指定MQGMO_NO_PROPERTIES。这具有不依赖非默认队列属性的额外好处,并且在应用程序控件中。
  • 确实 - 如果您有能力更改应用程序,这相当于对应用程序进行的更改。
【解决方案2】:

有很多方法可以做到这一点,从 cmets 的传播和您已经收到的答案中可以看出。你如何做到这一点真的取决于你。

正如丹尼尔所说,您可以修改队列网址。

正如 Morag 所说,您可以使用 MQSC 来更改队列。

您也可以通过代码执行此操作。您没有提供任何代码,因此很难告诉您如何执行此操作,但如果您将目标(队列)转换为 MQDestination,则可以使用 IBM JMS API 排除 RFH2 标头。

RFH2 将被排除

    import javax.jms.Destination;
    import com.ibm.mq.jms.MQDestination;
    import com.ibm.msg.client.wmq.WMQConstants;
    ...

    Destination destination = ...
    ...


    MQDestination mqDestination = (MQDestination) destination;
    destination.setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ);

我在 Spring 中使用此服务对此进行了测试


import com.ibm.mq.jms.MQDestination;
import com.ibm.msg.client.wmq.WMQConstants;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

import javax.jms.*;

@Service
public class SendMessageNonJmsService {

    protected final Log logger = LogFactory.getLog(getClass());

    final private JmsTemplate myNonJmsTemplate;

    @Autowired
    private ConnectionFactory connectionFactory;

    SendMessageNonJmsService(JmsTemplate myNonJmsTemplate) {
        this.myNonJmsTemplate = myNonJmsTemplate;
    }

    public void sendAsNonJms(String msg) {
        Destination destination = null;
        JMSContext context = connectionFactory.createContext();
        destination = context.createQueue("queue:///audit");
        try {
            MQDestination mqDestination = (MQDestination) destination;
            mqDestination.setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ);
        }
        catch (JMSException ex) {
            logger.warn("JMSException preparing message destination : "
                            + ex.getErrorCode() + " : "
                            + ex.getMessage());
        }
        myNonJmsTemplate.send(destination, session -> session.createTextMessage(msg));
    }

}

如果您希望发送代码尽可能简单

    public void sendAsNonJms(String msg) {
        myNonJmsTemplate.send("audit", session -> session.createTextMessage(msg));
    }

然后你可以在你的 JmsTemplate 上设置一个目标解析器

    @Bean("myNonJmsTemplate")
    public JmsTemplate myNonJmsTemplate() {
        JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
        jmsTemplate.setDestinationResolver(new OurDestinationResolver());
        return jmsTemplate;
    }

你的目标解析器看起来像这样:

import com.ibm.mq.jms.MQDestination;
import com.ibm.msg.client.wmq.WMQConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.support.destination.DestinationResolver;

import javax.jms.*;

public class OurDestinationResolver implements DestinationResolver {

    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ConnectionFactory connectionFactory;

    @Override
    public Destination resolveDestinationName(Session session, String dest, boolean pubSub) throws JMSException {
        Destination destination = null;

        if (pubSub) {
            destination = session.createTopic(dest);
        } else {
            destination = session.createQueue(dest);
        }

        MQDestination mqDestination = (MQDestination) destination;
        mqDestination.setTargetClient(WMQConstants.WMQ_CLIENT_NONJMS_MQ);

        return destination;
    }
}

【讨论】:

    猜你喜欢
    • 2017-05-03
    • 1970-01-01
    • 2015-07-05
    • 2012-01-20
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    相关资源
    最近更新 更多