You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Christian Schubert-Huff (Jira)" <ji...@apache.org> on 2023/01/06 09:43:00 UTC
[jira] [Created] (CAMEL-18865) camel-main - Setters not invoked on bean that implements Map
Christian Schubert-Huff created CAMEL-18865:
-----------------------------------------------
Summary: camel-main - Setters not invoked on bean that implements Map
Key: CAMEL-18865
URL: https://issues.apache.org/jira/browse/CAMEL-18865
Project: Camel
Issue Type: Bug
Components: camel-main
Affects Versions: 3.20.0
Environment: jdk11, camel-main, camel-jms, IBM-MQ 9.2 (https://mvnrepository.com/artifact/com.ibm.mq/com.ibm.mq.allclient)
Reporter: Christian Schubert-Huff
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|https://www.ibm.com/docs/api/v1/content/SSFKSJ_9.2.0/com.ibm.mq.javadoc.doc/WMQJMSClasses/com/ibm/mq/jms/MQConnectionFactory.html]. 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:
{code:java}
camel.beans.mqConnectionFactory = #class:com.ibm.mq.jms.MQConnectionFactory
camel.beans.mqConnectionFactory.hostName = mqhost
{code}
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:
{code:java}
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;
}
}
{code}
and a unit test, which checks for the hostName:
{code:java}
@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();
}
{code}
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.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)