简体   繁体   中英

Spring Boot multiple JMS connections

I'm developing Spring Boot application which must connect to several WebSphere JMS connections with different ports or even ip addresses. I need receive and send messages to different queues.

I took example of connection from this source - https://github.com/lzp4ever/IBM_WebSphere_MQ_Spring_Boot_JMS

But when i add second connectionFactory Spring Boot failes to start, it just don't know which once to use.

My question is How should i configure my config file to listen several queues? Is it good idea connecting SpringBoot app to several different JMS servers?

Solution

i just copy and paste same beans(like at git link above) second time and add Bean(name) to separate them. It was not work and then i added new JmsListenerContainerFactory bean to each of my config file.

One of my config file is:

@Bean(name = "mqQueueConnectionFactory2")
public MQQueueConnectionFactory mqQueueConnectionFactory2() {
    MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
    mqQueueConnectionFactory.setHostName(host);
    try {
        mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
        mqQueueConnectionFactory.setCCSID(1208);
        mqQueueConnectionFactory.setChannel(channel);
        mqQueueConnectionFactory.setPort(port);
        mqQueueConnectionFactory.setQueueManager(queueManager);
    } catch (Exception e) {
        logger.error("MQQueueConnectionFactory bean exception", e);
    }
    return mqQueueConnectionFactory;
}

@Bean(name = "userCredentialsConnectionFactoryAdapter2")
UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter2(@Qualifier("mqQueueConnectionFactory2") MQQueueConnectionFactory mqQueueConnectionFactory) {
    UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter = new UserCredentialsConnectionFactoryAdapter();
    userCredentialsConnectionFactoryAdapter.setUsername(username);
    userCredentialsConnectionFactoryAdapter.setPassword(password);
    userCredentialsConnectionFactoryAdapter.setTargetConnectionFactory(mqQueueConnectionFactory);
    return userCredentialsConnectionFactoryAdapter;
}

@Bean(name = "cachingConnectionFactory2")
//@Primary
public CachingConnectionFactory cachingConnectionFactory2(@Qualifier("userCredentialsConnectionFactoryAdapter2") UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter) {
    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
    cachingConnectionFactory.setTargetConnectionFactory(userCredentialsConnectionFactoryAdapter);
    cachingConnectionFactory.setSessionCacheSize(500);
    cachingConnectionFactory.setReconnectOnException(true);
    return cachingConnectionFactory;
}

@Bean(name = "jmsTransactionManager2")
public PlatformTransactionManager jmsTransactionManager2(@Qualifier("cachingConnectionFactory2") CachingConnectionFactory cachingConnectionFactory) {
    JmsTransactionManager jmsTransactionManager = new JmsTransactionManager();
    jmsTransactionManager.setConnectionFactory(cachingConnectionFactory);
    return jmsTransactionManager;
}

@Bean(name = "jmsOperations2")
public JmsOperations jmsOperations2(@Qualifier("cachingConnectionFactory2") CachingConnectionFactory cachingConnectionFactory) {
    JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
    jmsTemplate.setReceiveTimeout(receiveTimeout);
    return jmsTemplate;
}

@Bean
public JmsListenerContainerFactory<?> myFactory2(@Qualifier("cachingConnectionFactory2") CachingConnectionFactory connectionFactory,
                                                 DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    // This provides all boot's default to this factory, including the message converter
    configurer.configure(factory, connectionFactory);
    // You could still override some of Boot's default if necessary.
    return factory;
}

Then i change my sender code from this:

@Autowired
private JmsOperations jmsOperations;

to this

@Autowired
@Qualifier("jmsOperations2")
private JmsOperations jmsOperations;

also i change my receiver to:

@JmsListener(destination = "${project.queues.uzb.recieve}", containerFactory = "myFactory2")
public void receiveMessage(JMSTextMessage data) {
    
}

it seems to me it worked!!!

But one of my CachingConnectionFactory must be marked as @Primary. If i delete @Primaty from one of my config files then i am gettig this error:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2018-03-28 12:28:37 -


APPLICATION FAILED TO START


Description:

Parameter 1 of method myFactory in com.config.UzbConnection required a bean of type 'org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer' that could not be found.

Action:

Consider defining a bean of type 'org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer' in your configuration.

Thanks

Just my 2 cents. If you have problems with multiple JMS connections because you have a project using a mix of Spring-boot and JMS with Spring xml configuration to make your connection factory, you can disable autostart of spring-boot-jms with this in your application:

 @SpringBootApplication(exclude = {JmsAutoConfiguration.class})

this way you can mix both.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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