jms queuebrowser # getEnumeration always obtained as empty - java

I'm using jbossall-client jar for JMS and I'm new to messaging. Whenever I try to browse the queue to which I send a message (its an object message), always I'm getting 'false' on my qBrowser.getEnumeration().hasMoreElements();
This is how I create the connection:
public void initialize() throws Exception {
try {
InitialContext initialContext = new InitialContext(contextProperties);
connectionFactory = (QueueConnectionFactory) initialContext.lookup(connectionFactoryName);
queue = (Queue) initialContext.lookup("queue/" + queueName);
initialContext.close();
} catch (NamingException e) {
throw new Exception("Error initializing enqueuer for " + queueName, e);
}
}
public MyQueueConnection openQueueConnection() throws JMSException {
QueueConnection connection = null;
try {
connection = connectionFactory.createQueueConnection();
connection.start();
QueueSession session = connection.createQueueSession(true, QueueSession.DUPS_OK_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
sender.setDeliveryMode(DeliveryMode.PERSISTENT);
return new MyQueueConnection(connection, session, sender);
} catch (JMSException e) {
throw e;
}
}
Do I need to configure anything with QueueConnection/QueueSession/QueueSender or something else to browse the messages in a queue? Is it something I need to configure in jboss properties? (I do this in a singleton-MDB; this project is a spring framework project)
Please advise; thanks in advance.

Just a suggestion for another one.
I used hornetQ
Please check you created QueueReceiver createReceiver() after getEnumeration() is called.
Make sure you start connection connection.start()
Check the link for bug
Check the custom size

Related

JMS point-to-point chat

I'm trying to do a simple point-to-point chat, but after running the program I get an exception:
javax.naming.CommunicationException: Failed to get registry service for URL: tcp://localhost:8080/ [Root exception is java.rmi.ConnectIOException: Failed to create connection; nested exception is:
org.exolab.jms.net.connector.ConnectException: Failed to connect to localhost:8080]
at org.exolab.jms.jndi.InitialContextFactory.getInitialContext(InitialContextFactory.java:146)
at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:732)
at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
at java.naming/javax.naming.InitialContext.<init>(InitialContext.java:208)
at zad1.Receiver.<init>(Receiver.java:24)
at zad1.Client.lambda$new$0(Client.java:61)
....
What could be the problem? I'm a complete beginner at this.
Here's my code:
private Context context;
private Connection connection = null;
private Session session;
private MessageProducer sender;
public Sender() {
try {
Hashtable<String, String> properties = new Hashtable<>();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.exolab.jms.jndi.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "tcp://localhost:8080/");
context = new InitialContext(properties);
ConnectionFactory factory = (ConnectionFactory) context.lookup("ConnectionFactory");
Topic topic = (Topic) context.lookup("topic1");
connection = factory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
sender = session.createProducer(topic);
connection.start();
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
}
public void send(String message) {
try {
TextMessage textMessage = session.createTextMessage();
textMessage.setText(message);
sender.send(textMessage);
} catch (JMSException ex) {
ex.printStackTrace();
}
}
The message from the exception indicates what the problem is:
Failed to connect to localhost:8080
When you configure your JNDI lookup you specify:
properties.put(Context.PROVIDER_URL, "tcp://localhost:8080/");
However, the JNDI implementation can't establish a connection to localhost:8080. Please ensure that the URL is correct for your environment and/or that the JNDI server is actually running on port 8080 on localhost.
Lastly, it's worth noting that the stack-trace for the exception you shared does not match the source code you shared. The stack-trace came from the constructor of a class named Receiver, but the source code you shared is for a class named Sender.

how can I check if a queue exists on Activemq

