I'm trying to realize a simple web application with an MDB running on JBoss 6.1.0 (Java EE 6 - Hornetq) to try the JMS and the MDB. I need also a simple stand-alone client that send text message on the queue where the MDB is listening. This is just a try so it's sufficient that the client sends a simple "hello world!" text message and the MDB simply read it and write it to the log. I found a lot of examples on Internet but someone use Glassfish as server, someother doesn't explain what are the correct libraries to import into the client, someother doesn't explain how to perform the queue and connection factory lookup when the client is remote, so I'm still unable to realize a functioning application.
The following is the code of the MDB that I created:
package it.test.mymdb;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@messageDriven(
activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination",
propertyValue = "myQueue")})
public class MyMDB implements MessageListener {
private static final Logger logger = LoggerFactory.getLogger(MyMDB.class);
@Override
public void onMessage(Message message) {
try {
logger.info("Messaggio ricevuto");
TextMessage txtMsg = (TextMessage) message;
logger.info(txtMsg.getText());
}
catch (JMSException ex) {
logger.error("Errore durante la lettura del testo del messaggio.");
}
}
}
And this is the hornetq-jms.xml file on which I defined the queue and the connection factory:
<?xml version="1.0"?>
<configuration xsi:schemaLocation="urn:hornetq /schema/hornetq-jms.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:hornetq">
<connection-factory name="myConnectionFactory">
<connectors>
<connector-ref connector-name="netty"/>
</connectors>
<entries>
<entry name="/myConnectionFactory"/>
</entries>
</connection-factory>
<queue name="myQueue">
<entry name="/queue/myQueue" />
</queue>
</configuration>
QUESTION 1: Have I to insert in this file the "user" and "password" data needed by the client to perform the JNDI search? If yes, how?
The deploy of my MDB seems to work, if I access to the JBoss Admin Panel I see the queue:
Name: myQueue
JNDI Binding: /queue/myQueue
Address: jms.queue.myQueue
Temporary: false
Paused: false
and the connection factory:
Name: myConnectionFactory
JNDI Bindings: /myConnectionFactory
This is the (not working) code of my client:
package it.test.mymdbclient;
import java.util.Hashtable;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class MyMdbClient {
private final static String JNDI_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory";
private final static String JMS_FACTORY = "myConnectionFactory";
private final static String QUEUE = "queue/myQueue";
private final static String jbossUrl = "remote://localhost:4447";
private static InitialContext getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, jbossUrl);
env.put(Context.SECURITY_PRINCIPAL, "admin"); //PROBABLY THOSE CREDENTIALS ARE NOT CORRECT
env.put(Context.SECURITY_CREDENTIALS, "admin");
return new InitialContext(env);
}
public static void main(String[] args) throws Exception {
InitialContext ic = getInitialContext();
QueueConnectionFactory qconFactory = (QueueConnectionFactory) ic.lookup(JMS_FACTORY);
QueueConnection qcon = qconFactory.createQueueConnection("admin", "admin"); //PROBABLY THOSE CREDENTIALS ARE NOT CORRECT
QueueSession qsession = qcon.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) ic.lookup(QUEUE);
QueueSender qsender = qsession.createSender(queue);
qcon.start();
TextMessage msg = qsession.createTextMessage();
msg.setText("Hello world! :)");
qsender.send(msg);
qsender.close();
qsession.close();
qcon.close();
}
}
This is the library that I imported, but I'm almost sure that it's not sufficient and this is the cause of the exception thrown. If it is what other libraries do I need?
<dependency>
<groupId>org.hornetq</groupId>
<artifactId>hornetq-jms-client</artifactId>
<version>2.3.9.Final</version>
</dependency>
This is the exception thrown when I run the client:
Exception in thread "main" javax.naming.NoInitialContextException: Cannot instantiate class: org.jboss.naming.remote.client.InitialContextFactory [Root exception is java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory]
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:674)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:216)
at it.test.mymdbclient.MyMdbClient.getInitialContext(MyMdbClient.java:27)
at it.test.mymdbclient.MyMdbClient.main(MyMdbClient.java:31)
Caused by: java.lang.ClassNotFoundException: org.jboss.naming.remote.client.InitialContextFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:340)
at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:72)
at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:61)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:672)
... 5 more