简体   繁体   English

迁移JMS事件以侦听Spring Boot with Spring Boot的正确最终方法

[英]Proper ultimate way to migrate JMS event listening to Spring Integration with Spring Boot

I got a JmsConfig configuration class that handles JMS events from a topic in the following way: 我得到了一个JmsConfig配置类,该配置类以以下方式处理主题的JMS事件:

  • It defines a @Bean ConnectionFactory , containing an ActiveMQ implementation 它定义了一个@Bean ConnectionFactory ,其中包含一个ActiveMQ实现。
  • It defines a @Bean JmsListenerContainerFactory instantiating a DefaultJmsListenerContainerFactory and passing it through Boot's DefaultJmsListenerContainerFactoryConfigurer 它定义一个@Bean JmsListenerContainerFactory实例化DefaultJmsListenerContainerFactory并将其通过Boot的DefaultJmsListenerContainerFactoryConfigurer
  • It defines a @Bean MessageConverter containing a MappingJackson2MessageConverter and setting a custom ObjectMapper 它定义了一个@Bean MessageConverter其中包含一个MappingJackson2MessageConverter并设置了一个自定义ObjectMapper
  • I use @JmsListener annotation pointing to myfactory on a method of my service. 我在服务的方法上使用@JmsListener注释指向myfactory。 This is the only use I have for the topic, subscription alone. 这是我仅对订阅有此主题的唯一用途。

Now I want to move to Spring Integration . 现在我想转向Spring Integration After reading a lot, and provided I don't need a bidirectional use (discarding Gateways ) neither a polling mechanism (discarding @InboundChannelAdapter ), I am going for a message-driven-channel-adapter , in traditional XML configuration wording. 在阅读了很多书之后,并且假设我不需要双向使用(丢弃Gateway )和轮询机制(丢弃@InboundChannelAdapter ),我将使用传统的XML配置文字中的message-driven-channel-adapter I found that Java idiom should be accomplished by means of the new Spring Integration DSL library, and thus, I look for the proper snippet. 我发现Java习惯用法应该通过新的Spring Integration DSL库来完成,因此,我正在寻找适当的代码段。

It seems JmsMessageDrivenChannelAdapter is the proper equivalent, and I found a way: 似乎JmsMessageDrivenChannelAdapter是适当的等效项,我找到了一种方法:

IntegrationFlows.from(Jms.messageDriverChannelAdapter(...))

But the problem is that this only accepts the ActiveMQ ConnectionFactory or an AbstractMessageListenerContainer , but no my boot pre-configured JmsListenerContainerFactory ! 但是问题在于,这仅接受ActiveMQ ConnectionFactory或AbstractMessageListenerContainer ,而不接受我的引导预先配置的JmsListenerContainerFactory

How should this be implemented in an ultimate way? 应该如何最终实现呢?

JmsListenerContainerFactory is specific for the @JmsListener , it's a higher level abstraction used to configure a DefaultMessageListenerContainer . JmsListenerContainerFactory专门用于@JmsListener ,它是用于配置DefaultMessageListenerContainer的更高级别的抽象。 Boot does not provide an auto configuration option for a raw DefaultMessageListenerContainer ; 引导程序不为原始DefaultMessageListenerContainer提供自动配置选项; you have to wire it up yourself. 您必须自己连接。 But you can still use the Boot properties... 但是您仍然可以使用Boot属性...

@Bean
public IntegrationFlow flow(ConnectionFactory connectionFactory, 
                            JmsProperties properties) {
    return IntegrationFlows.from(Jms.messageDrivenChannelAdapter(container(connectionFactory, properties)))
            ...
            .get();
}

private DefaultMessageListenerContainer container(ConnectionFactory connectionFactory, 
                                                  JmsProperties properties) {
    DefaultMessageListenerContainer container = new DefaultMessageListenerContainer();
    container.setConcurrentConsumers(properties.getListener().getConcurrency());
    container.setMaxConcurrentConsumers(properties.getListener().getMaxConcurrency());
    ...
    return container;
}

There is even a better approach. 甚至有更好的方法。 I am surprised Gary did not comment it. 我很惊讶加里没有对此发表评论。 There's an out-of-the-box builder called Jms.container(...) . 有一个开箱即用的生成器,名为Jms.container(...)

@Bean
public IntegrationFlow jmsMyServiceMsgInboundFlow(ConnectionFactory connectionFactory, MessageConverter jmsMessageConverter, MyService myService, JmsProperties jmsProperties, @Value("${mycompany.jms.destination.my-topic}") String topicDestination){

      JmsProperties.Listener jmsInProps = jmsProperties.getListener();

      return IntegrationFlows.from(
                                Jms.messageDrivenChannelAdapter(  Jms.container(connectionFactory, topicDestination)
                                                                     .pubSubDomain(false)
                                                                     .sessionAcknowledgeMode(jmsInProps .getAcknowledgeMode().getMode())
                                                                     .maxMessagesPerTask(1)
                                                                     .errorHandler(e -> e.printStackTrace())
                                                                     .cacheLevel(0)
                                                                     .concurrency(jmsInProps.formatConcurrency())
                                                                     .taskExecutor(Executors.newCachedThreadPool())
                                                                     .get()))
                                   )
                                   .extractPayload(true)
                                   .jmsMessageConverter(jmsMessageConverter)
                                   .destination(topicDestination)
                                   .autoStartup(true)
                                    //.errorChannel("NOPE")
                             )
                             .log(LoggingHandler.Level.DEBUG)
                             .log()
                             .handle(myService, "myMethod", e -> e.async(true).advice(retryAdvice()))
                             .get();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM