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

眉间皱痕 提交于 2021-02-08 10:25:22

问题


I got a JmsConfig configuration class that handles JMS events from a topic in the following way:

  • It defines a @Bean ConnectionFactory, containing an ActiveMQ implementation
  • It defines a @Bean JmsListenerContainerFactory instantiating a DefaultJmsListenerContainerFactory and passing it through Boot's DefaultJmsListenerContainerFactoryConfigurer
  • It defines a @Bean MessageConverter containing a MappingJackson2MessageConverter and setting a custom ObjectMapper
  • I use @JmsListener annotation pointing to myfactory on a method of my service. This is the only use I have for the topic, subscription alone.

Now I want to move to 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. 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.

It seems JmsMessageDrivenChannelAdapter is the proper equivalent, and I found a way:

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 !

How should this be implemented in an ultimate way?


回答1:


JmsListenerContainerFactory is specific for the @JmsListener, it's a higher level abstraction used to configure a DefaultMessageListenerContainer. Boot does not provide an auto configuration option for a raw DefaultMessageListenerContainer; you have to wire it up yourself. But you can still use the Boot properties...

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



回答2:


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(...).

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


来源:https://stackoverflow.com/questions/44887651/proper-ultimate-way-to-migrate-jms-event-listening-to-spring-integration-with-sp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!