I have this method that throws me an exception when the data queue doesn't exists, but is not. Do you have other way to solve this?
public void checkDataQueue(String dataQueue) throws JMSException {
Connection connection = null;
Session session = null;
connection = jmsTemplate.getConnectionFactory().createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(dataQueue);
QueueBrowser browser = session.createBrowser(queue);
}
ActiveMQ 5.x creates Queues on demand by default so you may have changed the default configuration to disallow this in which case the error should be expected to happen if you are hitting a non-existent queue and you should check for and handle that. If you need to be sure then the broker provides a JMX interface to query for information on broker statistics etc. There are also other ways of monitoring such as using Rest style calls over the Jolokia management interface.
thank you Tim, I solved it with these method.
public boolean existDataQueue(String dataQueue) throws JMSException {
boolean response = false;
ActiveMQConnectionFactory activeMQConnectionFactory =
new ActiveMQConnectionFactory();
activeMQConnectionFactory.setBrokerURL(brokerUrl);
ActiveMQConnection connection = (ActiveMQConnection)activeMQConnectionFactory.createConnection();
connection.start();
DestinationSource ds = connection.getDestinationSource();
Set<ActiveMQQueue> queues = ds.getQueues();
for (ActiveMQQueue activeMQQueue : queues) {
try {
if(activeMQQueue.getQueueName().equalsIgnoreCase(dataQueue)) {
response = true;
}
} catch (JMSException e) {
e.printStackTrace();
}
}
connection.close();
return response;
}

Channel End Notification exception is coming while using JMS with JBoss

I am using JMS with JBoss. But whenever i run the my consumer code i always get the below exception
[org.jboss.as.naming] (Remoting "sorabh216901" task-2) JBAS011806: Channel end notification received, closing channel Channel ID 091878ba (inbound) of Remoting connection 007ce8a6 to /192.168.2.47:53318
My Consumer class is as below:
public class TopicConsumer implements MessageListener{
public static void main(String[] args) throws NamingException, JMSException {
Context context = TopicConsumer.getInitialContext();
try{
System.out.println("Entering into the main method!!!");
TopicConnectionFactory connectionFactory = (TopicConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
Topic topic = (Topic) context.lookup("jms/topic/test");
TopicConnection connection = connectionFactory.createTopicConnection("testuser", "testpassword");
TopicSession session = connection.createTopicSession(true, TopicSession.AUTO_ACKNOWLEDGE);
session.createSubscriber(topic).setMessageListener(new TopicConsumer());
connection.start();
System.out.println("Exiting from the main method!!!");
}finally{
//context.close();
}
}
public void onMessage(Message arg0) {
System.out.println("Incoming Message : " + arg0);
}
public static Context getInitialContext() throws NamingException{
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
props.put("remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER");
props.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
props.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
props.put(Context.PROVIDER_URL,"remote://192.168.2.47:4447");
props.put("jboss.naming.client.ejb.context", true);
// username
props.put(Context.SECURITY_PRINCIPAL, "testuser");
// password
props.put(Context.SECURITY_CREDENTIALS, "testpassword");
return new InitialContext(props);
}
}
When ever i ran the code i get the successful handshake in logs i.e.
INFO: EJBCLIENT000013: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext#cd0d2e,
receiver=Remoting connection EJB receiver [connection=Remoting connection <1e03fce>,channel=jboss.ejb,nodename=sorabh216901]} on channel Channel ID 9823d1ac (outbound) of Remoting connection 004edf4a to /192.168.2.47:4447
But the program just closed and in server logs i get channel end notification.
Please suggest, what is wrong here.
Add the following line at the end of main method of TopConsumer
class:
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This will not stop the JVM. And you won't get Channel End Notification exception

Jboss Messaging JMS

