Make a JMS client without JNDI connect to a JMS server
excalibur1491 Jul 12, 2013 11:17 AMHi,
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!