Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
3.20.0
-
None
-
jdk11, camel-main, camel-jms, IBM-MQ 9.2 (https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient)
-
Unknown
Description
We are having trouble configuring camel-jms with IBM-MQ as runtime implementation, using camel-main.
Doing so requires the declaration of a connection factory, which, in our case, is com.ibm.mq.jms.MQConnectionFactory. Unfortunately, this class implements both javax.jms.ConnectionFactory and java.util.Map<java.lang.String,java.lang.Object>. Also, the setters of that class have side effects, that are non-trivial to reproduce.
What was really troubling us was that, contrary to intuition, defining a bean like this:
camel.beans.mqConnectionFactory = #class:com.ibm.mq.jms.MQConnectionFactory
camel.beans.mqConnectionFactory.hostName = mqhost
does not actually invoke the setHostName method on the factory. Instead, value "mqhost" is put under key "hostName" into the map.
Reproduction can be achieved with a quick custom class, like this:
package org.apache.camel.main; import java.util.HashMap; public class MyFooFactory extends HashMap<String, Object> { private String hostName; public String getHostName() { return hostName; } public void setHostName(String hostName) { this.hostName = hostName; } }
and a unit test, which checks for the hostName:
@Test public void testBindBeansDottedHybridMap() { Main main = new Main(); main.configure().addRoutesBuilder(new MyRouteBuilder()); // defining a factory bean main.addProperty("camel.beans.myfactory", "#class:org.apache.camel.main.MyFooFactory"); main.addProperty("camel.beans.myfactory.hostName", "localhost"); main.start(); CamelContext camelContext = main.getCamelContext(); assertNotNull(camelContext); Object bean = camelContext.getRegistry().lookupByName("myfactory"); assertNotNull(bean); assertInstanceOf(MyFooFactory.class, bean); MyFooFactory factory = (MyFooFactory) bean; assertEquals("localhost", factory.getHostName()); main.stop(); }
For a custom bean that is under our own control, I would consider implementing java.util.Map and having additional custom getters and setters with side-effects to be invalid, but the IBM-MQ JMS client is out of our control - and required for our use case.
If the dotted annotation is used, it may be preferable to check for a suitable setter first, and only if that is missing, to check if the bean implements java.util.Map.