12 Replies Latest reply on Apr 23, 2013 6:22 AM by Andy Taylor

    How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?

    jenfi jenfi Newbie

      Hi all!

       

      First of all, sorry for my bad english, but i'm french!!

       

      I'm a newbie in using hornetQ and JBOSS so i need your help!!!

       

      Here my problem :

      I have X server and they have all the same configuration with JBOSS 6.1 ans HornetQ 2.2.5.

      So, for exemple, hornet is configured on each server to have a topic called "systemTrackMessageArchiver-Topic".

       

      My problem is that i want to publish messages in the topic "systemTrackMessageArchiver-Topic", but on the server of my choice.

      For exemple, I have a function : public void publish (String message, String host), and when i call this function, i want the message "message" to be publish in the topic "systemTrackMessageArchiver-Topic" on the host "host"

       

      I would do that on each server.

       

      Is that poissible ?

       

      in all hotnetq-jms.xml of each server, there is :

       

      <topic name="systemTrackMessageArchiver-Topic">
        <entry name="/topic/systemTrackMessageArchiver-Topic"/>
       </topic>
      

       

      here my jms-ds.xml :

       

      <connection-factories>
         <!--
          JMS Stuff
         -->
         <mbean code="org.jboss.jms.jndi.JMSProviderLoader" name="hornetq:service=JMSProviderLoader,name=JMSProvider">
            <attribute name="ProviderName">DefaultJMSProvider</attribute>
            <attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
            <attribute name="FactoryRef">java:/XAConnectionFactory</attribute>
            <attribute name="QueueFactoryRef">java:/XAConnectionFactory</attribute>
            <attribute name="TopicFactoryRef">java:/XAConnectionFactory</attribute>
         </mbean>
         <!--
          JMS XA Resource adapter, use this to get transacted JMS in beans
         -->
         <tx-connection-factory>
            <jndi-name>JmsXA</jndi-name>
            <xa-transaction/>
            <rar-name>jms-ra.rar</rar-name>
            <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory</connection-definition>
            <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
            <config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/DefaultJMSProvider</config-property>
            <max-pool-size>20</max-pool-size>
            <security-domain-and-application>JmsXARealm</security-domain-and-application>
         </tx-connection-factory>
      </connection-factories>
      
      

       

       

      Thx a lot!!

      Jenfi

        • 1. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
          Justin Bertram Master

          A <tx-connection-factory> is specifically designed so it's configuration is done in XML rather than in code so if you want to use a <tx-connection-factory> to send your message to different hosts then you'll need to create one for each, e.g.:

           

             <tx-connection-factory>
                <jndi-name>ConnectionFactoryToServer1</jndi-name>
                <xa-transaction/>
                <rar-name>jms-ra.rar</rar-name>
                <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory</connection-definition>
                <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
                <config-property name="ConnectorClassName" type="java.lang.String">org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property>
                <config-property name="ConnectionParameters" type="java.lang.String">host=server1;port=5445</config-property>
                <max-pool-size>20</max-pool-size>
                <security-domain-and-application>JmsXARealm</security-domain-and-application>
             </tx-connection-factory>
          
             <tx-connection-factory>
                <jndi-name>ConnectionFactoryToServer2</jndi-name>
                <xa-transaction/>
                <rar-name>jms-ra.rar</rar-name>
                <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory</connection-definition>
                <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>
                <config-property name="ConnectorClassName" type="java.lang.String">org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property>
                <config-property name="ConnectionParameters" type="java.lang.String">host=server2;port=5445</config-property>
                <max-pool-size>20</max-pool-size>
                <security-domain-and-application>JmsXARealm</security-domain-and-application>
             </tx-connection-factory>
          

          etc.

           

          If you don't want to use a <tx-connection-factory> then you would lookup the connection factory in the JNDI of the remote server of your choice.

          • 2. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
            jenfi jenfi Newbie

            Thanks for your answer.

            And how i can look up the connection factory in the jndi of the remote server ?

            I have done many tries to connect to remote server with an InitialContext specifying the remote server in the provider_url properties but it has never worked. Each time the messages are sent in the local topic.

            • 3. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
              Justin Bertram Master

              Something like this:

               

              Properties props = new Properties();
              props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
              props.put("java.naming.provider.url", "jnp://host:1099");
              props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
              
              InitialContext initialcontext = new InitialContext(props);
              ConnectionFactory connectionFactory = (ConnectionFactory) initialcontext.lookup("ConnectionFactory");
              connection = connectionFactory.createConnection();
              Destination destination = (Destination) initialcontext.lookup("systemTrackMessageArchiver-Topic");
              initialcontext.close();
              Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
              MessageProducer producer = session.createProducer(destination);
              Message msg = session.createTextMessage("example");
              producer.send(msg);
              

               

              That said, doing this every time you send a message is an anti-pattern because it is so costly in terms of resources.  Using a couple <tx-connection-factory> would be much more efficient.

              • 4. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                jenfi jenfi Newbie

                I have already try something like this with no result on the remote topic... The message is always sent to the local topic...

                Normal to close the initialContext before sending the message ?

                • 5. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                  Justin Bertram Master

                  I've never seen code like this fail to send a message to the intended server.

                   

                  It's proper to close the InitialContext when the look-ups are complete since that's all it's needed for.

                  • 6. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                    Andy Taylor Master

                    you dont look up a connection factory on the remote server when using JCA, you configure the local connection factory to point to the remote server, something like

                     

                     

                    <tx-connection-factory>

                          <jndi-name>RemoteJmsXA</jndi-name>

                          <xa-transaction/>

                          <rar-name>hornetq-ra.rar</rar-name>

                          <connection-definition>org.hornetq.ra.HornetQRAConnectionFactory</connection-definition>

                          <config-property name="SessionDefaultType" type="java.lang.String">javax.jms.Topic</config-property>

                          <!--if we over ride the connector class we must over ride the params too-->

                          <config-property name="ConnectorClassName" type="java.lang.String">org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</config-property>

                          <config-property name="ConnectionParameters" type="java.lang.String">host=127.0.0.1;port=5446</config-property>

                          <max-pool-size>20</max-pool-size>

                       </tx-connection-factory>

                     

                    you can then just inject this as a esource without having to use jndi at all. this is ll in the docs as far as I am aware.

                    • 7. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                      jenfi jenfi Newbie

                      I don't really understand this...

                       

                      i don't want to store any host in XML files, i prefer configure the topic connection on the fly, with a host that will be an parameter of the call method.

                      • 8. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                        Andy Taylor Master

                        then configure your resource adapter to use discovery

                        • 9. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                          jenfi jenfi Newbie

                          I confirm that using this, it doesn't work for me.

                          I want to send a message on the server "192.168.100.61"

                          it send the message on my local topic instead of the topic on the server "192.168.100.61"

                           

                          I have done an another test:

                          The topic "systemTrackMessageArchiver-Topic" was on my local server and on the server "192.168.100.61", so i decided to create a topic that will exist only on the remote server.

                          I have created a topic called "toto-Topic" on the server "192.168.100.61", and when i replace

                           

                          Destination destination = (Destination) initialcontext.lookup("systemTrackMessageArchiver-Topic");
                          

                          by

                          Destination destination = (Destination) initialcontext.lookup("toto-Topic");
                          

                          I have a stack trace saying it doesn't find "toto-Topic"

                          I think it's normal because it search on the local server and not on the remote server.

                           

                          Justin Bertram a écrit:

                           

                          Something like this:

                           

                          Properties props = new Properties();
                          props.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
                          props.put("java.naming.provider.url", "jnp://host:1099");
                          props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
                           
                          InitialContext initialcontext = new InitialContext(props);
                          ConnectionFactory connectionFactory = (ConnectionFactory) initialcontext.lookup("ConnectionFactory");
                          connection = connectionFactory.createConnection();
                          Destination destination = (Destination) initialcontext.lookup("systemTrackMessageArchiver-Topic");
                          initialcontext.close();
                          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                          MessageProducer producer = session.createProducer(destination);
                          Message msg = session.createTextMessage("example");
                          producer.send(msg);
                          

                           

                          That said, doing this every time you send a message is an anti-pattern because it is so costly in terms of resources.  Using a couple <tx-connection-factory> would be much more efficient.

                          • 10. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                            Andy Taylor Master

                            your misunderstanding how JCA connection factories work, they are always local, you never look them up on a remote server. You configure them to connect to a remote server and look them up locally. take a look at the jca-remote example it does exactly this, https://github.com/hornetq/hornetq/tree/Branch_2_2_EAP/examples/javaee/jca-remote. If you dont want to configure a host/port then use discovery instead by configuring discovery (discoveryAddress and discoveryPort). Also read http://docs.jboss.org/hornetq/2.2.14.Final/user-manual/en/html_single/index.html#d0e7675

                            • 11. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                              jenfi jenfi Newbie

                              problem resolved with this code :

                               

                               

                              Map<String, Object> connectionParams = new HashMap<String, Object>();
                              connectionParams.put(TransportConstants.HOST_PROP_NAME, host);
                              connectionParams.put(TransportConstants.PORT_PROP_NAME, 5445);
                              TransportConfiguration configuration = new TransportConfiguration(NettyConnectorFactory.class.getName(), connectionParams);
                              ConnectionFactory cf = new HornetQJMSConnectionFactory(false,configuration);
                              connection = cf.createConnection();
                              Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                              topic = HornetQJMSClient.createTopic(topicName);
                              
                              
                              • 12. Re: How to publish a message into a remote topic with HornetQ, JMS ans JBOSS ?
                                Andy Taylor Master

                                yes, but here you won't be using the pooled connection factory (JCA) so it will be really slow since you will be creating a connection for every message. You should use the correct method as i explained.