Author |
Message
|
shindeashish |
Posted: Thu Oct 06, 2005 10:08 pm Post subject: JMS-MQ Response cannot be read |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
Problem: We have C based MQ client which accepts user inputs and sends a request message on a req. queue. It then waits on a response queue for the response. The server side component is a MDB which recieves this message (onMessage), processes it, and sends the response on the response queue. Upto this point it works as expected. However the client keeps on waiting for the response even though the message is on the response queue (the CURRDEPTH parameter when seen from runmqsc increases after MDB sends back a response).
The client waits a certain amount of time on response queue and expires giving a reason code of 2033 (No message found).
Since we are using C based client for binary transfer of data we are setting the property for format as "AP_BMH_0".
Please let me know what might be the issue/ configuration I might have missed out
The MDB side code is as follows
public void onMessage( Message requestMessage )
{
System.out.println( "Enter onMessage() of MessageBean" );
try
{
getData(requestMessage);
}
catch ( Exception exception )
{
exception.printStackTrace();
}
}
private void getData(Message msg)
{
try
{
if (msg instanceof Message) {
/***************************************************/
/* Need to get the destination that the reply will */
/* go to. This destination then needs to be used */
/* to create a QueueSender to send the actual */
/* reply. Just for curiosity, print out the name */
/* of the destination. */
/***************************************************/
Destination des = msg.getJMSReplyTo();
responseQueueName = ((MQQueue)des).getQueueName();
responseQueue = ((MQQueue)des);
System.out.println("responseQueueName "+responseQueueName);
byte[] b = new byte[500];
bmsg = (BytesMessage)msg;
int m = bmsg.readBytes(b);
String test = new String (b);
System.out.println("The message is : \n" + test);
System.out.println( "Method = "+ bmsg);
sendMessage("00C1");
}
}
catch( MessageEOFException mje ) {
/*******************************************/
/* Catch and display exception information */
/*******************************************/
System.out.println("MessageEOFException: " + mje.getErrorCode());
System.out.println("Linked exception: " + mje.getLinkedException());
}
catch( JMSException je ) {
/*******************************************/
/* Catch and display exception information */
/*******************************************/
System.out.println("JMSException: " + je);
Exception le = je.getLinkedException();
if (le != null) System.out.println("Linked exception: " + le);
} catch( Exception e ) {
/*******************************************/
/* Catch and display exception information */
/*******************************************/
System.out.println("Exception: " + e);
}
}
public void sendMessage( ArrayList messageList,
ArrayList correlationIDList )
throws Exception
{
final String METHOD_NAME = " sendMessage( ArrayList, ArrayList ) ";
String message = null;
String correlationID = null;
QueueSession session = null;
QueueSender queueSender = null;
MQQueue requestQueue = null;
BytesMessage bytesMessage = null;
int messageListSize = 0;
int correlationIDListSize = 0;
System.out.println( "Inside sendMessage" );
try
{
// If connection object is null, invoke init()
if ( connection == null )
{
init();
System.out.println("Connection object created");
}
System.out.println( "Parameters retrived from ejb-jar.xml: " );
session = connection.createQueueSession( SESSION_TRANSACTED,
Session.AUTO_ACKNOWLEDGE );
System.out.println("Session created: " );
//responseQueue = session.createQueue(responseQueueName);
if(responseQueue != null)
{
System.out.println("Response queue object created" );
}
else
{
System.out.println("Response queue object is null" );
}
responseQueue.setTargetClient( JMSC.MQJMS_CLIENT_NONJMS_MQ );
responseQueue.setCCSID( 819 );
responseQueue.setPersistence( DeliveryMode.NON_PERSISTENT );
responseQueue.setPriority( bmsg.getJMSPriority() );
//Queue responseQueue = session.createQueue(responseQueueName);
queueSender = session.createSender( responseQueue );
System.out.println("Queue Sender created: " );
queueSender.setDeliveryMode( DeliveryMode.NON_PERSISTENT );
if ( messageList != null )
{
messageListSize = messageList.size();
}
if ( correlationIDList != null )
{
correlationIDListSize = correlationIDList.size();
}
System.out.println("messageListSize: " + messageListSize
+ " correlationIDListSize: " + correlationIDListSize );
for ( int i = 0; i < messageListSize; i++ )
{
message = ( String ) messageList.get( i );
// Set the response message
bytesMessage = session.createBytesMessage();
bytesMessage.setJMSTimestamp( System.currentTimeMillis() );
bytesMessage.setJMSExpiration( System.currentTimeMillis() + (10*1000) );
bytesMessage.setJMSDeliveryMode( DeliveryMode.NON_PERSISTENT );
//bytesMessage.setJMSReplyTo( responseQueue );
//bytesMessage.setStringProperty( "JMS_IBM_Format", "AP_BMH_0" );
bytesMessage.setStringProperty( "JMS_IBM_Format", "AP_BMH_0" );
//bytesMessage.setStringProperty( "JMS_IBM_MsgType", "1" );
//bytesMessage.setStringProperty( "JMS_IBM_Character_Set", "819");
//((MQMessage)bytesMessage).characterSet = 819 ;
if ( i < correlationIDListSize )
{
correlationID = ( String ) correlationIDList.get( i );
System.out.println("correlationID: " + correlationID );
if ( correlationID != null
&& correlationID.trim().length() != 0 )
{
bytesMessage.setJMSCorrelationID( correlationID );
}
}
bytesMessage.writeBytes( message.getBytes() );
System.out.println( "Message posted: " + message );
// Post the response on the queue
queueSender.send( bytesMessage );
System.out.println( "Message sent successfully: " );
message = null;
correlationID = null;
}
session.commit();
//close all object
queueSender.close();
session.close();
connection.close();
System.out.println("Message posted successfully" );
}
catch ( JMSException jmsException )
{
try
{
session.rollback();
System.out.println( "Exception occured and session rolled back." );
}
catch ( JMSException jmsNewException )
{
System.out.println(
"Session roll back failed with exception: "
+ jmsNewException );
System.out.println("jmsNewException: " + jmsNewException.getErrorCode());
System.out.println("Linked exception: " + jmsNewException.getLinkedException());
}
System.out.println(
"JMSException in sendMessage(): " + jmsException.getMessage() );
System.out.println("jmsException: " + jmsException.getErrorCode());
System.out.println("Linked exception: " + jmsException.getLinkedException());
//throw new MOSException( MQ_UNABLE_SEND_ERROR );
}
catch ( Exception exception )
{
try
{
session.rollback();
System.out.println(
"Exception occured and session rolled back." );
}
catch ( JMSException jmsException )
{
System.out.println(
"Session roll back failed with exception: "
+ jmsException );
}
System.out.println( exception );
}
finally
{
try
{
if ( queueSender != null )
{
queueSender.close();
}
if ( session != null )
{
session.close();
}
}
catch ( JMSException jmsException )
{
System.out.println("Exception while closing session/queueSender : "
+ jmsException );
}
// Assign unused objects to null
bytesMessage = null;
message = null;
session = null;
queueSender = null;
requestQueue = null;
responseQueue = null;
}
}
/**
* Initializes the class attributes of the session bean No logging is done
* in this class as this will be invoked when the bean is deployed during
* server start up. <code>MOSGlobals</code> may not have been loaded at
* that time. This causes exception to be thrown on the console, when we try
* to use <code>MOSLog</code> methods.
*
* @throws MOSException
* In case any Error occurs while reading from ejb-xml.jar
*/
private void init() throws Exception
{
Context ctx = null;
try
{
ctx = new InitialContext();
// already retrieved in onMessage function
//responseQueueName = ( String ) ctx
// .lookup( DCONCDB_MQ_RESPONSE_QUEUE_NAME );
queueManager = ( String ) ctx.lookup( DCONCDB_MQ_QUEUE_MANAGER );
queueHost = ( String ) ctx.lookup( DCONCDB_MQ_HOST );
serverChannel = ( String ) ctx.lookup( DCONCDB_SERVER_CHANNEL );
queuePort = ( ( Integer ) ctx.lookup( DCONCDB_MQ_PORT ) ).intValue();
// For debugging purpose
buffer = new StringBuffer( " requestQueueName = " );
buffer.append( requestQueueName );
buffer.append( " responseQueueName = " )
.append( responseQueueName );
buffer.append( " queueManager = " ).append( queueManager );
buffer.append( " queueHost = " ).append( queueHost );
buffer.append( " serverChannel = " ).append( serverChannel );
buffer.append( " priority = " ).append( priority );
buffer.append( " queuePort = " ).append( queuePort );
System.out.println(buffer.toString());
factory = new com.ibm.mq.jms.MQQueueConnectionFactory();
// Setting the parameters for connection factory.
factory.setTransportType( JMSC.MQJMS_TP_CLIENT_MQ_TCPIP );
factory.setQueueManager( queueManager );
factory.setHostName( queueHost );
factory.setChannel( serverChannel );
factory.setPort( queuePort );
//Create Queue connection
connection = factory.createQueueConnection();
//Start the connection before further processing
connection.start();
}
catch ( NamingException namingException )
{
System.out.println(namingException.toString());
}
catch ( JMSException mje )
{
System.out.println("JMSException: " + mje.getErrorCode());
System.out.println("Linked exception: " + mje.getLinkedException());
}
catch ( Exception e )
{
System.out.println("Exception: " + e.toString());
System.out.println("Message: " + e.getMessage());
}
finally
{
// Initialise unused objects to null
ctx = null;
}
} |
|
Back to top |
|
 |
