I'm so stuck about this.
I want to subscribe an ActiveMQ topic. ActiveMQ works on Centos machine, NOT LOCALHOST. I can consume messages with tcp, http protocols. Code;
public static void main(String[] args) throws JMSException {
PropertyUtils.loadPropertyFile();
Properties receiverProperties = PropertyUtils.getreceiverProperties();
// URL of the JMS server
String url = (String) receiverProperties.get("receiver.connection.url");
// Name of the queue we will receive messages from
String subject = (String) receiverProperties.get("receiver.topic.name");
// Getting JMS connection from the server
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
// Creating session for getting messages
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Getting the topic
Destination destination = session.createTopic(subject);
// MessageConsumer is used for receiving (consuming) messages
MessageConsumer consumer = session.createConsumer(destination);
Message message = null;
// Here we receive the message.
while (true) {
message = consumer.receive();
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println("Received message '" + textMessage.getText() + "'");
}
}
// We will be using TestMessage in our example. MessageProducer sent us a
// TextMessage
// so we must cast to it to get access to its .getText() method.
// connection.close();
}
I want to use wss protocol. This is a must for me. When I changed url with wss://host:port getting;
Could not create Transport. Reason: java.io.IOException: createTransport() method not implemented!
So I checked the alternatives. People figure this out with Stomp over WS. My first achievement is wss connection.
Any recommendation will be appreciated!
The exception you're seeing is expected because the OpenWire JMS client you're using doesn't support WebSocket connections, and it doesn't really need to. WebSocket connections are really only relevant for clients running in a limited environment like a web browser. Web browsers don't support running Java clients.
If you really want to use STOMP over WebSockets then you'll have to use a STOMP client implementation that supports WebSockets (most do).
Keep in mind that ActiveMQ is a broker. It does not supply clients for all the protocols it supports. It only provides a JMS client because it is required in order to implement JMS. STOMP, for example, is a standardized protocol and anyone can implement a client which will work with any broker implementing STOMP. There are lots of STOMP client implementations available written in many different languages for many different platforms. Any good search engine should help you find one to fit your needs.
Related
is it possible to establish rabbitMQ connection with javax.jms (not using rabbitMQ jms client/ java client )? if yes how (not with springboot).
You either need to use the driver or write your own driver. You should not expect anyone here to write it for you. What have you tried?
Yes it's possible. RabbitMQ provides a class implementing JMS Connection factory com.rabbitmq.client.ConnectionFactory:
ConnectionFactory connectionFactory = new Connection().newConnection();
// create a Connection
connection = connectionFactory.createConnection();
connection.setClientID(clientId);
// create a Session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// create the Topic from which messages will be received
Topic topic = session.createTopic(topicName);
// create a MessageConsumer for receiving messages
messageConsumer = session.createConsumer(topic);
// start the connection in order to receive messages
connection.start();
Except for the first line (Factory creation), this is pure JMS code.
The application I am working on needs to communicate to an IBM MQ server in a remote location. We currently have a working system using active MQ which uses a broker, and a bridge to connect to this remote IBM MQ server and is working fine.
Due to some new enhancement, we are now trying to achieve the same using IBM client jars instead of Active MQ.
The problem I am facing is that I can connect to the remote server's inboundQ and send messages.But I am always receiving null from the remote servers outbound Queue. But I have no way to check if the messages are received at the remote location. But the same message if sending through the old ActiveMQ system will get a response from remote MQ server.
Old Active MQ internally uses the bridge to connect to remote IBM MQ server which is configured exactly like the new code I am using.
I have tried multiple codes from internet and stack overflow itself and always I am able to connect but not getting any responses.
Also, I get no errors or exceptions while trying to send or receive from remote IBM MQ.
I will paste a sample code which I am trying to get to work. I have changed some configuration values in the code.
My doubts are the following.
All I am doing for this is copying IBM MQ client jars into the application and using the code to send messages to remote MQ. I have not installed any other application. Will such a system work or should there always be some intermediate program like active MQ?
The same code is able to send and receive from an IBM MQ server which I installed in our local network but fails to get a response from the remote server? This leads me to believe if I am missing anything in configuration ? should anything else be configured other than in code?
I see no errors or exceptions. Always message is sent but the response is null. I have not seen the usage of any username-password or public-private key authentication. Is there any authentication used normally to check the source. ?
I am using IBM MQ client 5.3 version which I know is old. But used that since they working active MQ setup uses the same and is working correctly. I have no way of knowing which version on IBM MQ server is present on the remote machine. Is there a problem if we use a different client MQ version than the version of server MQ version. ?
Sample code which works for me in local environment ie is able to send and receive from an IBM MQ server I have installed in another machine in the local network. The same code will fetch null response when I am trying to use it with remote IBM MQ server.
import javax.jms.*;
import javax.jms.JMSException;
import com.ibm.mq.jms.*;
import com.ibm.jms.JMSMessage;
import javax.jms.TextMessage;
public class SendReceive {
private MQQueueConnectionFactory connectionFactory;
private MQQueueConnection connection;
private void runTest() {
try {
connect();
connection.start();
MQQueueSession session = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueue queue = (MQQueue) session.createQueue("INBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueue queue2 = (MQQueue) session.createQueue("OUTBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueueSender sender = (MQQueueSender) session.createSender(queue);
MQQueueReceiver receiver = (MQQueueReceiver) session.createReceiver(queue2);
//TextMessage message = session.createTextMessage("yesyesyes");
String stt = "Test Message"; //
TextMessage message = session.createTextMessage(stt);
message.setJMSReplyTo(queue2);
sender.send(message);
System.out.println("Sent: " + message);
Message msg1 = receiver.receive(5000);
if(msg1!=null){
String responseMsg = ((TextMessage) msg1).getText();
System.out.println("Received: " + responseMsg);
}else{
System.out.println("Message received is null");
}
}catch(Exception e){
System.out.println("Exception caught in program : " + e);
e.printStackTrace();
}
}
public boolean connect() {
boolean connected = false;
try {
/* values below are replaced with correct values in deployment server */
connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setPort(1515);
connectionFactory.setHostName("192.168.1.23"); //
connectionFactory.setQueueManager("QCCMGR");
connectionFactory.setChannel("QCHANNEL");
connectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
connection = (MQQueueConnection) connectionFactory.createQueueConnection();
connected = true;
} catch (Exception e) {
connected = false;
}
return connected;
}
public static void main(String[] args) {
new SendReceive().runTest();
}
}
MQ v5.3 was released November 29th 2002 and has been out of support since September 28th 2007 (almost 9 years). The version may not have anything to do with your issue but I would strongly suggest that you move to a supported version of the MQ client. Newer MQ client versions can connect to older MQ queue managers. You can download a java only install of MQ 8.0 or MQ 9.0 jar files at the links below:
IBM MQ v8.0 Client
IBM MQ v9.0 Client
I read on some old threads that having the sender and receiver on the same session caused problems when a timeout was specified. Try adding another session for the receiver.
private void runTest() {
try {
connect();
connection.start();
MQQueueSession session = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueueSession session2 = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueue queue = (MQQueue) session.createQueue("INBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueue queue2 = (MQQueue) session2.createQueue("OUTBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueueSender sender = (MQQueueSender) session.createSender(queue);
MQQueueReceiver receiver = (MQQueueReceiver) session2.createReceiver(queue2);
//TextMessage message = session.createTextMessage("yesyesyes");
String stt = "Test Message"; //
TextMessage message = session.createTextMessage(stt);
message.setJMSReplyTo(queue2);
sender.send(message);
System.out.println("Sent: " + message);
Message msg1 = receiver.receive(5000);
if(msg1!=null){
String responseMsg = ((TextMessage) msg1).getText();
System.out.println("Received: " + responseMsg);
}else{
System.out.println("Message received is null");
}
}catch(Exception e){
System.out.println("Exception caught in program : " + e);
e.printStackTrace();
}
}
Try taking a JMS trace by adding the following to the execution of the java app:
-DMQJMS_TRACE_LEVEL=base
-DMQJMS_TRACE_DIR=/tracedirectory
ex: java -DMQJMS_TRACE_LEVEL=base -DMQJMS_TRACE_DIR=/tracedirectory JavaApp
This should produce a file that I believe ends in .trc in the directory you specify.
You can review this for errors that might help point you in the right direction.
Suggestions:
Try changing your program to force it to send a blank username:
connection = (MQQueueConnection) connectionFactory.createQueueConnection("", "");
Try closing the sender after sender.send is called
sender.close();
With out further information it is difficult to determine the cause. The more information you can gather the better.
It could be some network related configuration issue or maybe Windows Messaging not configured well. You may consider giving WebSphere MQ - Message Test Utility by IBM to ensure that there are no such system or network configuration issues are present.
I have a question as regards JMS Queues.
I have implemented a jms sender/reciever using a shared queue as its the only queue avaialbe to me and the only one i can use.
The problem that i am now faced with is that i as this first come first served i cannot guarentee that the messages that i am sending from my producer will be consumed by my consumer and not the other sharing this queue and vice versa. So i am consuming the other apps messages and they are consuming mine.
Is there a way i can just listen for my messages and not consume them from the queue or is this more of a topic implementation?
Or perhaps i can explicitly set an identifier that only my consumer will pick up.
My main code:
public class AsyncReceiver implements MessageListener, ExceptionListener
{
public static void main(String[] args) throws Exception
{
//create queue factory
factory = new TibjmsQueueConnectionFactory(serverUrl);
//create queue connection
queueConn = factory.createQueueConnection(userName, password);
queueConn.setExceptionListener(this);
//create queue session
session = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
//receive message by QueueReceiver
final Queue queue = session.createQueue(queueName);
final QueueReceiver queueReceiver = session.createReceiver(queue);
queueReceiver.setMessageListener(this);
queueConn.start ();
}
You should use JMS selector. Every JMS message can contain properties that you initiate at sender's side.
Message consumer can register to JMS destination (either queue or topic) specifying selector - SQL-like statement that explains which messages does it want to consume. So you can specify your application specific property and then receive relevant messages only.
You could use message selector as shown below
queueReceiver = queueSession.createReceiver(responseQueue, "JMSCorrelationID='"
+ requestMessage.getJMSCorrelationID() +"'");
Here i am using the JMS correlation ID to identify the correct message I need.
Please note that the filter will only work on Message Header and Message properties.
It will not work on the message content.
Details on Message Header & Properties: http://docs.oracle.com/javaee/1.4/tutorial/doc/JMS4.html#wp79367
If you need to filter based on message content, you may have to use QueueSession.MANUAL_ACKNOWLEDGE mode and acknowledge messages that you want. In this case the application has to have the logic to identify messages based on content. Not the ideal design though.
I am having a problem about JMS. The problem is, I have an application and it is trying to send a message through JMS , but after JMS server restart, it throws exception as when the server was down time. It is not reconnecting.
It is completely fine without a restart of JMS server and I am using weblogic 10.x.
Is it a problem about JMS configuration?
Thanks
Can you post your code how you are sending messages?
If you attempt to send a message when the JMS server is down, you will probably have an exception, and have to deal with that. When you attempt to send a message the next time, when the JMS server is restarted and running, you probably create a new connection from your connection factory. Reconnection will happend then:
// Let's say, you inject CF and Dest.
#Resource(lookup = "jms/ConnectionFactory")
private static ConnectionFactory cf;
#Resource(lookup = "jms/MyQueue")
private static Destination dest;
public void sendMessage(){ // called every time you need to send a message.
try{
Connection con = cf.createConnection(); // will reconnect, otherwise pooled.
Session sess = con.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sess.createProducer(dest);
Message msg = sess.createTextMessage("Hello, World");
prod.send(msg);
sess.close();
con.close();
}catch(Exception e){
// handle errors
}
}
However, there are some built in failover/reconnecting features in Weblogic JMS, take a look at this page:
Oracle code listing and documentation about reconnecting JMS producers
I haven't touched any J2EE stuff in years and I need to whip up a quick JMS client for a demo.
I'm using Eclipse, on OS X and I can't even get started because I can't seem to figure out how to get the required libraries.
This is supposed to be a simple stand alone application (not running in a container) that pulls messages from a topic.
Every JMS implementation has its own set of libraries that specify how you get the initial connection factory. If you have an existing server from which to pull messages, you need to examine the documentation of that server to determine where to find the libraries to put in your classpath and how to create your initial connection factory. If you want to create a server for the purposes of the demonstration, I recommend using an embedded Active MQ broker.
Once you have your connection factory, polling for messages from a topic is pretty straightforward. Here is some example code which can be called to drain a topic of its current messages.
// Implementation specific code
public void drainTopic(TopicConnectionFactory factory, String topicName, String subscriberId)
// set factory properties like the server ID
Connection conn = factory.createConnection();
conn.start();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(topicName);
MessageConsumer consumer = session.createDurableSubscriber(topic, subscriberId);
Message message;
while (null != (message = consumer.receive(1000))) {
// do work on the message
}
conn.close();
}
Note the use of a durable subscriber. This means that I don't have to try to maintain a single connection all the time and handle the errors if it times out somehow. But because the subscription is durable, the server knows to retain any messages the topic receives while I'm not connected and provide them on my next connection. This code would be the same regardless of the host OS. The only tricky part is the creation of the provider specific connection factory.