HornetQ connecting to a JMS server

13,479

If you want to use HornetQ's native client, look at these documents

http://docs.jboss.org/hornetq/2.2.2.Final/user-manual/en/html_single/#d0e1611

This will likely also help, with direct connections

http://docs.jboss.org/hornetq/2.2.2.Final/user-manual/en/html_single/#d0e2387

You'll want to use their local core client examples.

Share:
13,479
excalibur1491
Author by

excalibur1491

Ph.D. Student at the University of Melbourne, Australia, in Discrete Optimization & Constraint Programming.

Updated on June 25, 2022

Comments

  • excalibur1491
    excalibur1491 almost 2 years

    I am currently trying to create a JMS client for a JMS Server both using HornetQ. I did not code the server and I don't know much about hoy it works, I only know how to connect to it: no username, no password and the address is jnp://x.y.z.t:1099 .

    I am trying to connect to the server without using JNDI and I am having some trouble. In fact I have found this example: http://anonsvn.jboss.org/repos/hornetq/trunk/examples/jms/instantiate-connection-factory/ and I don't know what do I need to change in the XML files and in the code to make it work.

    I had this code, with JNDI:

    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.Destination;
    import javax.jms.JMSException;
    import javax.jms.MessageProducer;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * A simple polymorphic JMS producer which can work with Queues or Topics which
     * uses JNDI to lookup the JMS connection factory and destination
     * 
     * 
     */
    public final class SimpleProducer {
    
        private static final Logger LOG = LoggerFactory.getLogger(SimpleProducer.class);
    
        private SimpleProducer() {
        }
    
        /**
         * @param args the destination name to send to and optionally, the number of
         *                messages to send
         */
        public static void main(String[] args) {
            Context jndiContext = null;
            ConnectionFactory connectionFactory = null;
            Connection connection = null;
            Session session = null;
            Destination destination = null;
            MessageProducer producer = null;
            String destinationName = null;
            final int numMsgs;
    
            if ((args.length < 1) || (args.length > 2)) {
                LOG.info("Usage: java SimpleProducer <destination-name> [<number-of-messages>]");
                System.exit(1);
            }
            destinationName = args[0];
            LOG.info("Destination name is " + destinationName);
            if (args.length == 2) {
                numMsgs = (new Integer(args[1])).intValue();
            } else {
                numMsgs = 1;
            }
    
            /*
             * Create a JNDI API InitialContext object
             */
            try {
                jndiContext = new InitialContext();
            } catch (NamingException e) {
                LOG.info("Could not create JNDI API context: " + e.toString());
                System.exit(1);
            }
    
            /*
             * Look up connection factory and destination.
             */
            try {
                connectionFactory = (ConnectionFactory)jndiContext.lookup("ConnectionFactory");
                destination = (Destination)jndiContext.lookup(destinationName);
            } catch (NamingException e) {
                LOG.info("JNDI API lookup failed: " + e);
                System.exit(1);
            }
    
            /*
             * Create connection. Create session from connection; false means
             * session is not transacted. Create sender and text message. Send
             * messages, varying text slightly. Send end-of-messages message.
             * Finally, close connection.
             */
            try {
                connection = connectionFactory.createConnection();
                session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                producer = session.createProducer(destination);
                TextMessage message = session.createTextMessage();
                for (int i = 0; i < numMsgs; i++) {
                    message.setText("This is message " + (i + 1));
                    LOG.info("Sending message: " + message.getText());
                    producer.send(message);
                }
    
                /*
                 * Send a non-text control message indicating end of messages.
                 */
                producer.send(session.createMessage());
            } catch (JMSException e) {
                LOG.info("Exception occurred: " + e);
            } finally {
                if (connection != null) {
                    try {
                        connection.close();
                    } catch (JMSException e) {
                    }
                }
            }
        }
    }
    

    with this jndi.properties file:

    java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
    java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
    java.naming.provider.url = jnp://x.y.z.t:1099
    

    and everything worked fine. But now I need to do the same thing without JNDI. The example I gave above (http://anonsvn.jboss.org/repos/hornetq/trunk/examples/jms/instantiate-connection-factory/) shoutd work, but I don't know what to change in the config to make it work, I have never used a JMS client this way, so I'm completelly lost!

    These are the config files I'm talking about: http://anonsvn.jboss.org/repos/hornetq/trunk/examples/jms/instantiate-connection-factory/server0/ . I coulnd't find on the net to what the files correpsond, I'm confused. Also, the Java code is here: http://anonsvn.jboss.org/repos/hornetq/trunk/examples/jms/instantiate-connection-factory/src/org/hornetq/jms/example/InstantiateConnectionFactoryExample.java

    Thank you in advance

    ----- EDIT This is the last vesion of my code:

    import java.util.HashMap;
    import java.util.Map;
    
    
    import javax.jms.Connection;
    import javax.jms.ConnectionFactory;
    import javax.jms.MessageConsumer;
    import javax.jms.MessageProducer;
    import javax.jms.Queue;
    import javax.jms.Session;
    import javax.jms.TextMessage;
    
    
    import org.hornetq.api.core.TransportConfiguration;
    import org.hornetq.api.jms.HornetQJMSClient;
    import org.hornetq.api.jms.JMSFactoryType;
    import org.hornetq.common.example.HornetQExample;
    import org.hornetq.core.remoting.impl.netty.NettyConnectorFactory;
    import org.hornetq.core.remoting.impl.netty.TransportConstants;
    import org.hornetq.jms.client.HornetQConnectionFactory;
    
    
    public class Snippet extends HornetQExample
    {
       public static void main(final String[] args)
       {
          new Snippet().run(args);
       }
    
    
       @Override
       public boolean runExample() throws Exception
       {
          Connection connection = null;
          try
          {
             // Step 1. Directly instantiate the JMS Queue object.
             Queue queue = HornetQJMSClient.createQueue("exampleQueue");
    
    
             // Step 2. Instantiate the TransportConfiguration object which contains the knowledge of what transport to use,
             // The server port etc.
    
    
             Map<String, Object> connectionParams = new HashMap<String, Object>();
             connectionParams.put(TransportConstants.PORT_PROP_NAME, 5446);
             //My server's port:
             //connectionParams.put(TransportConstants.PORT_PROP_NAME, 1099);
    
    
             TransportConfiguration transportConfiguration = new TransportConfiguration(NettyConnectorFactory.class.getName(),
                                                                                        connectionParams);
    
    
             // Step 3 Directly instantiate the JMS ConnectionFactory object using that TransportConfiguration
             HornetQConnectionFactory cf = HornetQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);
    
    
             // Step 4.Create a JMS Connection
             connection = cf.createConnection();
    
             // Step 5. Create a JMS Session
             Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    
    
             // Step 6. Create a JMS Message Producer
             MessageProducer producer = session.createProducer(queue);
    
    
             // Step 7. Create a Text Message
             TextMessage message = session.createTextMessage("This is a text message");
    
    
             System.out.println("Sent message: " + message.getText());
    
    
             // Step 8. Send the Message
             producer.send(message);
    
    
             // Step 9. Create a JMS Message Consumer
             MessageConsumer messageConsumer = session.createConsumer(queue);
    
    
             // Step 10. Start the Connection
             connection.start();
    
    
             // Step 11. Receive the message
             TextMessage messageReceived = (TextMessage)messageConsumer.receive(5000);
    
    
             System.out.println("Received message: " + messageReceived.getText());
    
    
             return true;
          }
          finally
          {
             if (connection != null)
             {
                connection.close();
             }
          }
       }
    
    
    }
    

    This is my hornetq-beans.xml (I disable JNDI)

    <?xml version="1.0" encoding="UTF-8"?>
    
    
    <deployment xmlns="urn:jboss:bean-deployer:2.0">
    
    
       <bean name="Naming" class="org.jnp.server.NamingBeanImpl"/>
    
    
       <!-- JNDI server. Disable this if you don't want JNDI -->
       <!-- <bean name="JNDIServer" class="org.jnp.server.Main">
          <property name="namingInfo">
             <inject bean="Naming"/>
          </property>
          <property name="port">1099</property>
                                                                                <!-- <property name="bindAddress">localhost</property>
          <property name="bindAddress">jnp://X.Y.Z.T</property>
          <property name="rmiPort">1098</property>
                                                                                <!-- <property name="rmiBindAddress">localhost</property>
          <property name="bindAddress">jnp://X.Y.Z.T</property>
       </bean>-->
    
       <!-- MBean server -->
       <bean name="MBeanServer" class="javax.management.MBeanServer">
          <constructor factoryClass="java.lang.management.ManagementFactory"
                       factoryMethod="getPlatformMBeanServer"/>
       </bean> 
    
    
       <!-- The core configuration -->
       <bean name="Configuration" class="org.hornetq.core.config.impl.FileConfiguration"/>
    
    
       <!-- The security manager -->
       <bean name="HornetQSecurityManager" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl">
          <start ignored="true"/>
          <stop ignored="true"/>
       </bean>
    
    
       <!-- The core server -->
       <bean name="HornetQServer" class="org.hornetq.core.server.impl.HornetQServerImpl">
          <constructor>
             <parameter>
                <inject bean="Configuration"/>
             </parameter>
             <parameter>
                <inject bean="MBeanServer"/>
             </parameter>
             <parameter>
                <inject bean="HornetQSecurityManager"/>
             </parameter>        
          </constructor>
          <start ignored="true"/>
          <stop ignored="true"/>
       </bean>
    
       <!-- The JMS server -->
       <bean name="JMSServerManager" class="org.hornetq.jms.server.impl.JMSServerManagerImpl">
          <constructor>         
             <parameter>
                <inject bean="HornetQServer"/>
             </parameter>
          </constructor>
       </bean>
    
    
    </deployment>
    

    and my hornetq-jms.xml (same as in the example)

    <configuration xmlns="urn:hornetq"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd">
    
       <!--the queue used by the example-->
       <queue name="exampleQueue">
          <entry name="/queue/exampleQueue"/>
       </queue>
    
    
    </configuration>
    

    hornetq-users.xml (There is no need to have users to connect to the JMS server, so I commented it):

    <configuration xmlns="urn:hornetq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:hornetq /schema/hornetq-users.xsd">
       <!-- the default user.  this is used where username is null
       <defaultuser name="guest" password="guest">
          <role name="guest"/>
       </defaultuser>-->
    </configuration> 
    

    My hornetq-configuratio.xml: I am not sur whether I have to put jnp:// in the connectors and acceptors or not. Actually I don't really get much of this....

    <configuration xmlns="urn:hornetq"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="urn:hornetq /schema/hornetq-configuration.xsd">
    
    
       <!-- Connectors -->
    
    
       <connectors>
          <connector name="netty-connector">
             <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
             <param key="host" value="jnp://X.Y.Z.T"/>    
             <param key="port" value="5445"/>
          </connector>
       </connectors>
    
       <!-- Acceptors -->
       <acceptors>
          <acceptor name="netty-acceptor">
             <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>         
             <param key="host" value="jnp://X.Y.Z.T"/>
             <param key="port" value="5445"/>
          </acceptor>
       </acceptors>
    
    
       <!-- Other config -->
    
    
       <security-settings>
          <!--security for example queue-->
          <security-setting match="jms.queue.exampleQueue">
             <permission type="createDurableQueue" roles="guest"/>
             <permission type="deleteDurableQueue" roles="guest"/>
             <permission type="createNonDurableQueue" roles="guest"/>
             <permission type="deleteNonDurableQueue" roles="guest"/>
             <permission type="consume" roles="guest"/>
             <permission type="send" roles="guest"/>
          </security-setting>
       </security-settings>
    
    
    </configuration>
    

    What I get with this code is:

    HornetQException[errorCode=2 message=Cannot connect to server(s). Tried with all available servers.]
            at org.hornetq.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:619)
            at org.hornetq.jms.client.HornetQConnectionFactory.createConnectionInternal(HornetQConnectionFactory.java:601)
    

    I am using version 2.2.2, by the way ;)

  • excalibur1491
    excalibur1491 almost 11 years
    Thank you for the answer. I am trying to execute this code github.com/hornetq/hornetq/blob/master/examples/core/… , and it simply does not connect to my server. I change the port and the address. In the address I only give the IP address, because if I give jnp://x.y.z.t it does not work either. I dont really see what I'm doing wrong, the code is quite short, though! I get a HornetQException[errorCode=3 message=Timed out waiting for response when sending packet 30] when creating the session.
  • John Ament
    John Ament almost 11 years
    what did you change the port to? 5445 is the default. 1099 is for JNDI only.
  • excalibur1491
    excalibur1491 almost 11 years
    Do you mean that there are two differnet ports? One for JNDI and one for the actual JMS server with the topics? There are two different applications on the same host, each one doing one thing: JNDI and JMS? I'm not sure I understand... sorry, I'm new with all that. In that case, I have to connect to the JMS server port directly avoiding JNDI?
  • excalibur1491
    excalibur1491 almost 11 years
    Just for your information, I tried the code from before (github.com/hornetq/hornetq/blob/master/examples/core/…) with the port 5445, and I get HornetQException[errorCode=2 message=Cannot connect to server(s). Tried with all available servers.] I don't know what I'm missing.... Any clue? Thank you a lot ;)
  • John Ament
    John Ament almost 11 years
    yes, different portions bind to different ports. same thing for the web tier, the web tier binds to port 8080 by default. you wouldn't want all traffic going through a single port, causes a lot of throughput issues and protocol handling problems. what happens if you try telnetting to the host on port 5445? does it work? try it locally as well as remotely, do you maybe need to open up ports on a firewall to allow it?
  • excalibur1491
    excalibur1491 almost 11 years
    Hi, thank you for your help. I cannot try telnet right now, because I'm not at my work place. I'll try it monday. Anyway, I think there is no poblem with the ports on the firewall since my cde with JNDI worked perfectly. Is there a way I can be sure that the JMS server is on port 5445 besides asking the person who did the server? And, is it possible to talk to this port without having asked the JNDI port before? Thanks again!
  • John Ament
    John Ament almost 11 years
    if you don't have access to the server, telnet is your easier way. you can also log in to the jboss admin console and verify it. is it possible for you to show your real code? Is the jms server running on localhost or did you modify the code?
  • excalibur1491
    excalibur1491 almost 11 years
    Hi, thank you again for your answer! Well, it is impossible for me to try right now because the server is in a host only accesible from inside my work place, but I have the last version of my code. I'm addin it to my first message right now. I'll try telnet as you say. The JMS server is running in a real host, not in localhost, and it perfectly works. I am not allowed to "play" with it much. Thank you again!!
  • John Ament
    John Ament almost 11 years
    this value looks wrong: <param key="host" value="jnp://X.Y.Z.T"/>, should be <param key="host" value="X.Y.Z.T"/>
  • excalibur1491
    excalibur1491 almost 11 years
    Ok, thank you. I will test it as soon as I can (normally tomorrow morning, european time). Just to be sure about telnet, what should I get if everything is right when doing telnet x.y.z.t 5445 because, I am not sure if it is 5445 or maybe 5446, I have seen some examples on the internet using 5446. Thank you again! You're being really helpful :)
  • excalibur1491
    excalibur1491 almost 11 years
    I just tried and it works!! I changed the port here: connectionParams.put(TransportConstants.PORT_PROP_NAME, 5445); and the host: connectionParams.put(TransportConstants.HOST_PROP_NAME, "name"); Also, I used this to create the factory: HornetQConnectionFactory cf = HornetQJMSClient.createConnectionFactory(transportConfigurat‌​ion); (using hornetQ version 2.1.2 this time) and it works!! Thank you a lot! I hope it will be easy to put it in an OSGI environment! Thanks again!