wschutz |
Posted: Fri Oct 07, 2005 1:38 am Post subject: |
|
|
 Jedi Knight
Joined: 02 Jun 2005 Posts: 3316 Location: IBM (retired)
|
So, this generally means one of two things:
(1) The MDB hasn't committed the message. The client will not be able to read the message until it has been committed.
(2) The client is doing a selective get on msgID or correlID, and the response message doesn't match the given criteria. (see MQMO_NONE) _________________ -wayne |
|
Back to top |
|
 |
shindeashish |
Posted: Fri Oct 07, 2005 2:10 am Post subject: |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
Hi,
I have closed all the objects as can be seen in the sendMessage code.
Is there anything else I need to do???
Also the client side is using the default option while trying to get the message ( to browse the messages).
I have also used the MQMessenger tool available on this site to successfully read the message posted by MDB.
When I try to get message using "amqsget" the output is as follows:
------
Sample AMQSGET0 start
/usr/lib/dld.sl: Can't open shared library: /var/mqm/exits//AP_BMH_0_r
/usr/lib/dld.sl: No such file or directory
MQGET ended with reason code 2110
message <00C1>
no more messages
Sample AMQSGET0 end
------
As above I am able to get the data but also recv an error with erason code 2110.
2110 is format error.
I am setting format as:
bytesMessage.setStringProperty( "JMS_IBM_Format", "AP_BMH_0" );
Even after removing the format setting from client C program and server side MDB
I get same 2110 error as:
==========
Sample AMQSGET0 start
MQGET ended with reason code 2110
message <00C1>
no more messages
Sample AMQSGET0 end
=============
Any idea why |
|
Back to top |
|
 |
