15

In my project I add two different JmsListener but when I run project in ActiveMQ panel only one of these topics has consumer!

So should I add separate jmsListenerContainerFactory configuration for each JmsListener ??

@JmsListener(destination = "foo1")
public void foo1(final Message jsonMessage) throws JMSException {
    ...
}

@JmsListener(destination = "foo2")
public void foo12(final Message jsonMessage) throws JMSException {
    ...
}

edit: this is from JMS config file:

@Configuration
@EnableJms
public class FooJmsConfig {

    @Bean
    public ActiveMQConnectionFactory connectionFactory() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL(BROKER_URL);
        connectionFactory.setPassword(BROKER_USERNAME);
        connectionFactory.setUserName(BROKER_PASSWORD);
        connectionFactory.setUseCompression(true);
        connectionFactory.setClientID("FPP_API");
        connectionFactory.setConnectionIDPrefix("DRR");
        connectionFactory.setUseAsyncSend(true);
        return connectionFactory;
    }

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setConcurrency("1-1");
        factory.setPubSubDomain(true);
        factory.setSubscriptionDurable(true);
        return factory;
    }
}
Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
mohsenJsh
  • 2,048
  • 3
  • 25
  • 49
  • This is supported and your code snippet is correct, so your issue is elsewhere, you'll need to provide more information. – KeatsPeeks Feb 06 '18 at 11:14
  • @KeatsPeeks what is supported? using same jmsListenerContainerFactory for all jmsListeners? – mohsenJsh Feb 07 '18 at 09:31

3 Answers3

14

I find out that by moving setClientID() from ActiveMQConnectionFactory provider method to DefaultJmsListenerContainerFactory provider method,

I can have only one globaly ActiveMQConnectionFactory provider method and multiple DefaultJmsListenerContainerFactory provider method for each jmsListener:

So the final working code is:

JMSConfig file:

@Configuration
@EnableJms
public class FooJmsConfig {

@Bean
public ActiveMQConnectionFactory connectionFactory() {
    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
    connectionFactory.setBrokerURL(BROKER_URL);
    connectionFactory.setPassword(BROKER_USERNAME);
    connectionFactory.setUserName(BROKER_PASSWORD);
    connectionFactory.setUseCompression(true);

    connectionFactory.setConnectionIDPrefix("DRR");
    connectionFactory.setUseAsyncSend(true);
    return connectionFactory;
}

@Bean(name= "foo1")
public DefaultJmsListenerContainerFactory foo1() {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());
    factory.setConcurrency("1-1");
    factory.setPubSubDomain(true);
    factory.setSubscriptionDurable(true);

    connectionFactory.setClientID("FOO_1");
    return factory;
}

 @Bean(name= "foo2")
public DefaultJmsListenerContainerFactory foo2() {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());
    factory.setConcurrency("1-1");
    factory.setPubSubDomain(true);
    factory.setSubscriptionDurable(true);

    connectionFactory.setClientID("FOO_1");
    return factory;
}

}

and jms listeners will be

@JmsListener(destination = "foo1", containerFactory="foo1")
public void foo1(final Message jsonMessage) throws JMSException {
...
}

@JmsListener(destination = "foo2", containerFactory="foo2")
public void foo12(final Message jsonMessage) throws JMSException {
...
}
mohsenJsh
  • 2,048
  • 3
  • 25
  • 49
7

I think the issues lies in the fact that you have set the concurrency on 1 for the JmsListenerContainerFactory used by both listeners.

If needed you can create multiple JmsListenerContainerFactory and set them for a JmsListener by specifying the JmsListener#containerFactory property.

0

You can have multiple JMSFactory connections established. Default JMS listeners only accepts singleton connectionfactory object. So you need to setup two beans of jmslistenercontainerfactory itself.

The code for the connection to the individual topic would be like this:

@Configuration
@EnableJms
@EnableTransactionManagement
public class JMSConnectionConfig{

private static final String AMQP_URI_FORMAT = "amqps://%s?amqp.idleTimeout=%d";

private int idleTimeout;

private String hostURL;

@Bean(name = "cachingConnectionFactory1")
@Primary
public ConnectionFactory myConnectionFactory1() {
    // set up connection details to the topic
    String remoteUri = String.format(AMQP_URI_FORMAT, hostURL, idleTimeout);
    JmsConnectionFactory jmsConnectionFactory = new JmsConnectionFactory();
    jmsConnectionFactory.setRemoteURI(remoteUri);
    jmsConnectionFactory.setClientID(clientId);
    jmsConnectionFactory.setUsername(topic1SASName);
    jmsConnectionFactory.setPassword(topic1SASKey);
    // create caching factory object and return as connectionfactory parent object
    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
    cachingConnectionFactory.setTargetConnectionFactory(jmsConnectionFactory);
    cachingConnectionFactory.setReconnectOnException(true);
    return cachingConnectionFactory;
}

@Bean(name = "factory1")
public JmsListenerContainerFactory<?> factory1(@Qualifier("cachingConnectionFactory1") ConnectionFactory connectionFactory,
                                                DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory topicFactory = new DefaultJmsListenerContainerFactory();
    topicFactory.setConnectionFactory(connectionFactory);
    topicFactory.setSubscriptionDurable(Boolean.TRUE);
    // configure DefaultJmsListenerContainerFactoryConfigurer with caching factory and listener factory
    configurer.configure(topicFactory, connectionFactory);
    return topicFactory;
}

// Goes here for another topic in the same way as above two methods to establish initial connection to the topic
}

The code for JMS listener message receiver class will be like this, you can provide destination as your topic name and for factory, you can provide bean of conenction factory we setup as above:

@JmsListener(destination = "${topic.name}", containerFactory = "factory1",
        subscription = "${topic.subscription.name}")
public void receiveMessage(JmsTextMessage jmsTextMessage) throws JMSException, IOException, InterruptedException {
    // listener code goes here
}
YAP
  • 451
  • 5
  • 6