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!