wschutz |
Posted: Fri Oct 07, 2005 2:21 am Post subject: |
|
|
 Jedi Knight
Joined: 02 Jun 2005 Posts: 3316 Location: IBM (retired)
|
By doing this:
Code: |
bytesMessage.setStringProperty( "JMS_IBM_Format", "AP_BMH_0" ); |
You are telling MQ that you have your own conversion exit, which is why you are getting this:
Quote: |
/usr/lib/dld.sl: Can't open shared library: /var/mqm/exits//AP_BMH_0_r
|
Set the format the MQFMT_STRING and see if that helps. _________________ -wayne |
|
Back to top |
|
 |
shindeashish |
Posted: Fri Oct 07, 2005 3:44 am Post subject: |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
Hi,
I am using MQ-JMS for sending messages.
How do I set the format "MQFMT_STRING"
Do you mean
bytesMessage.setStringProperty( "JMS_IBM_Format", "MQFMT_STRING" ); ?? |
|
Back to top |
|
 |
wschutz |
Posted: Fri Oct 07, 2005 4:06 am Post subject: |
|
|
 Jedi Knight
Joined: 02 Jun 2005 Posts: 3316 Location: IBM (retired)
|
Yes, that is what I meant, however, try:
Code: |
bytesMessage.setStringProperty( "JMS_IBM_Format", MQFMT_STRING );
|
(I think that should work, if not, then the "MQSTR" literal.) _________________ -wayne |
|
Back to top |
|
 |
shindeashish |
Posted: Fri Oct 07, 2005 4:43 am Post subject: |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
The response now works ok for MQSTR and I am able to get the response using amqsget without any problem.
However the client still cannot read it. The C client opens the connection successfully on response queue, however the receiver component keeps on waiting. The receiver options (GMO) on client are set to default. |
|
Back to top |
|
 |
wschutz |
Posted: Fri Oct 07, 2005 4:56 am Post subject: |
|
|
 Jedi Knight
Joined: 02 Jun 2005 Posts: 3316 Location: IBM (retired)
|
Try using MQMO_NONE _________________ -wayne |
|
Back to top |
|
 |
