在使用出站 jms 适配器时,我们可以 select 基于 MessageHeaders 动态地使用 JmsTemplate 吗?

Can we select JmsTemplate dynamically on the basis of MessageHeaders while using outbound jms adapter?

我已经创建了 2 个 jmsTemplate Bean,以便能够相应地处理向 Solace QueueSolace Topic 发送消息,现在当我在 exampleChannel 上传递消息时下面我想知道 MessageHandler 是否可以动态选择 jmsTemplate ?如果我用 MessageHeader 传递消息让我们说 destinationType=Topic/Queue

配置如下

    @Autowired
    @Qualifier("topic")
    private JmsTemplate jmsTemplate;
    
    @Autowired
    @Qualifier("queue")
    private JmsTemplate jmsTemplate1;

    @Bean
    @ServiceActivator(inputChannel = "exampleMessageChannel" )
    public MessageHandler archiveOutboundHandler() {

        /*
         I need to select between jmsTemplate & jmsTemplate1 on the basis on header 
         information. 
         **/
        JmsSendingMessageHandler messageHandler = new JmsSendingMessageHandler(jmsTemplete);
        messageHandler.setDestinationExpression(new FunctionExpression<Message<?>>(m->m.getHeaders().get("destination")));
        return messageHandler;
    }

可能吗?或者有更好的方法吗?

更新 1:

在@Artem 建议将 destinationExpression 的实现更改为 return Destination 之后,我这样做了

    @Bean
    @ServiceActivator(inputChannel = "outMessageChannel" )
    public MessageHandler archiveOutboundHandler() {
        JmsSendingMessageHandler messageHandler = new JmsSendingMessageHandler(jmsTemplate);
        messageHandler.setDestinationExpression(new FunctionExpression<Message<?>>(message -> {
            if((Objects.equals(message.getHeaders().get("destinationType"), "topic"))){
               return (Topic) () -> (String) message.getHeaders().get("destination");
            }else{
                return (Queue) () -> (String) message.getHeaders().get("destination");
            }
        }));
        return messageHandler;
    }

我低于异常

$$Lambda1/1572602632 cannot be cast to com.solacesystems.jms.SolDestination)

更新 2

我能够使用 JndiDestinationResolver

解析目的地

正如 Artem 建议使用 BeanFactoryDestinationResolver 那样,我使用它是不可行的,因为目的地太多并且 BeanFactoryDestinationResolver 需要为每个目的地创建特定的 bean。

我已经配置了 JndiDestinationResolver 所以我只需要注入 DestinationResolver 来解析目标。

下面是片段,

@Autowired
private JmsTemplate jmsTemplate;

@Autowired
private DestinationResolver destinationResolver;

@Bean
@ServiceActivator(inputChannel = "exampleChannel" )
public MessageHandler jmsOutboundHandler() {
    
    JmsSendingMessageHandler messageHandler = new JmsSendingMessageHandler(jmsTemplate);
    messageHandler.setDestinationExpression(new FunctionExpression<Message<?>>(message -> {
        if(message.getHeaders().get("dest_type").equals("topic")){
               return destinationResolver.resolveDestinationName(null,(String) message.getHeaders().get("dest"),true);
            
        }else{
               return destinationResolver.resolveDestinationName(null,(String) message.getHeaders().get("dest"),false);
        }
    }));
    return messageHandler;
}

感谢所有意见,我将提出 GH 问题以在 DynamicJmsTemplate

中包含 pubsub 功能

我明白你的意思了。

它的逻辑是这样的:

protected Destination resolveDestinationName(Session session, String destinationName) throws JMSException {
    return getDestinationResolver().resolveDestinationName(session, destinationName, isPubSubDomain());
}

默认 DynamicDestinationResolver 是这样的:

if (pubSubDomain) {
        return resolveTopic(session, destinationName);
    }
    else {
        return resolveQueue(session, destinationName);
    }

作为解决方法,考虑让 destinationExpression 被评估为 javax.jms.Destination 实例而不是它们的普通名称。这样你就不会被束缚在 pubSubDomain 属性.

还有一个 BeanFactoryDestinationResolver 可以将提供的名称从应用程序上下文解析为 Destination bean。

同时,我要求您提出一个 GH 问题,以便将 pubSubDomain 支持添加到 DynamicJmsTemplate API。因此,您将能够根据 JmsSendingMessageHandler.

中的表达式求值来确定 pubSubDomain