I am using Apache Camel and I defined a route receiving inputs from 2 queues located on 2 distinct servers. I want ideally to consume from both server but I also want to be able to run the application when one of the 2 destinations is down.

Here's my route:

    try {
        from("mccdsJmsRequest1:queue:{{mccds.queues.in}}").to("direct:apolloMccdsRoute");
    } catch (Exception e){
        // debug line
        System.out.println("Ms1 not reachable");
        e.printStackTrace();
    }
    try {
        from("mccdsJmsRequest2:queue:{{mccds.queues.in}}").to("direct:apolloMccdsRoute");
    } catch (Exception e){
        // debug line
        System.out.println("Ms2 not reachable");
        e.printStackTrace();
    }

    from("direct:apolloMccdsRoute").routeId("apolloMCCDSRoute")
   // Main route starts here...

I declare my beans here:

@Bean
public JndiObjectFactoryBean mccdsJmsConnectionFactory1() {
    JndiObjectFactoryBean cf = new JndiObjectFactoryBean();
    cf.setJndiEnvironment(prodMccdsJndiProperties.getJndi1());
    cf.setJndiName(jndiName1);
    return cf;
}

@Bean
public JndiObjectFactoryBean mccdsJmsConnectionFactory2(){
    JndiObjectFactoryBean cf = new JndiObjectFactoryBean();
    cf.setJndiEnvironment(prodMccdsJndiProperties.getJndi2());
    cf.setJndiName(jndiName2);  
    return cf;
}

@Inject
private CamelContext camelContext;

@Bean
public JmsComponent mccdsJmsRequest1() {
    JmsComponent ac = new JmsComponent(camelContext);
    ac.setConnectionFactory((ConnectionFactory) mccdsJmsConnectionFactory1().getObject());
    ac.setConcurrentConsumers(5);
    return ac;
}

@Bean
public JmsComponent mccdsJmsRequest2(){
    JmsComponent ac = new JmsComponent(camelContext);
    ac.setConnectionFactory((ConnectionFactory) mccdsJmsConnectionFactory2().getObject());
    ac.setConcurrentConsumers(5);
    return ac;
}

If one of the connection factory is not reachable the application doesn't start. I would like to catch an ignore the exception:

o.s.b.f.s.DefaultListableBeanFactory     : Bean creation exception on non-lazy FactoryBean type check: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mccdsJmsConnectionFactory2' defined in class path resource [ca/bell/it/spa/uim/apollo/maximo/config/mccds/ProdMccdsJmsConfiguration.class]: Invocation of init method failed; nested exception is javax.naming.CommunicationException [Root exception is java.net.ConnectException: t3://someTestServerIP: Destination unreachable; nested exception is: 
java.net.ConnectException: Connection refused (Connection refused); No available router to destination]
2

There are 2 best solutions below

1
On BEST ANSWER

Try to set lookupOnStartup to false. (Add cf.setLookupOnStartup(false) to the mccdsJmsConnectionFactory1 and mccdsJmsConnectionFactory2 bean definitions.)

Also check this thread: http://forum.spring.io/forum/spring-projects/batch/95620-jndi-lookup

0
On

That won't work because your try/catch blocks are never executed during the execution of your route. In your code, you'd only get an exception during Camel's initial execution of this code upon application startup when it's building the route, when it doesn't care if your queues even exist or not.

Instead you need to determine when an error occurs in your route when it's executed after being constructed. There are a number of ways to do this, but a good start might be to look at Camel's Exception Clause

And alternative and perhaps even better choice is to make use of Camel's Load Balancer . It allows you to try any number of endpoints and failover to the next should one fail with an exception.