shindeashish |
Posted: Fri Oct 07, 2005 5:31 am Post subject: |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
This does not seems to work as the message is posted on the respnse queue but using amqsget to retrieve the message gives following error:
========
Sample AMQSGET0 start
/usr/lib/dld.sl: Can't open shared library: /var/mqm/exits//0_r
/usr/lib/dld.sl: No such file or directory
MQGET ended with reason code 2110
message <00C1>
no more messages
Sample AMQSGET0 end
===============
The java code to send bytesmessage is:
=========
message = ( String ) messageList.get( i );
//message.format = MQC.MQFMT_NONE;
// Set the response message
bytesMessage = session.createBytesMessage();
bytesMessage.setJMSTimestamp( System.currentTimeMillis() );
bytesMessage.setJMSDeliveryMode( DeliveryMode.NON_PERSISTENT );
bytesMessage.setJMSReplyTo( responseQueue );
bytesMessage.setIntProperty("JMS_IBM_Format", com.ibm.mq.MQC.MQMO_NONE);
bytesMessage.writeBytes( message.getBytes() );
System.out.println( "Message posted: " + message );
// Post the response on the queue
queueSender.send( bytesMessage );
System.out.println( "Message sent successfully: " );
message = null;
correlationID = null;
========= |
|
Back to top |
|
 |
wschutz |
Posted: Fri Oct 07, 2005 5:51 am Post subject: |
|
|
 Jedi Knight
Joined: 02 Jun 2005 Posts: 3316 Location: IBM (retired)
|
No, use the MQMO_NONE in the "C" client program, not the java server. _________________ -wayne |
|
Back to top |
|
 |
shindeashish |
Posted: Fri Oct 07, 2005 6:25 am Post subject: |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
Openeing the receiver with MQMO_NONE gives an error with error code.
Quote: |
Failed to open the response queue! reason code = 2037 |
Any idea why? |
|
Back to top |
|
 |
wschutz |
Posted: Fri Oct 07, 2005 7:40 am Post subject: |
|
|
 Jedi Knight
Joined: 02 Jun 2005 Posts: 3316 Location: IBM (retired)
|
Yes ...
Quote: |
[wschutz@wschutz ~]$ mqrc 2037
2037 0x000007f5 MQRC_NOT_OPEN_FOR_INPUT
|
_________________ -wayne |
|
Back to top |
|
 |
fjb_saper |
Posted: Fri Oct 07, 2005 8:47 am Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Common problem between JMS and non JMS clients:
Did you make sure to either have the client extract the RFH header or suppress it in the sender app ?
By the way the easiest way to send a text message in JMS (format MQSTR) is to create one from the session:
Code: |
TextMessage mytxtmsg = session.createTextMessage(): |
try something like
Code: |
(Queue) myq=reqmsg.getJMSReplyTo();
String qname = myq.getName();
//Analyse the name to add in the URI format "targetClient=1"
//needs either a ? or an & in front of it.
// This will suppress the RFH header
// Then you might have the session recreate the destination...
// alternatively
import com.ibm.mq.jms.*;
MQQueue mymq = (MQQueue)myq;
mymq.setTargetClientProperty(JMSC.***_Client_MQ);
|
Sorry but it is all from memory...
You should then receive a response without the RFH header....
Enjoy  |
|
Back to top |
|
 |
shindeashish |
Posted: Sun Oct 09, 2005 8:51 pm Post subject: |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
I am using the reply to queue to send reply as below
Destination des = msg.getJMSReplyTo();
responseQueueName = ((MQQueue)des).getQueueName();
responseQueue = ((MQQueue)des);
System.out.println("responseQueueName "+responseQueueName);
We are also using :
responseQueue.setTargetClient( JMSC.MQJMS_CLIENT_NONJMS_MQ );
Since client is written in C listening on response queue.
Can you please give an example of
//Analyse the name to add in the URI format "targetClient=1"
//needs either a ? or an & in front of it.
// This will suppress the RFH header
// Then you might have the session recreate the destination...
Also why is the client not able to open the queue when the options for mqget is set to MQMO_NONE??
|
|
Back to top |
|
 |
shindeashish |
Posted: Mon Oct 10, 2005 8:38 pm Post subject: |
|
|
Novice
Joined: 06 Oct 2005 Posts: 16
|
Finally got the solution. The messageId was being looked for in the response object.
The message Id in request was set to "DCON.....", however since it is a byte message it is received as 44434F... (44=D, 43=C, 4F=O...).
Hence we had to get the ascii equivalent from request at JMS end and set
it again as messageId in the response being sent to client.
Just a small question we are using the below logic to get actual ASCII values from message Id at server end
Code: |
while (count<24)
{
bytes[count] = (byte)Integer.parseInt( msgId.substring(start,end),16);
count++;
start +=2;
end +=2;
} |
Is there any more optimized approach?? |
|
Back to top |
|
 |
|