I successfully managed to send the message to queue name ReceiverQueue on my localhost Jboss server, how can I retrieve message I sent to it or how do I check if there is any messages in the queue if any retrieve them. or can I get an explanation of some sort what is the best way to do this. Thank you
A working send/receive tutorial would be accept as well. Anything that will get me to just send to the queue and receive message from that queue will get accepted answer.
I'm using Spring.
I want a solution that does it using application context with bean injection ..
Standard JMS API steps:
1. Create a javax.naming.Context with the access details of the server
context = new InitialContext(environment)
2. Look up javax.jms.QueueConnectionFactory in the context. Factory name is specific to the JMS server
factory = (QueueConnectionFactory)context.lookup(factoryName)
3. Create a javax.jms.QueueConnection
connection = factory.createQueueConnection(...)
4. Create a javax.jms.QueueSession
session = connection.createQueueSession(...)
5. Look up your javax.jms.Queue in the context
queue = (Queue) context.lookup(qJndiName)
Till now it is the same as sending....
6. Create a javax.jms.QueueReceiver with the session
receiver = session.createReceiver(queue)
7. JMS API provides 2 ways to retrieve a message:
7.a Wait for a message with one of the receiver.receive() methods
7.b Implement javax.jms.MessageListener in your class and register it as the listener
receiver.setMessageListener(this)
JMS API will call your onMessage() method whenever a new message arrives
8. Don't forget to start the listener:
connection.start()
9. Close the context (very important, when you access multiple JMS servers from the same program):
context.close()
The above is a typical solution from a stand-alone application. In EJB environment you should use message driven beans. You can find ino on them on http://java.sun.com/javaee/6/docs/tutorial/doc/gipko.html and a tutorial on http://schuchert.wikispaces.com/EJB3+Tutorial+5+-+Message+Driven+Beans
Here is the working example you've asked for:
import java.util.Hashtable;
import javax.naming.*;
import javax.jms.*;
public class JMSJNDISample implements MessageListener {
public static final String JNDI_URL = "jnp://localhost:1099";
public static final String JNDI_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
public static final String JMS_USER = null;
public static final String JMS_PASSWORD = null;
public static final String JMS_CONNECTION_FACTORY = "MyConnectionFactory";
public static final String QUEUE_JNDI_NAME = "ReceiverQueue";
QueueConnection qConn = null;
QueueSession qSession = null;
QueueSender qSender = null;
QueueReceiver qReceiver = null;
public JMSJNDISample () {
}
public void init() throws JMSException, NamingException {
// Set up JNDI Context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_CONTEXT_FACTORY);
env.put(Context.PROVIDER_URL, JNDI_URL);
if (JMS_USER != null)
env.put(Context.SECURITY_PRINCIPAL, JMS_USER);
if (JMS_PASSWORD != null)
env.put(Context.SECURITY_CREDENTIALS, JMS_PASSWORD);
Context jndiContext = new InitialContext(env);
// Lookup queue connection factory
QueueConnectionFactory cFactory = (QueueConnectionFactory)jndiContext.lookup(JMS_CONNECTION_FACTORY);
// Create Connection
if (JMS_USER == null || JMS_PASSWORD == null)
qConn = cFactory.createQueueConnection();
else {
qConn = cFactory.createQueueConnection(JMS_USER, JMS_PASSWORD);
}
// Create Session
qSession = qConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
// Lookup Queue
Queue queue = (Queue) jndiContext.lookup(QUEUE_JNDI_NAME);
// Create Queue Sender
qSender = qSession.createSender(queue);
// Create Queue Receiver
qReceiver = qSession.createReceiver(queue);
qReceiver.setMessageListener(this);
// Start receiving messages
qConn.start();
// Close JNDI context
jndiContext.close();
}
public void sendMessage (String str) throws JMSException {
TextMessage msg = qSession.createTextMessage(str);
qSender.send(msg);
}
public void onMessage (Message message) {
try {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage)message;
System.out.println("Text Message Received: "+textMessage.getText());
} else {
System.out.println(message.getJMSType()+" Message Received");
}
} catch (JMSException je) {
je.printStackTrace();
}
}
public void destroy() throws JMSException {
if (qSender != null) qSender.close();
if (qReceiver != null) qReceiver.close();
if (qSession != null) qSession.close();
if (qConn != null) qConn.close();
}
public static void main(String args[]) {
try {
JMSJNDISample sample = new JMSJNDISample();
// Initialize connetion
sample.init();
// Send Message
sample.sendMessage("Hello World");
// Wait 2 sec for answer
Thread.sleep(2000);
// Disconnect
sample.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Other than having a MessageDrivenBean listening to that queue?
EDIT:
You are using spring just to create the payload, right? JMS is a JavaEE spec. You don't need to use Spring for actually sending/receiving messages. You don't have to manually check whether there are messages in the queue etc., either. All you need to do is have an MDB(MessageDrivenBean) set up like this,
#MessageDriven(activationConfig = {
#ActivationConfigProperty(
propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(
propertyName = "destination", propertyValue = "queue/myqueue")
})
public class MyMessageDrivenBean implements MessageListener {
public void onMessage(Message message) {
ObjectMessage objMsg = (ObjectMessage) message;
Payload payload = (Payload)objMsg.getObject();
//do stuff
}
}
And then send some JMS messages.
#Stateless
public class QueuerBean implements QueuerLocal {
#Resource(mappedName = "java:/JmsXA")
private ConnectionFactory jmsConnectionFactory;
#Resource(mappedName = "queue/myqueue")
private Queue queue;
private void queue(MyPayload payload) {
try {
Connection connect = jmsConnectionFactory.createConnection();
Session session = connect.createSession(false,
Session.DUPS_OK_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
// create a JMS message and send it
ObjectMessage objMsg = session.createObjectMessage(payload);
producer.send(objMsg);
producer.close();
session.close();
connect.close();
} catch (JMSException e) {
log.error("Bad thing happened", e);
}
}
}
The queue is configured by the annotation. When a message is sent, JBoss will automatically trigger the MDB.
Here's an example showing how to set up a message-driven POJO in Spring. I'd recommend following this idiom if you're already using Spring.
As for the part about seeing how many messages are on the queue, I'd say you should be using the admin console for JBOSS, not your code.
I would recommend also using a tool like HermesJMS (http://www.hermesjms.com/confluence/display/HJMS/Home) to inspect the queue manager and queues. It's a great debugging tool.

Message Driven Bean with a Datasource

My question is how do I configure an EJB 3.0 style message driven bean to use a configured JMS datasource in jboss.
For example, my MDB looks something like:
#MessageDriven(mappedName = "ExampleMDB", activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "MyTopic"),
#ActivationConfigProperty(propertyName = "channel", propertyValue = "MyChannel"),
})
#ResourceAdapter(value = "wmq.jmsra.rar")
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
#TransactionManagement(TransactionManagementType.BEAN)
public class MyMDB implements MessageListener {
.....
}
But I would like the bean to attached to a given JMS datasource ( in the case of jboss 4.2.2 this is in deploy/jms/jms-ds.xml). Perhaps this is not even possible but is worth asking.
If I understood your problem correctly, MyMDB listens to a topic on WebLogic, and you want to use an additional JMS destination provided by JBoss, defined in a deployed configuration file and identified by its JNDI name (by default, deploy/jms/jms-ds.xml only contains the configuration for the JMS provider and connection factories -- no data sources).
The easiest way is to let the container inject the JMS destination and a connection factory via its JNDI name (in JBoss the JMS destinations are configured by deploying xxx-service.xml files). On startup you can then initialize the connection, and perform cleanup as soon as the MDB is released.
The following examples shows injection (#Resource) and resource managemend (#PostConstruct and #PreDestroy). The JMS connection and destination is used in useJmsDestination(String) to send a text message.
public class MyMDB implements MessageListener {
#Resource(mappedName = "queue/YourQueueName") // can be topic too
private Queue targetDestination;
#Resource(mappedName = "QueueConnectionFactory") // or ConnectionFactory
private QueueConnectionFactory factory;
private Connection conn;
public void onMessage(Message m) {
// parse message and do what you need to do
...
// do something with the message and the JBoss JMS destination
useJmsDestination(messageString);
}
private void useJmsDestination(String text) {
Session session = null;
MessageProducer producer = null;
try {
session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(targetDestination);
TextMessage msg = session.createTextMessage(text);
producer.send(msg);
} catch (JMSException e) {
throw new RuntimeException(e);
} finally {
try {
if (producer != null) {
producer.close();
}
if (session != null) {
session.close();
}
} catch (JMSException e) {
// handle error, should be non-fatal, as the message is already sent.
}
}
}
#PostConstruct
void init() {
initConnection();
// other initialization logic
...
}
#PreDestroy
void cleanUp() {
closeConnection();
// other cleanup logic
...
}
private void initConnection() {
try {
conn = factory.createConnection();
} catch (JMSException e) {
throw new RuntimeException("Could not initialize connection", e);
}
}
private void closeConnection() {
try {
conn.close();
} catch (JMSException e) {
// handle error, should be non-fatal, as the connection is being closed
}
}
}
I hope this can help you.
I think what you are asking is "How do I specify the JNDI location of the JMS datasource to use for an MDB?"
In which case the answer is:
#ActivationConfigProperty(propertyName = "providerAdapterJNDI", propertyValue = "java:/DefaultJMSProvider")
Also, take a look at the following page which provides loads of useful details on configuring MDBs in jBoss:
http://www.jboss.org/community/docs/DOC-9352

Categories

Resources