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)

Reply via email to