5 Replies Latest reply on Dec 31, 2014 4:00 PM by jbertram

    hornetq-jms.xml queue names

    pminearo

      I have the following hornetq-jms.xml file:

       

      <configuration xmlns="urn:hornetq"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
      
      
          <connection-factory name="ConnectionFactory">
              <connectors>
                  <connector-ref connector-name="in-vm"/>
              </connectors>
              <entries>
                  <entry name="ConnectionFactory"/>
              </entries>
          </connection-factory>
      
          <queue name="testQueue">
              <entry name="/queue/testQueue"/>
          </queue>
      
      </configuration>
      


      I am using org.hornetq.integration.spring.SpringJmsBootstrap to start an embedded HornetQ server.  What I want to be able to do is have the queue names come from a properties file.  Is there a way to use get the queue names from the Spring Property Placeholder?  For example:


      <configuration xmlns="urn:hornetq"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
          
          <connection-factory name="ConnectionFactory">
              <connectors>
                  <connector-ref connector-name="in-vm"/>
              </connectors>
              <entries>
                  <entry name="ConnectionFactory"/>
              </entries>
          </connection-factory>
      
          <queue name="${testQueueName}">
              <entry name="/queue/${testQueueName}"/>
          </queue>
        
      </configuration>
      




        • 1. Re: hornetq-jms.xml queue names
          gaohoward

          I think it should be handled by Spring. Did you try it?

          • 2. Re: Re: hornetq-jms.xml queue names
            pminearo

            Yes, I have tried it.  It did not work.

             

            I have a Spring Context that instantiates a bean:

             

            <bean id="embeddedHornteQJms" class="org.hornetq.integration.spring.SpringJmsBootstrap" init-method="start" destroy-method="stop" />
            

             

            org.hornetq.integration.spring.SpringJmsBootStrap extends org.hornetq.jms.server.embedded.EmbeddedJMS.  SpringJmsBootstrap does not have a start() method; so, we look at it's parent class.  EmbeddedJMS has the following for the start() method:

             

            public void start() throws Exception
               {
                  super.initStart();
                  if (jmsConfiguration != null)
                  {
                     serverManager = new JMSServerManagerImpl(hornetQServer, jmsConfiguration);
                  }
                  else if (jmsConfigResourcePath == null) serverManager = new JMSServerManagerImpl(hornetQServer);
                  else serverManager = new JMSServerManagerImpl(hornetQServer, jmsConfigResourcePath);
            
                  if (registry == null)
                  {
                     if (context != null) registry = new JndiBindingRegistry(context);
                     else registry = new MapBindingRegistry();
                  }
                  serverManager.setRegistry(registry);
                  serverManager.start();
               }
            

             

            org.hornetq.jms.server.embedded.EmbeddedJMS extends org.hornetq.core.server.embedded.EmbeddedHornetQ.  On line 3 above, super.initStart() looks like:

             

            protectedvoid initStart() throws Exception
               {
                  if (configuration == null)
                  {
                     if (configResourcePath == null) configResourcePath = "hornetq-configuration.xml";
                     FileConfiguration config = new FileConfiguration(configResourcePath);
                     config.start();
                     configuration = config;
                  }
                  if (securityManager == null)
                  {
                     securityManager = new HornetQSecurityManagerImpl();
                  }
                  if (mbeanServer == null)
                  {
                     hornetQServer = new HornetQServerImpl(configuration, securityManager);
                  }
                  else
                  {
                     hornetQServer = new HornetQServerImpl(configuration, mbeanServer, securityManager);
                  }
               }
            

             

            From the look of these 2 methods; it seems like any properties that come in via the Property Placeholder in the parent context will not get applied to HornetQ.  And you can not mix Spring namespace information with the hornetq-configuration.xml or the hornetq-jms.xml files.  So, the question still remains:

             

            How do you get Properties from a Spring Context into HornetQ?

             

            If it is not possible, this seems like a bug with the SpringJmsBootstrap.  This class should be able to pick up all properties from the Spring Context and pass them onto the HornetQ Server.  This way the host, ports, etc can be configured via property files.

            • 3. Re: Re: hornetq-jms.xml queue names
              jbertram

              From the look of these 2 methods; it seems like any properties that come in via the Property Placeholder in the parent context will not get applied to HornetQ.

              Yes. I would agree.  There's no special property handling for the Spring use-case.

               

              That said, it's not clear to me why there necessarily should be.  Aside from org.apache.activemq.integration.spring.SpringJmsBootstrap which implements org.springframework.beans.factory.BeanFactoryAware the other POJOs have no knowledge of anything Spring-related.

               

              How do you get Properties from a Spring Context into HornetQ?

              At this point I'd say you can't.

               

              If it is not possible, this seems like a bug with the SpringJmsBootstrap.  This class should be able to pick up all properties from the Spring Context and pass them onto the HornetQ Server.  This way the host, ports, etc can be configured via property files.

              I'm certainly no Spring expert so this may be a dumb question, but why does this seem like a bug with SpringJmsBootstrap?  Are POJOs used by Spring required to pick up all properties from the Spring Context?  If so, doesn't that force the POJOs to be Spring aware?

               

              Also, why should it necessarily be possible for hosts, ports, etc. be configured via property files?

               

              Lastly, it's worth noting that HornetQ will pick-up system properties and can substitute values in the config files

              • 4. Re: Re: hornetq-jms.xml queue names
                pminearo

                Digging through the code, I can see now that it is not possible to use properties from the Spring Context to replace values in hornetq-configuration.xml and hornetq-jms.xml. These 2 file are parsed by specific file parsers built for HornetQ.  Spring is not involved at this point.  Could it be an enhancement for the SpringJmsBootstrap to pick up the properties from Spring and add them to HornetQ?  This would require the FileConfigurationParser and the JMSServerConfigParserImpl to have the ability to use a variable substitution.


                In our case, we have multiple JVMs on the same machine.  Each JVM will have it's own embedded HornetQ server which will have its own Port. Also, each HornetQ server will have HornetQ JMS on top of HornetQ Core; and have Apache Camel creating a JMS Bridge between the embedded HornetQ and a remote standalone ActiveMQ broker.  Furthermore, each JMS Bridge will point to a different Queue on the ActiveMQ broker.  So, we need the ability to configure the Port and the Queue Names based on which JVM HornetQ is deployed in.  Putting this on the command line is not an option for us.  I could put in a workaround to grab the properties file and stuff it into the System properties; but that would be a code smell.  So, it is looking like, more and more, if we want to use HornetQ embedded in our application; I will have to figure out how to create all the Spring beans for HornetQ to run. Does anyone know of a good example of pure Spring instantiation of HornetQ?

                • 5. Re: Re: hornetq-jms.xml queue names
                  jbertram

                  Digging through the code, I can see now that it is not possible to use properties from the Spring Context to replace values in hornetq-configuration.xml and hornetq-jms.xml. These 2 file are parsed by specific file parsers built for HornetQ.  Spring is not involved at this point.

                  That's correct.  This was essentially the point I was trying to make in my previous comment.

                   

                  Could it be an enhancement for the SpringJmsBootstrap to pick up the properties from Spring and add them to HornetQ?  This would require the FileConfigurationParser and the JMSServerConfigParserImpl to have the ability to use a variable substitution.

                  Theoretically, yes.  The org.apache.activemq.core.deployers.impl.FileConfigurationParser and org.apache.activemq.jms.server.impl.JMSServerConfigParserImpl already have the ability to use variable substitution (via org.apache.activemq.utils.XMLUtil.replaceSystemProps), but the variable substitution uses system properties.  The simplest solution would be to put all the properties from Spring into the system (e.g. via java.lang.System.setProperty(String,String)) as that should bridge the gap.  I'm not sure what you mean by, "...that would be a code smell."

                   

                  Does anyone know of a good example of pure Spring instantiation of HornetQ?

                  I don't know of any, but it should be pretty simple using the org.apache.activemq.core.config.impl.ConfigurationImpl and org.apache.activemq.jms.server.config.impl.JMSConfigurationImpl objects.  You can see the "embedded" example we ship for a programmatic example.