6 Replies Latest reply on Jul 14, 2013 6:55 AM by ataylor

    Make a JMS client without JNDI connect to a JMS server

    excalibur1491

      Hi,

       

      I am new at JMs and HornetQ, and I have been working the whole day without getting any result. I just want to code a JMS client to connect to a JMS server.

      The JMS server uses HornetQ as the client, so there should be no problem.

      Nevertheless I am trying to avoid JNDI because I have tried for a week to get my JMS Client work in Felix OSGI, and it has been impossible for me (several problems with classloader, classpaths etc. really anoying), so I have decided to make a client without JNDI using only the HornetQ Objects.

       

      This is what I have got:

       

      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();
               }
            }
         }
      
      
      }
      
      

       

       

      And I have these files on my class path:

      hornetq-beans.xml

      <?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>
      
      

       

      hornetq-jms.xml

      <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 for authentification)

       

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

       

      hornetq-configuration.xml

      In the "host" tag, putting jnp://, taking it out, putting the port or taking it out does not have any effect. It doesn't change anything, I have tested all the options

      <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="1099"/>
            </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="1099"/>
            </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>
      
      

       

       

      By executing this code, I have:

      javax.jms.JMSException: Timed out waiting for response when sending packet 30
                at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:276)
                at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSessionInternal(ClientSessionFactoryImpl.java:677)
                at org.hornetq.core.client.impl.ClientSessionFactoryImpl.createSession(ClientSessionFactoryImpl.java:249)
                at org.hornetq.jms.client.HornetQConnection.authorize(HornetQConnection.java:589)
                at org.hornetq.jms.client.HornetQConnectionFactory.createConnectionInternal(HornetQConnectionFactory.java:684)
                at org.hornetq.jms.client.HornetQConnectionFactory.createConnection(HornetQConnectionFactory.java:119)
                at org.hornetq.jms.client.HornetQConnectionFactory.createConnection(HornetQConnectionFactory.java:114)
                at com.test.Snippet.runExample(Snippet.java:175)
                at org.hornetq.common.example.HornetQExample.run(HornetQExample.java:69)
                at com.test.Snippet.main(Snippet.java:149)
      Caused by: HornetQException[errorCode=3 message=Timed out waiting for response when sending packet 30]
                ... 10 more
      
      
      #####################
      ###    FAILURE!   ###
      #####################
      Exception in thread "main" java.lang.RuntimeException: failure in running example
                at org.hornetq.common.example.HornetQExample.reportResultAndExit(HornetQExample.java:214)
                at org.hornetq.common.example.HornetQExample.run(HornetQExample.java:80)
                at com.test.Snippet.main(Snippet.java:149)
      

       

      The problem is this line: connection = cf.createConnection();

       

       

      More over, this code (my old one using JNDI) works perfectly, like a charm (no config files needed, just a little bit of generic code):

       

      public class Snippet {
      
      
      
                public static void main(String[] args) {
                          System.out.println("Starting");
                          String destName = null;
                          Context jndiContext = null;
                          ConnectionFactory connectionFactory = null;
                          Connection connection = null;
                          Session session = null;
                          Destination dest = null;
                          MessageConsumer consumer = null;
      
      
                          destName = "x.y.z.t";
                          System.out.println("Destination name is " + destName);
      
      
                          /*
                           * Create a JNDI API InitialContext object if none exists yet.
                           */
                          try {
                                    jndiContext = new InitialContext(getJavaNamingProperties());
                          } catch (NamingException e) {
                                    System.out.println("Could not create JNDI API context: " + e.toString());
                                    System.exit(1);
                          }
      
      
                          /*
                           * Look up connection factory and destination. If either does not exist, exit. If you look up a TopicConnectionFactory or a QueueConnectionFactory, program behavior is the same.
                           */
                          try {
                                    connectionFactory = (ConnectionFactory) jndiContext.lookup("/ConnectionFactory");
                                    System.out.println(connectionFactory);
                                    dest = (Destination) jndiContext.lookup("/topic/HandledAlarmTopic");
                                    System.out.println(dest);
                          } catch (Exception e) {
                                    System.out.println("JNDI API lookup failed: " + e.toString());
                                    System.exit(1);
                          }
      
      
                          /*
                           * Create connection. Create session from connection; false means session is not transacted. Create consumer, then start message delivery. Receive all text messages from destination until a
                           * non-text message is received indicating end of message stream. Close connection.
                           */
                          try {
                                    connection = connectionFactory.createConnection();
                                    session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                                    consumer = session.createConsumer(dest);
                                    connection.start();
                                    System.out.println("Listening...");
                                    while (true) {
                                              Message m = consumer.receive(1);
      
      
                                              if (m != null) {
                                                        System.out.println("Receive " + m);
      
      
                                                        ObjectMessage om = (ObjectMessage) m;
                                                        HandledAlarmEvent alarm = (HandledAlarmEvent) om.getObject();
                                                        System.out.println("message value = " + alarm);
      
      
                                              }
                                    }
                          } catch (JMSException e) {
                                    System.out.println("Exception occurred: " + e.toString());
                                    e.printStackTrace();
                          } finally {
                                    if (connection != null) {
                                              try {
                                                        connection.close();
                                              } catch (Exception e) {
                                              }
                                    }
                          }
                }
      
      
                private static Properties getJavaNamingProperties() {
                          Properties props = new Properties();
                          String address = "x.Y.Z.T";
                          Integer port = 1099;
      
      
                          Properties returnProps = new Properties();
                          returnProps.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
                          returnProps.put("java.naming.provider.url", "jnp://" + address + ":" + port);
                          returnProps.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
                          return returnProps;
                }
      }
      
      

       

       

      So, my problem is that I have absolutelly no idea of what I am doing wrong with the HornetQ classes. I suspect there is something wrong in the configuration, but I don't know why.

       

      Really, the only thing I need is a little client that listents a topic in a JMS server. That's all, no need to send, just listen.

       

      Any help would be appreciated, I have spent a lot of time on this problem.

       

       

      thank you a lot in advance!

        • 1. Re: Make a JMS client without JNDI connect to a JMS server
          excalibur1491

          Hi, does any ony one have an idea, please?
          I just discovered hat in fact, if I want to avoid JNDI, I have to use port 5445 instad of 1099, but it is still not working. I get this:

          HornetQException[errorCode=2 messge=Cannot connect to server(s). Tried with all available servers.]

           

           

          Any help would really be appreciated!

          • 2. Re: Make a JMS client without JNDI connect to a JMS server
            ataylor

            how are you trying to connect without JNDI?

            • 3. Re: Make a JMS client without JNDI connect to a JMS server
              excalibur1491

              Hi, thank you for your answer
              Well, I am using the code I gave on my first post (the first java code and the 4 XML files, the last java coe is my old code, using JNDI, taht works perfectly), I have on only changed the port number to 5445 everywhere I had set it to 1099. It's really the only difference.

               

              I am trying to avoid JNDI because I am in a Felix OSGi enviroment and it seems like using JNDI in OSGi is really not easy. I have tries with Apache Aries (which is meant to help developer to do that), but the lack of documentation is really anoying and it just keeps not working because most of the clases can't be found since we are in a OSGi envirment and the classpaths are somehow "modified" by the environment...

              So, my idea is to avoi JNDI, just create objects that OSGi knows where to find (I converted he hornetq jars into bundles) and hope it works. By the moment I'm only trying it outside of OSGi, and once I will be abl to connect to the server without JNDI ouside of OSGI, I will put it in an OSGi envirment

              • 4. Re: Make a JMS client without JNDI connect to a JMS server
                ataylor

                just make sure the host and port yopu use for the Transport configuration match th ehost and port of your acceptor.

                • 5. Re: Make a JMS client without JNDI connect to a JMS server
                  excalibur1491

                  Ok, thank you again for your answer!

                  I cannot test it right now because the host is only available at my work place's network, but I'll do it as soon as I can (tomorrow morning).

                  I still have a question:

                  You say I have to do this:

                  connectionParams.put(TransportConstants.PORT_PROP_NAME, 5446);

                  connectionParams.put(TransportConstants.HOST_PROP_NAME, "x.y.z.t");

                  or should it be:

                  connectionParams.put(TransportConstants.HOST_PROP_NAME, "jnp://x.y.z.t");

                  Also, on the acceptors and connectors do I have to specify he protocol jnp:// or not? I assume that I don't need to specify the port in the address like x.y.z.t:5449, am I right?

                  After that modification, do you think that it hould work, or is there anything else in my configuration that loks wrong?

                   

                  Thank you again for your patiente

                  • 6. Re: Make a JMS client without JNDI connect to a JMS server
                    ataylor

                    the host should be an ip address or hostname