Tuesday, July 3, 2012

WebLogic, move JMS messages in Java

Here how to move JMS messages in WLST http://www.javamonamour.org/2011/09/wlst-move-jms-messages.html


Here the Javadoc of the JMSDestinationRuntimeMBean.moveMessages():

http://docs.oracle.com/cd/E24001_01/apirefs.1111/e13951/mbeans/JMSDestinationRuntimeMBean.html?skipReload=true#moveMessages



selector is "JMSMessageID = '${jmsmessageid}'"

javax.management.openmbean.CompositeData you can get it with the JMSDestinationRuntimeMBean.getDestinationInfo() method.



So this code will work:

// ctx is a proper InitialContext

  String destinationJNDI = request.getParameter("destinationJNDI");
  String intermediateJNDI = destinationJNDI.replace("ReprocessQ", "Q");
  String jmsmessageid = request.getParameter("jmsmessageid");
  javax.jms.Queue queue = (javax.jms.Queue) ctx.lookup(destinationJNDI);
  javax.jms.Queue intermediateQueue = (javax.jms.Queue) ctx.lookup(intermediateJNDI);
    
  // lookup the queue connection factory
  QueueConnectionFactory queueConnFactory = (QueueConnectionFactory) ctx.lookup(WEBLOGIC_JMS_XA_CONNECTION_FACTORY);
  // create a queue connection
  QueueConnection queueConn = queueConnFactory.createQueueConnection();
  // create a queue session
  Session queueSession = queueConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
  
  // start the connection
  queueConn.start();
  
  JMSDestinationRuntimeMBean reprocessQueueMBean = JMSRuntimeHelper.getJMSDestinationRuntimeMBean( ctx, queue);
  JMSDestinationRuntimeMBean intermediateQueueMBean = JMSRuntimeHelper.getJMSDestinationRuntimeMBean( ctx, intermediateQueue);
  // see http://docs.oracle.com/cd/E24001_01/apirefs.1111/e13951/mbeans/JMSDestinationRuntimeMBean.html?skipReload=true#moveMessages
  reprocessQueueMBean.moveMessages("JMSMessageID = '" + jmsmessageid + "'", intermediateQueueMBean.getDestinationInfo());




8 comments:

Menaka Balakrishnamoorthy said...

Hi,

Could you please tell me how to get jmsmessageid in the above code or post the full code.

Thanks,
Marguerite

Pierluigi Vernetto said...

the code above is to move a specific message..... you can find the jmsmessageid using a queue browser (HermesJMS or use standard QueueBrowser from Java) or even using WebLogic console JMS queue browser.

Menaka Balakrishnamoorthy said...
This comment has been removed by the author.
Menaka Balakrishnamoorthy said...
This comment has been removed by the author.
Menaka Balakrishnamoorthy said...

Hi,

Thanks for the reply
I got jmsmessageid, but the messages are not moved to the destination queue. could you please help me out

package com.xxx.util;

public class MoveMessages implements MessageListener {

public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
public final static String JMS_FACTORY="mslv/oms/oms1/internal/jms/ConnectionFactory";
public final static String QUEUE1="oracle/communications/ordermanagement/OrderResponseQueue";
public final static String QUEUE2="oracle/communications/ordermanagement/OrderRequestQueue";
private QueueConnectionFactory qconFactory;
private QueueConnection qcon;
private QueueSession qsession;
private QueueReceiver qreceiver;
private QueueSender qsender;
private Queue fromQueue;
private Queue toQueue;
private boolean quit = false;

String output_file_name = "c:\\Samples.txt";
Write_To_Text_File data = new Write_To_Text_File(output_file_name,false);



public void onMessage(Message msg)
{
try {
String msgText;
long timeStamp = 0;
String jmsmessageid = msg.getJMSMessageID();
InitialContext ic = null;
try {
ic = getInitialContext("t3://xxx:7007");
} catch (NamingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (msg instanceof TextMessage)
{
msgText = ((TextMessage)msg).getText();
timeStamp = ((TextMessage)msg).getJMSTimestamp();
Timestamp stamp = new Timestamp(timeStamp);
Date date = new Date(stamp.getTime());
System.out.println("\n\t<Msg_Receiver> "+ jmsmessageid );

JMSDestinationRuntimeMBean reprocessQueueMBean = JMSRuntimeHelper.getJMSDestinationRuntimeMBean(ic, fromQueue);
JMSDestinationRuntimeMBean intermediateQueueMBean = JMSRuntimeHelper.getJMSDestinationRuntimeMBean( ic, toQueue);
try {
System.out.println("Menaka" );
reprocessQueueMBean.moveMessages("JMSMessageID = '" + jmsmessageid + "'", intermediateQueueMBean. );
} catch (ManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
else
{
msgText = msg.toString();
}
System.out.println("\n\t<Msg_Receiver> "+ msgText );

if (msgText.equalsIgnoreCase("quit"))
{
synchronized(this)
{
quit = true;
this.notifyAll(); // Notify main thread to quit
}
}
}
catch (JMSException jmse)
{
jmse.printStackTrace();
}
}
public void init(Context ctx, String moveFromQueueName, String moveToQueueName) throws NamingException, JMSException
{
qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
fromQueue = (Queue) ctx.lookup(moveFromQueueName);
toQueue = (Queue) ctx.lookup(moveToQueueName);
qreceiver = qsession.createReceiver(fromQueue);
qsender = qsession.createSender(toQueue);
qreceiver.setMessageListener(this);
qcon.start();
}

public void close()throws JMSException
{
qreceiver.close();
qsession.close();
qcon.close();
}

public static void main(String[] args) throws Exception
{
/* if (args.length != 1)
{
System.out.println("Usage: java QueueReceive WebLogicURL");
return;
}*/

InitialContext ic = getInitialContext("t3://xxx.qc.bell.ca:7007");
MoveMessages qr = new MoveMessages();
qr.init(ic, QUEUE1, QUEUE2);



System.out.println("JMS Ready To Receive Messages (To quit, send a \"quit\" message from QueueSender.class).");

synchronized(qr)
{
while (! qr.quit)
{
try
{
qr.wait();
}
catch (InterruptedException ie)
{}
}
}
qr.close();
}

}

Pierluigi Vernetto said...

dear friend from India, you are trying to move a JMS message to a queue before it has been consumed (acknowledged)... I am not sure this is supported in JEE... normally you would simply Create a new message and post it to a queue, then consume the old message (it's automatically acknowledged by the MDB, so no need to explicitly acknowledge). COPY+DELETE is equivalent to a MOVE. Just don't try to move the message while you are processing it...

Menaka Balakrishnamoorthy said...

IS there other way to move message from one queue to another? Please let me know

Pierluigi Vernetto said...

the answer was already in my previous comment: not while you are handling the message. Just copy the message to the other queue (by creating a new message) and consume the message. No need to MOVE.