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.
Related
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.
I am trying to send messages to MQ Queue from the java program running on Websphere Application Server.
I configured QConnection Factory & Q jndis in Websphere Applciaiton server. But when running program I am getting error
Details: "com.ibm.ejs.jms.JMSConnectionFactoryHandle incompatible with javax.jms.QueueConnectionFactory".
at com.ibm.bpm.rest.impl.service.ServiceRunner$TaskRunner.runService(ServiceRunner.java:1385)
at com.ibm.bpm.rest.impl.service.StartActionHandler.handleActionGetModel(StartActionHandler.java:363)
at com.ibm.bpm.rest.impl.playback.ServicePlaybackResourceImpl.createServicePlayback(ServicePlaybackResourceImpl.java:141)
at com.ibm.bpm.rest.impl.playback.ServicePlaybackResource.createServicePlayback(ServicePlaybackResource.java:115)
at sun.reflect.GeneratedMethodAccessor742.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
This is the program I am using. Any help is greatly appreciated.
public void putMessageViaCF3(String messageContent, String connectionFactory, String sendQName)
throws MQException, IOException, NamingException, JMSException {
Queue myQueue;
QueueConnectionFactory myQueueFactory;
QueueConnection connection = null;
QueueSession session = null;
try {
InitialContext jndi = new InitialContext();
myQueueFactory = (QueueConnectionFactory) jndi.lookup("jms/SORC_QM_CF");
myQueue = (Queue) jndi.lookup("jms/SORC_SEND_Q");
connection=myQueueFactory.createQueueConnection();
session = connection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(myQueue);
connection.start();
TextMessage textMessage = session.createTextMessage("Test Harish");
textMessage.setStringProperty("messageType", "file");
sender.send(textMessage);
sender.close();
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
According to this resource from IBM this kind of ClassCastException is seen when:
...a queue connection factory is defined as a WebSphere MQ Connection Factory instead of a WebSphere MQ Queue Connection Factory.
To resolve this you should either:
Define the connection factory as a WebSphere MQ Queue Connection Factory.
Use a javax.jms.ConnectionFactory object in the application code rather than a javax.jms.QueueConnectionFactory object.
I am following this tutorial to read messages from a given subscription. I have created a Receive class like this -
public class Receive implements MessageListener{
private static boolean runReceiver = true;
private Connection connection;
private Session sendSession;
private Session receiveSession;
private MessageProducer sender;
private MessageConsumer receiver;
private static Random randomGenerator = new Random();
public Receive() throws Exception {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put("connectionfactory.SBCF", "amqps://All:[shared-access-key]#[namespace].servicebus.windows.net?amqp.idleTimeout=120000");
env.put("topic.TOPIC", "job/Subscriptions/job-test-subscription");
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
Context context = new InitialContext(env);
// Look up ConnectionFactory and Queue
ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");
Destination queue = (Destination) context.lookup("TOPIC");
// Create Connection
connection = cf.createConnection();
// Create sender-side Session and MessageProducer
sendSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
sender = sendSession.createProducer(queue);
if (runReceiver) {
// Create receiver-side Session, MessageConsumer,and MessageListener
receiveSession = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
receiver = receiveSession.createConsumer(queue);
receiver.setMessageListener(this);
connection.start();
}
}
public void close() throws JMSException {
connection.close();
}
public void onMessage(Message message) {
try {
System.out.println("Received message with JMSMessageID = " + message.getJMSMessageID());
message.acknowledge();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
Receive simpleReceiver = new Receive();
} catch (Exception e) {
e.printStackTrace();
}
}
On executing this programI am getting this error -
log4j:WARN No appenders could be found for logger (io.netty.util.internal.logging.InternalLoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
javax.jms.JMSException: hostname can't be null
at org.apache.qpid.jms.exceptions.JmsExceptionSupport.create(JmsExceptionSupport.java:86)
at org.apache.qpid.jms.exceptions.JmsExceptionSupport.create(JmsExceptionSupport.java:108)
at org.apache.qpid.jms.JmsConnection.connect(JmsConnection.java:172)
at org.apache.qpid.jms.JmsConnectionFactory.createConnection(JmsConnectionFactory.java:204)
at org.apache.qpid.jms.JmsConnectionFactory.createConnection(JmsConnectionFactory.java:191)
at Receive.<init>(Receive.java:41)
at Receive.main(Receive.java:63)
Caused by: java.io.IOException: hostname can't be null
at org.apache.qpid.jms.util.IOExceptionSupport.create(IOExceptionSupport.java:45)
at org.apache.qpid.jms.provider.amqp.AmqpProvider$2.run(AmqpProvider.java:217)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: hostname can't be null
at java.net.InetSocketAddress.checkHost(InetSocketAddress.java:149)
at java.net.InetSocketAddress.createUnresolved(InetSocketAddress.java:254)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:126)
at org.apache.qpid.jms.transports.netty.NettyTcpTransport.connect(NettyTcpTransport.java:167)
at org.apache.qpid.jms.provider.amqp.AmqpProvider$2.run(AmqpProvider.java:195)
... 7 more
Error is pointing towards this line - connection = cf.createConnection();
Also would like to know if providing my topic and subscription name like this -job/Subscriptions/job-test-subscription is fine or not.
Apologies for posting a long post.
According to the subsection Service Bus entity address from here, the job/Subscriptions/job-test-subscription value is your subscription address, not topic. Please change your url and topic property as below and try again.
connectionfactory.SBCF=amqps://All:[shared-access-key]#[namespace].servicebus.windows.net/job/Subscriptions/job-test-subscription?amqp.idleTimeout=120000
topic.TOPIC=job
Hope it helps.
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
EDIT: Rephrased the question:
I want to use ActiveMQ as a messenger service between my server and client applications.
I am trying to set up an embedded broker (i.e. not a separate process) within the server to handle the produced messages for my clients to consume. This queue is persisted.
The broker initialisation as follows:
BrokerService broker = new BrokerService();
KahaPersistenceAdapter adaptor = new KahaPersistenceAdapter();
adaptor.setDirectory(new File("activemq"));
broker.setPersistenceAdapter(adaptor);
broker.setUseJmx(true);
broker.addConnector("tcp://localhost:61616");
broker.start();
After tinkering, I ended up with the server part being:
public static class HelloWorldProducer implements Runnable {
public void run() {
try {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost"); // apparently the vm part is all i need
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("TEST.FOO");
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
String text = "Hello world! From: " + Thread.currentThread().getName() + " : " + this.hashCode();
TextMessage message = session.createTextMessage(text);
System.out.println("Sent message: "+ message.hashCode() + " : " + Thread.currentThread().getName());
producer.send(message);
session.close();
connection.close();
}
catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
}
The client is very similar and looks like this:
public static class HelloWorldConsumer implements Runnable, ExceptionListener {
public void run() {
try {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost");
Connection connection = connectionFactory.createConnection(); // exception happens here...
connection.start();
connection.setExceptionListener(this);
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("TEST.FOO");
MessageConsumer consumer = session.createConsumer(destination);
Message message = consumer.receive(1000);
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
System.out.println("*****Received: " + text);
} else {
System.out.println("*****Received obj: " + message);
}
consumer.close();
session.close();
connection.close();
} catch (Exception e) {
System.out.println("Caught: " + e);
e.printStackTrace();
}
}
The main method simply starts each of these in a thread to start producing/receiving messages.
...but I am running into the following with the start of each thread:
2013-01-24 07:54:31,271 INFO [org.apache.activemq.broker.BrokerService] Using Persistence Adapter: AMQPersistenceAdapter(activemq-data/localhost)
2013-01-24 07:54:31,281 INFO [org.apache.activemq.store.amq.AMQPersistenceAdapter] AMQStore starting using directory: activemq-data/localhost
2013-01-24 07:54:31,302 INFO [org.apache.activemq.kaha.impl.KahaStore] Kaha Store using data directory activemq-data/localhost/kr-store/state
2013-01-24 07:54:31,339 INFO [org.apache.activemq.store.amq.AMQPersistenceAdapter] Active data files: []
2013-01-24 07:54:31,445 DEBUG [org.apache.activemq.broker.jmx.ManagementContext] Probably not using JRE 1.4: mx4j.tools.naming.NamingService
2013-01-24 07:54:31,450 DEBUG [org.apache.activemq.broker.jmx.ManagementContext] Failed to create local registry
java.rmi.server.ExportException: internal error: ObjID already in use
at sun.rmi.transport.ObjectTable.putTarget(ObjectTable.java:186)
at sun.rmi.transport.Transport.exportObject(Transport.java:92)
at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:247)
at sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:411)
at sun.rmi.transport.LiveRef.exportObject(LiveRef.java:147)
<snip....>
It seems like the messages are produced and consumed successfully (the other issues I previously posted about was resolved), but the above exception is worrying me.
EDIT: During broker shutdown, I am now also greeted by the following:
2013-01-25 08:40:17,486 DEBUG [org.apache.activemq.transport.failover.FailoverTransport] Transport failed with the following exception:
java.io.EOFException
at java.io.DataInputStream.readInt(DataInputStream.java:392)
at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:269)
at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:210)
at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:202)
at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:185)
at java.lang.Thread.run(Thread.java:722)
You can embed a broker into your code in a number of ways, much of which is documented here. You may want to try upgrading you version since what you are using appears to be quite old as it defaulting to the now deprecated AMQ Store instead of the newer KahaDB store. You might be having issues because of a race between the client threads as they use the different connection factories which could race to create in VM brokers. If you set the create=false option on the producer and ensure the consumer thread starts after that could address the issue, or you could create the VM broker ahead of time and the add create=false to both thread's and that might do the trick.
BrokerService broker = new BrokerService();
// configure the broker
broker.setBrokerName("localhost");
broker.setUseJmx(false);
broker.start();
And then in the client code just attach via this connection factory configuration.
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost?create=false");
When I run your code, I got the below exception:
javax.jms.JMSException: Could not connect to broker URL: tcp://localhost.
Reason java.lang.IllegalArgumentException: port out of range:-1
Your broker is running and listening to port 61616, so any client which tries to connect to broker need to have the port in its URL.
The client code tries to connect to localhost but doesn't mention the port to which it has to connect.
Both the producer and consumer code needs to be fixed.
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost");
To
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
After fixing the port, I was able to run your code.