Cómo procesar las cabeceras de mensaje de IBM MQ
Los mensajes de IBM MQ pueden incluir opcionalmente cabeceras adicionales, o cabeceras alternativas, a la cabecera MQRFH2, que contiene propiedades JMS.Los programas de la aplicación WebSphere Application Server pueden utilizar las clases com.ibm.mq.headers para acceder a las cabeceras de los mensajes de IBM MQ y para construir cabeceras en mensajes para IBM MQ.
cabeceras de mensaje de IBM MQ
Los mensajes de IBM MQ incluyen siempre un descriptor de mensaje (MQMD). También pueden incluir cabeceras que contienen información adicional acerca de los mensajes; por ejemplo, los mensajes destinados o procedentes de las aplicaciones JMS suelen incluir una cabecera MQRFH2 que contiene las propiedades de mensaje. IBM MQ define el formato y uso de algunas cabeceras (por ejemplo, MQRFH2) y también permite que usuarios y proveedores de software de terceros definan sus propias cabeceras personalizadas.
Normalmente, no es necesario que los programas de aplicaciones procesen las cabeceras de mensajes de IBM MQ. La mayoría de las aplicaciones IBM MQ no utilizan cabeceras en absoluto, o utilizan únicamente la cabecera MQRFH2, y la integración de servicios y los proveedores de mensajería de IBM MQ procesan automáticamente la cabecera MQRFH2 cuando se comunica con estas aplicaciones. Sin embargo, si se está comunicando con una aplicación IBM MQ que utiliza o crea cabeceras adicionales o diferentes, la aplicación WebSphere Application Server puede utilizar las clases com.ibm.mq.headers para crear las cabeceras en los mensajes que envía y procesarlas en los mensajes que recibe.
En el mensaje de IBM MQ las cabeceras (si hay cabeceras) se encuentran en el principio del mensaje, antes de la carga útil del mensaje. Cada cabecera contiene campos que describen la cabecera siguiente, o la carga útil si no hay más cabeceras; el MQMD contiene los campos que describen la primera cabecera, o la carga útil si no hay cabeceras. El MQMD y la cabecera MQRFH2 no aparecen normalmente en un mensaje JMS. Cuando el proveedor de mensajería convierte un mensaje de IBM MQ en un mensaje JMS, utiliza la información de la cabecera MQMD y MQRFH2 para establecer los campos y las propiedades de las cabeceras JMS. Del mismo modo, cuando el proveedor de mensajería convierte un mensaje JMS en un mensaje IBM MQ, utiliza los campos y las propiedades de la cabecera JMS para crear la cabecera MQMD y MQRFH2.
El proveedor de JMS maneja otras cabeceras en los mensajes IBM MQ convirtiendo el mensaje IBM MQ a un objeto JMS BytesMessage (o desde éste); las cabeceras aparecen al principio del cuerpo del mensaje, seguidas de la carga útil del mensaje IBM MQ (si hay alguna). La propiedad JMS_IBM_Format del mensaje JMS indica el formato de los datos del cuerpo de mensaje (en este caso, la primera cabecera) y las propiedades JMS_IBM_Encoding y JMS_IBM_Character_Set indican la codificación y el CCSID.
Proceso de las cabeceras de mensaje IBM MQ en un JMS BytesMessage
El paquete com.ibm.mq.headers contiene clases e interfaces que puede utilizar para analizar y manipular las cabeceras de IBM MQ en el cuerpo de un JMS BytesMessage. La interfaz MQHeader proporciona métodos de finalidad general para acceder a campos de cabecera y para leer y escribir el contenido del mensaje. Cada tipo de cabecera tiene su propia clase que implementa la interfaz MQHeader y añade los métodos getter y setter para campos individuales. Por ejemplo, la clase MQCIH representa el tipo de cabecera MQCIH (Puente CICS). Las clases de cabecera realizan automáticamente las conversiones de datos necesarias y pueden leer o grabar datos en cualquier juego de caracteres o codificación numérica especificado (CCSID).
- MQHeaderIterator funciona como un java.util.Iterator. Mientras haya más cabeceras en el mensaje, el método next() devuelve true, y el método nextHeader() o next() devuelve el siguiente objeto de cabecera.
- MQHeaderList funciona como una java.util.List. Al igual que MQHeaderIterator, analiza el contenido de la cabecera, aunque también permite buscar cabeceras concretas, añadir nuevas cabeceras, eliminar cabeceras existentes, actualizar campos de cabeceras y, a continuación, grabar el contenido de la cabecera en un mensaje. De forma alternativa, puede crear una lista MQHeaderList vacía y después rellenarla con instancias de cabecera y escribirlo en un mensaje una vez o repetidamente.
Cada clase de cabecera implementa la interfaz MQHeader, que proporciona los métodos int read (java.io.DataInput message, int encoding, int characterSet) e int write (java.io.DataOutput message, int encoding, int characterSet). Las clases java.io.DataInputStream y java.io.DataOutputStream implementan DataInput y DataOutput respectivamente. Puede obtener objetos DataInput y DataOutput de las matrices de bytes que transportan los mensajes de JMS, como en el ejemplo siguiente, en el que se procesa una sola cabecera MQCIH:
import java.io.*;
import
javax.jms.*;
import com.ibm.mq.headers.*;
...
BytesMessage bytesMessage = (BytesMessage) msg; // Mensaje recibido del consumidor JMS
byte[] bytes = new byte [(int) bytesMessage.getBodyLength ()];
bytesMessage.readBytes (bytes);
DataInput in = new DataInputStream (new ByteArrayInputStream (bytes));
MQCIH cih = new MQCIH (in,
bytesMessage.getIntProperty("JMS_IBM_Encoding"),
819);
Como alternativa, puede utilizar la clase MQHeaderIterator para procesar una secuencia de cabeceras, sustituyendo la línea que empieza por MQCIH cih = new MQCIH por:
MQHeaderIterator it = new MQHeaderIterator (in,
bytesMessage.getStringProperty("JMS_IBM_Format"),
bytesMessage.getIntProperty("JMS_IBM_Encoding"),
819);
while (it.hasNext()) {
MQHeader item = (MQHeader) it.next();
...
}
En este ejemplo se crea una cabecera individual (una cabecera de tipo MQCIH) y la añade a un BytesMessage:
import java.io.*;
import
javax.jms.*;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.headers.*;
...
MQCIH header = new MQCIH();
ByteArrayOutputStream out = new ByteArrayOutputStream ();
header.write (new DataOutputStream (out), CMQC.MQENC_NATIVE, 819);
byte[] bytes = out.toByteArray ();
BytesMessage newMsg = origSes.createBytesMessage();
newMsg.writeBytes(bytes);
Este ejemplo utiliza la clase MQHeaderList para añadir dos cabeceras a un BytesMessage:
import java.io.*;
import
javax.jms.*;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.headers.*;
...
byte[] outheaders = null;
byte[] outbody = ...
try {
MQHeaderList it = new MQHeaderList ();
MQHeader header1 = ... // Puede ser cualquier tipo de cabecera
MQHeader header2 = ... // Puede ser cualquier tipo de cabecera
ByteArrayOutputStream out = new ByteArrayOutputStream ();
DataOutput dout = new DataOutputStream(out);
it.add(header1);
it.add(header2);
it.write(dout);
outheaders = out.toByteArray();
} catch (Exception e) {
System.out.println("error generating MQ message headers : " + e);
}
BytesMessage newMsg = origSes.createBytesMessage();
newMsg.writeBytes(outheaders);
newMsg.writeBytes(bytes);
newMsg.setStringProperty("JMS_IBM_Format", "MQCICS");
newMsg.setIntProperty("JMS_IBM_Encoding", CMQC.MQENC_NATIVE);
newMsg.setIntProperty("JMS_IBM_Character_Set", 819);
Utilice siempre los valores correctos para los argumentos encoding y characterSet. Cuando lea cabeceras, especifique la codificación y el CCSID con los que el contenido de bytes se ha escrito originalmente. Cuando escriba cabeceras, especifique la codificación y el CCSID que desee producir. La conversión de datos la realizan automáticamente las clases de cabecera.
Más información sobre las clases com.ibm.mq.headers
- MQCIH – cabecera de puente CICS
- MQIIH – cabecera de información IMS
- MQSAPH – cabecera SAP
También puede definir clases que representen sus propias cabeceras.