9

How to configure multiple remote activemq brokers (different IP address) in spring context? Below is the configuration for 1 remote broker. I am using camel to create routes that produce and consume messages from and to different queues in multiple remote brokers. Based on the following routes, how do the system knows which remote broker each queue belongs to?

  • List item

    from("direct:start").to("activemq:queue:outgoingRequests")

  • List item

    from("activemq:queue:incomingOrders").to("log:Events? showAll=true").to("bean:jmsService")

Spring context for 1 broker org.camel.routes

<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="tcp://10.1.11.97:61616" />
</bean>

<bean id="pooledConnectionFactory"
    class="org.apache.activemq.pool.PooledConnectionFactory" init-
            method="start" destroy-method="stop">
    <property name="maxConnections" value="8" />
    <property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>

<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="pooledConnectionFactory"/>
    <property name="concurrentConsumers" value="10"/>
</bean>

<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
    <property name="configuration" ref="jmsConfig"/>
</bean>
kenn3th
  • 1,187
  • 2
  • 22
  • 47

3 Answers3

19

Just add more components with different names

<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
   <property name="configuration" ref="jmsConfig"/>
</bean>

<bean id="activemq2" class="org.apache.activemq.camel.component.ActiveMQComponent">
   <property name="configuration" ref="myOtherJmsConfig"/>
</bean>

Then simply use the names:

<from uri="activemq:queue:MY.QUEUE"/><!-- get from "1st" ActiveMQ -->
<to uri="activemq2:queue:MY.QUEUE"/> <!-- put to same queue name on other ActiveMQ -->

Actually, you can call them whatever you want, like "EuropeanMarketBroker" or whatever fits in.

Petter Nordlander
  • 22,053
  • 5
  • 50
  • 84
  • It is possible to set the `connectionFactory` as a URI option? ``, I'm assuming it be a `ConnectionFactory` type, not component? – raffian Mar 18 '16 at 20:45
0

I have been trying to achieve this with the difference that my spring configuration is not in xml. It is helpful to know that you can achieve the same outcome by using spring annotations in a few ways.

The key to achieving this is registering the component with the desired name. For example:

camelContext.addComponent("activemq2", jmsComponentInstance);

There is two ways of achieving this. Namely by creating two beans with qualifiers which identifies them from each other and then wiring those beans and registering them as components. Alternatively (this is preferable) you can create the bean and register the component all at once. Below are examples of both:

1 - Create Bean and Register elsewhere

@Configuration
public class ClassA{    
  @Bean @Qualifier("activemq2") public JmsComponent createJmsComponent(){
      return JmsComponent.jmsComponentAutoAcknowledge(..);//Initialise component from externalised configs
  }
}

@Component
public class ClassB{

  @Autowired private CamelContext camelContext;

  @Autowired @Qualifier("activemq2")
  private JmsComponent jmsComponent;

  public void someMethod(){
    camelContext.addComponent("activemq2", jmsComponent);
  }
}

2 - Create Bean and Register in one place within your @Configuration bean.

@Bean @Autowired public JmsComponent createJmsComponent(CamelContext camelContext){
    JmsComponent component = JmsComponent.jmsComponentAutoAcknowledge(..);//Initialise component from externalised configs
    camelContext.addComponent("activemq2", component);//Add Component to camel context
    return component;//Return component instance
}
0

I addition of the two answers, here is my working solution with the latest SpringBoot using dedicated properties for both broker:

First, I define two Beans for each ConnectionFactory:

// gatewayRouterProperties is a java `record` mapped to the application.yml property file.
// One ConnectionFactory for the onPremise broker
@Bean
public ConnectionFactory jmsConnectionFactoryOnPrem() {
    ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
    activeMQConnectionFactory.setBrokerURL(gatewayRouterProperties.activeMq().brokerOnPrem().url());
    activeMQConnectionFactory.setUserName(gatewayRouterProperties.activeMq().brokerOnPrem().user());
    activeMQConnectionFactory.setPassword(gatewayRouterProperties.activeMq().brokerOnPrem().pass());
    return activeMQConnectionFactory;
}

// Another broker ConnectionFactory for the cloud AWS broker
@Bean
public ConnectionFactory jmsConnectionFactoryAws() {
    ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
    activeMQConnectionFactory.setBrokerURL(gatewayRouterProperties.activeMq().brokerAws().url());
    activeMQConnectionFactory.setUserName(gatewayRouterProperties.activeMq().brokerAws().user());
    activeMQConnectionFactory.setPassword(gatewayRouterProperties.activeMq().brokerAws().pass());
    return activeMQConnectionFactory;
}

And then I just define the two Beans ActiveMQComponent (the same as Peter's answer but using annotations):

@Bean(name = "activemq")
public ActiveMQComponent createActiveMQComponentOnPrem() {
    ActiveMQConfiguration amqConfig = new ActiveMQConfiguration();
    amqConfig.setConnectionFactory(jmsConnectionFactoryOnPrem());
    return new ActiveMQComponent(amqConfig);
}

@Bean(name = "activemq2")
public ActiveMQComponent createActiveMQComponentAws() {
    ActiveMQConfiguration amqConfig = new ActiveMQConfiguration();
    amqConfig.setConnectionFactory(jmsConnectionFactoryAws());
    return new ActiveMQComponent(amqConfig);
}

Note that I am using the bean name attribute and no need to add that manually in CamelContext.

After in my Camel route I just use my activemq components beans like this:


// 'activemq' component => AMQ on-prem
// 'activemq2' component => AMQ AWS

from("activemq:queue:QUEUE.TO.SYNC.TO.AWS")
    .routeId("gw-router-route-on-prem-to-aws")
    .autoStartup("{{autostart-enabled}}")
    .to("activemq2:queue:QUEUE.FROM.ON.PREM")
;
рüффп
  • 5,172
  • 34
  • 67
  • 113