Uploaded image for project: 'Camel'
  1. Camel
  2. CAMEL-18865

camel-main - Setters not invoked on bean that implements Map

    XMLWordPrintableJSON

Details

    • 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.

      Attachments

        Activity

          People

            davsclaus Claus Ibsen
            chrissh Christian Schubert-Huff
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: