Migrating from WebSphere MQ to Active MQ - activemq

There was a similar question Procedure to migrate from IBM MQ to ActiveMQ and it was closed, but I will try anyway.
Our customers want to migrate from WebSphere MQ to Active MQ. In above mentioned question it was said that as for JMS such migration in theory will consist in apps re-configuration. Our customers say that their apps use auto-generated .bindings file. So, is it possible to make apps work with Active MQ just by editing .binding file and putting active mq's .jars to java classpath, or some other configuration is required?

To check this , i tried the following
a) Create a WMQ bindings file use JMSAdmin. Once i created a QCF and Queue i was able to send a message via a JMS lookup and send a message.
b) For the AMQ set up to generate a .bindings file , IBM had some sample code to generate the bindings file.
Once this was done i used exactly the same code to send a message and the message was perfectly sent to both AMQ and WMQ
Here is the sample code that i was able to interoperate.
public void sendMessages() {
ConnectionFactory connectionFactory;
Connection con = null;
Session session = null;
MessageProducer producer = null;
//create initial context properties
Properties initialContextProperties = new Properties();
initialContextProperties.put("java.naming.factory.initial", "com.sun.jndi.fscontext.RefFSContextFactory");
initialContextProperties.put(Context.PROVIDER_URL, "file:/C:/JNDI-Directory/AMQ");
initialContextProperties.setProperty("transport.jms.security.authentication", "none");
try {
InitialContext initialContext = new InitialContext(initialContextProperties);
//create connection factory object
//ivtQCF - created connection factory object in IBM-MQ
connectionFactory = (ConnectionFactory) initialContext.lookup("confact2");
con = connectionFactory.createConnection();
con.start();
session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
//localq - created queue in IBM-MQ
Destination destination = (Destination) initialContext.lookup("dest");
producer = session.createProducer(destination);
String msg = "SAMPLE MESSAGE PLACED TO QUEUE";
TextMessage textMessage = session.createTextMessage(msg);
producer.send(textMessage);
con.close();
session.close();
producer.close();
} catch (NamingException e) {
throw new RuntimeException("Unable to send jms messages", e);
} catch (JMSException e) {
throw new RuntimeException("Unable to send jms messages", e);
}
}

Related

How to catch error when message have been sent from JMS

I am sending an message through my standalone application that uses EJB MDB to communicate to my other application server that is running on JBOSS server.My application server is connected to a MSSQL server. In certain scenario, connection to the database is lost on application server side and we get following error -
Connection is reset.
Later , when i try to send message i don't get any error at my standalone EJB MDB logs and the process just stops executing.I get error log on application server side logs but same logs don't get propagated to my EJB MDB error logs.
As per my understanding, when db connection is lost all the ejb bean present in jboss container get nullified too.(I could be wrong here, i am new to EJB).
I tried implementing below code in my code that use to send message -
QueueConnection qcon = null;
#PostConstruct
public void initialize() {
System.out.println("In PostConstruct");
try {
qcon = qconFactory.createQueueConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
#PreDestroy
public void releaseResources() {
System.out.println("In PreDestroy");
try {
if(qcon != null)
{
qcon.close();
}
if(qcon== null){
throw new Exception(" new exception occured.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
I was in a impression that Queueconnection object will be nullified, when our db connection have been lost(as we are creating bean and making connection for message). But it doesn't seem to work.
I did found a way to call back my application after sending message. I used a separate temporary queue and used setJMSReplyTo method to set the reply destination. More info could be obtained from this
link. Hope this helps others.

Message is Not a JMSTextMessage error in MobileFirst 7.0 JMS Adapter

I am sending JMS message to HornetQ and consuming this message from MobileFirst 7.0 adapter. Following is my producer code:
public void sendObjectMessage(Serializable object){
Connection con = null;
Session session = null;
MessageProducer producer = null;
try{
con = this.template.getJmsDataSource().getConnection();
session = this.template.getSession(con);
producer = this.template.getMessageProducer(session);
ObjectMessage message = session.createObjectMessage();
message.setObject(object);
producer.send(message);
}catch(JMSException ex){
BaseRunTimeException.wrapAndThrow(ex);
}finally{
JmsUtils.closeMessageProducer(producer);
JmsUtils.closeSession(session);
JmsUtils.closeConnection(con);
}
}
When I am trying to consume the message using MF adapter it is throwing me below message:
"Runtime: java.lang.RuntimeException: com.worklight.adapters.jms.NotJMSTextMessageException: Message is Not a JMSTextMessage: HornetQMessage[ID:0db1cb4e-8d4a-11e5-a8d1-0f826151395f]:PERSISTENT"
My question is, is there any way through which I can consume custom serializable classes sent by my application in MF JMS adapter? Are only JMSTextMessage supported by MF adapter?
Unfortunately, the MFP server supports only javax.jms.TextMessage or derived classes for reading messages.

ActiveMQ, Wildfly and get message body (getBody)

I am new to JEE7 and have been working on some quick exercises but I've bumped into a problem. I have a sample Java SE application that sends a message to an ActiveMQ queue and I have an MDB deployed on Wildfly 8 that reads the messages as they come in. This all works fine and I can receive the messages using getText. However, when I use getBody to get the message body, I get an "Unknown Error". Can anyone let me know what I'm doing wrong?
Here's my code below;
/***CLIENT CODE****/
import javax.jms.*;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class SimpleMessageClient {
// URL of the JMS server. DEFAULT_BROKER_URL will just mean
// that JMS server is on localhost
private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;
// Name of the queue we will be sending messages to
private static String subject = "MyQueue";
public static void main(String[] args) throws JMSException {
// Getting JMS connection from the server and starting it
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
// JMS messages are sent and received using a Session. We will
// create here a non-transactional session object. If you want
// to use transactions you should set the first parameter to 'true'
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
// Destination represents here our queue 'TESTQUEUE' on the
// JMS server. You don't have to do anything special on the
// server to create it, it will be created automatically.
Destination destination = session.createQueue(subject);
// MessageProducer is used for sending messages (as opposed
// to MessageConsumer which is used for receiving them)
MessageProducer producer = session.createProducer(destination);
// We will send a small text message saying 'Hello' in Japanese
TextMessage message = session.createTextMessage("Jai Hind");
//Message someMsg=session.createMessage();
// someMsg.
// Here we are sending the message!
producer.send(message);
System.out.println("Sent message '" + message.getText() + "'");
connection.close();
}
}
And the consumer;
package javaeetutorial.simplemessage.ejb;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
#MessageDriven(activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "MyQueue")
})
public class SimpleMessageBean implements MessageListener {
#Resource
private MessageDrivenContext mdc;
static final Logger logger = Logger.getLogger("SimpleMessageBean");
public SimpleMessageBean() {
}
#Override
public void onMessage(Message inMessage) {
try {
if (inMessage instanceof TextMessage) {
logger.log(Level.INFO,
"MESSAGE BEAN: Message received: {0}",
inMessage.getBody(String.class));
} else {
logger.log(Level.WARNING,
"Message of wrong type: {0}",
inMessage.getClass().getName());
}
} catch (JMSException e) {
e.printStackTrace();
logger.log(Level.SEVERE,
"SimpleMessageBean.onMessage: JMSException: {0}",
e.toString());
mdc.setRollbackOnly();
}
}
}
Part of the error I get is;
16:47:48,510 ERROR [org.jboss.as.ejb3] (default-threads - 32) javax.ejb.EJBTransactionRolledbackException: Unexpected Error
16:47:48,511 ERROR [org.jboss.as.ejb3.invocation] (default-threads - 32) JBAS014134: EJB Invocation failed on component SimpleMessageBean for method public void javaeetutorial.simplemessage.ejb.SimpleMessageBean.onMessage(javax.jms.Message): javax.ejb.EJBTransactionRolledbackException: Unexpected Error
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:157) [wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:253) [wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:342) [wildfly-ejb3-8.2.0.Final.jar:8.2.0.Final]
The method
<T> T Message.getBody(Class<T> c)
you refer to was an addition to JMS 2.0 (see also: http://www.oracle.com/technetwork/articles/java/jms20-1947669.html).
While WildFly 8 is fully compliant to Java EE 7 and therefore JMS 2.1, the current ActiveMQ (5.12.0) is still restricted to JMS 1.1.
Since you presumably import the JMS 2.1 API in your SimpleMessageBean, you reference a method simply not present in the ActiveMQ message.
When you try to call the getBody()-method on the message, it cannot be resolved in the message implementation and hence an AbstractMethodError is thrown. This results in the rollback of the transaction which gives you the EJBTransactionRolledbackException.
I see two immediate solutions for your problem:
If you want to keep using ActiveMQ, confine yourself to the JMS 1.1 API. The getText()-method you mentioned is part of JMS 1.1 and therefore works flawlessly. See here for the JMS 1.1 API (https://docs.oracle.com/javaee/6/api/javax/jms/package-summary.html) and here for the current ActiveMQ API documentation (http://activemq.apache.org/maven/5.12.0/apidocs/index.html).
Switch to a JMS 2.x compliant message broker. Since you are using WildFly, I recommend taking a look at HornetQ (http://hornetq.jboss.org/).

Sending Text Message using JMS on glassfish server

I am testing JMS with glassfish server so for that i want to send simple text message on glassfish server queue. I have tried with ActiveMQ and that is going fine but i unable to understand what can i put in configuration jndi.properties file and which jar is needed for glassfish server. Please give me some idea to implement this.
thanks in advance
Since you're using Glassfish, the easiest way is to write simple application (EJB) that will perform the task. You have to define in GF:
ConnectionFactory (Resources -> JMS Resources -> Connection Factory),
let's give it JNDI name jms/ConnectionFactory
Message queue (Resources -> JMS Resources -> Destination Resources),
let's give it JNDI name jms/myQueue
Next step is to use these in some EJB that you need to write. It's not hard: firstly, you have to inject:
#Resource(mappedName="jms/ConnectionFactory")
private ConnectionFactory cf;
#Resource(mappedName="jms/myQueue")
private Queue messageQueue;
and then use it like this:
..
javax.jms.Connection conn = null;
javax.jms.Session s = null;
javax.jms.MessageProducer mp = null
try {
conn = cf.createConnection();
s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
mp = s.createProducer(messageQueue);
javax.jms.TextMessage msg = s.createTextMessage();
msg.setStringProperty("your-key", "your-value");
msg.setText("Your text message");
mp.send(msg);
}
catch(JMSException ex) {
// exception handling
}
finally {
try {
// close Connection, Session and MessageProducer
} catch (JMSException ex) {
//exception handling
}
}
Regarding configuration, you don't need any external JAR, everything that is needed is shipped. If you don't want to write EJB, but regular Java (standalone) application, then you'll have to include jms.jar and imq.jar.

Problems creating JMS Queue on Glassfish

i'm get the following error when deploying my application with a JMS producer and consumer
com.sun.enterprise.connectors.ConnectorRuntimeException: JMS resource not created : QueueName
I used the annotations below:
Producer
#Resource(name = "jms/EmailNotificationQueue", mappedName = "EmailNotificationQueue")
private Destination destination;
#Resource(name = "jms/QueueConnectionFactory")
private ConnectionFactory connectionFactory;
I then create the connection and start it before sending the message
Consumer
#MessageDriven(name = "EmailNotificationBean", activationConfig = {
#ActivationConfigProperty(
propertyName="destinationType",
propertyValue="javax.jms.Queue"),
#ActivationConfigProperty(
propertyName="destinationName",
propertyValue="EmailNotificationQueue"),
#ActivationConfigProperty(
propertyName="acknowledgeMode",
propertyValue="CLIENT_ACKNOWLEDGE")
}
,mappedName = "EmailNotificationQueue"
)
Have you manually created the Destination?
Log into the admin console, expand Resource, JMS Resources, then Destination Resources. You'll probably need to create a connection factory as well.