Ecriture de classes pour encapsuler une présentation d'enregistrement dans un JMSBytesMessage

L'objectif de cette tâche est d'explorer, par exemple, comment combiner la conversion de données et une présentation d'enregistrement fixe dans un JMSBytesMessage. Dans la tâche, vous créez des classes Java pour échanger un exemple de structure d'enregistrement dans un JMSBytesMessage. Vous pouvez modifier l'exemple pour écrire des classes afin d'échanger d'autres structures d'enregistrement.

Un JMSBytesMessage est le meilleur choix de type de message JMS pour échanger des enregistrements de type de données mixtes avec des programmes nonJMS . Aucune donnée supplémentaire n'est insérée dans le corps du message par le fournisseur JMS . Il s'agit donc du meilleur choix de type de message à utiliser si un programme client JMS interagit avec un programme IBM® MQ existant. Le défi principal de l'utilisation d'un JMSBytesMessage consiste à faire correspondre le codage et le jeu de caractères attendus par l'autre programme. Une solution consiste à créer une classe qui encapsule l'enregistrement. Une classe qui encapsule la lecture et l'écriture d'un JMSBytesMessage, pour un type d'enregistrement spécifique, facilite l'envoi et la réception d'enregistrements au format fixe dans un programme JMS . En capturant les aspects génériques de l'interface dans une classe abstraite, une grande partie de la solution peut être réutilisée pour différents formats d'enregistrement. Différents formats d'enregistrement peuvent être implémentés dans des classes qui étendent la classe générique abstraite.

Une autre approche consiste à étendre la classe com.ibm.mq.headers.Header . La classe Header comporte des méthodes, telles que addMQLONG, pour générer un format d'enregistrement de manière plus déclarative. L'utilisation de la classe Header présente l'inconvénient d'obtenir et de définir des attributs à l'aide d'une interface d'interprétation plus complexe. Les deux approches aboutissent à une quantité sensiblement identique de code d'application.

Un JMSBytesMessage ne peut encapsuler qu'un seul format, en plus d'un MQRFH2, dans un seul message, sauf si chaque enregistrement utilise le même format, le même jeu de caractères codés et le même codage. Le format, le codage et le jeu de caractères d'un JMSBytesMessage sont les propriétés de tous les messages qui suivent le MQRFH2. L'exemple est écrit en supposant qu'un JMSBytesMessage ne contient qu'un seul enregistrement utilisateur.

Avant de commencer

  1. Votre niveau de compétence: vous devez être familiarisé avec la programmation Java et JMS. Aucune instruction n'est fournie pour la configuration de l'environnement de développement Java . Il est avantageux d'avoir écrit un programme pour échanger un JMSTextMessage, un JMSStreamMessageou un JMSMapMessage. Vous pouvez ensuite voir les différences dans l'échange d'un message à l'aide d'un JMSBytesMessage.
  2. L'exemple requiert IBM WebSphere® MQ 7.0.
  3. L'exemple a été créé en utilisant la perspective Java de l'atelier Eclipse. Il nécessite JRE 6.0 ou une version plus récente. Vous pouvez utiliser la perspective Java dans IBM MQ Explorer pour développer et exécuter les classes Java . Vous pouvez également utiliser votre propre environnement de développement Java .
  4. L'utilisation de IBM MQ Explorer permet de configurer l'environnement de test et le débogage, plus simplement que l'utilisation des utilitaires de ligne de commande.

A propos de cette tâche

Vous êtes guidé lors de la création de deux classes: RECORD et MyRecord. Ensemble, ces deux classes encapsulent un enregistrement à format fixe. Ils possèdent des méthodes permettant d'obtenir et de définir des attributs. La méthode get lit l'enregistrement à partir d'un JMSBytesMessage et la méthode put écrit un enregistrement dans un JMSBytesMessage.

L'objectif de la tâche n'est pas de créer une classe de qualité de production que vous pouvez réutiliser. Vous pouvez choisir d'utiliser les exemples de la tâche pour commencer à utiliser vos propres classes. L'objectif de la tâche est de vous fournir des notes de conseils, principalement sur l'utilisation des jeux de caractères, des formats et du codage, lors de l'utilisation d'un JMSBytesMessage. Chaque étape de création des classes est expliquée et les aspects de l'utilisation de JMSBytesMessage, qui sont parfois négligés, sont décrits.

La classe RECORD est abstraite et définit des zones communes pour un enregistrement utilisateur. Les zones communes sont modélisées sur la présentation d'en-tête IBM MQ standard d'un identificateur, d'une version et d'une zone de longueur. Les zones de codage, de jeu de caractères et de format, qui se trouvent dans de nombreux en-têtes IBM MQ , sont omises. Un autre en-tête ne peut pas suivre un format défini par l'utilisateur. La classe MyRecord , qui étend la classe RECORD , le fait en étendant littéralement l'enregistrement avec des zones utilisateur supplémentaires. Un JMSBytesMessage, créé par les classes, peut être traité par l'exit de conversion des données du gestionnaire de files d'attente.

Les classes utilisées pour exécuter l'exemple incluent une liste complète de RECORD et MyRecord. Il inclut également des listes des classes scaffolding supplémentaires pour tester RECORD et MyRecord. Les classes supplémentaires sont les suivantes:
TryMyRecord
Le programme principal pour tester RECORD et MyRecord.
EndPoint
Classe abstraite qui encapsule la connexion, la destination et la session JMS dans une seule classe. Son interface répond simplement aux besoins de test des classes RECORD et MyRecord . Il ne s'agit pas d'un modèle de conception établi pour l'écriture d'applications JMS .
Remarque: la classe Endpoint inclut cette ligne de code après la création d'une destination:
((MQDestination)destination).setReceiveConversion
                            (WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);

Dans V7.0, à partir de V7.0.1.5, il est nécessaire d'activer la conversion du gestionnaire de files d'attente. Elle est désactivée par défaut. Dans V7.0, la conversion du gestionnaire de files d'attente jusqu'à V7.0.1.4 est activée par défaut et cette ligne de code génère une erreur.

MyProducer et MyConsumer
Classes qui étendent EndPointet créent un MessageConsumer et un MessageProducer, connectés et prêts à accepter des demandes.
Ensemble, toutes les classes constituent une application complète que vous pouvez générer et utiliser pour comprendre comment utiliser la conversion de données dans un JMSBytesMessage.

Procédure

  1. Créez une classe abstraite pour encapsuler les zones standard dans un en-tête IBM MQ , avec un constructeur par défaut. Par la suite, vous étendez la classe pour personnaliser l'en-tête en fonction de vos besoins.
     public abstract class RECORD implements Serializable {
        private static final long serialVersionUID = -1616617232750561712L;
        protected final static int UTF8 = 1208;
        protected final static int MQLONG_LENGTH = 4;
        protected final static int RECORD_STRUCT_ID_LENGTH = 4;
        protected final static int RECORD_VERSION_1 = 1;
        protected final String RECORD_STRUCT_ID = "BLNK";
        protected final String RECORD_TYPE = "BLANK   ";
        private String structID = RECORD_STRUCT_ID;
        private int version = RECORD_VERSION_1;
        private int structLength = RECORD_STRUCT_ID_LENGTH + MQLONG_LENGTH * 2;
        private int headerEncoding = WMQConstants.WMQ_ENCODING_NATIVE;
        private String headerCharset = "UTF-8";
        private String headerFormat = RECORD_TYPE;
    
        public RECORD() {
            super();
        }
    
    
    Remarque :
    1. Les attributs, structID à nextFormat, sont répertoriés dans l'ordre dans lequel ils sont présentés dans un en-tête de message IBM MQ standard.
    2. Les attributs, format, messageEncodinget messageCharset, décrivent l'en-tête lui-même et ne font pas partie de l'en-tête.
    3. Vous devez décider de stocker l'identificateur de jeu de caractères codés ou le jeu de caractères de l'enregistrement. Java utilise des jeux de caractères et les messages IBM MQ utilisent des identificateurs de jeu de caractères codés. L'exemple de code utilise des jeux de caractères.
    4. int est sérialisé dans MQLONG par IBM MQ. MQLONG est de 4 octets.
  2. Créez les méthodes d'accès get et set pour les attributs privés.
    1. Créez ou générez les méthodes d'accès get:
           public String getHeaderFormat() { return headerFormat; }
          public int getHeaderEncoding() { return headerEncoding;    }
          public String getMessageCharset() { return headerCharset; }
          public int getMessageEncoding() { return headerEncoding; }
          public String getStructID() { return structID; }
          public int getStructLength() { return structLength; }
          public int getVersion() { return version; }
      
      
      
    2. Créez ou générez les méthodes d'accès set:
           public void setHeaderCharset(String charset) { 
              this.headerCharset = charset; }
          public void setHeaderEncoding(int encoding) {
              this.headerEncoding = encoding; }
          public void setHeaderFormat(String headerFormat) {
              this.headerFormat = headerFormat; }
          public void setStructID(String structID) {
              this.structID = structID; }
          public void setStructLength(int structLength) {
              this.structLength = structLength; }
          public void setVersion(int version) {
              this.version = version; }
      }
      
  3. Créez un constructeur pour créer une instance RECORD à partir d'un JMSBytesMessage.
         public RECORD(BytesMessage message) throws JMSException, IOException,
                MQDataException {
            super();
            setHeaderCharset(message.getStringProperty(WMQConstants.JMS_IBM_CHARACTER_SET));
            setHeaderEncoding(message.getIntProperty(WMQConstants.JMS_IBM_ENCODING));
            byte[] structID = new byte[RECORD_STRUCT_ID_LENGTH];
            message.readBytes(structID, RECORD_STRUCT_ID_LENGTH);
            setStructID(new String(structID, getMessageCharset()));
            setVersion(message.readInt());
            setStructLength(message.readInt());
        }
    
    
    Remarque :
    1. messageCharset et messageEncodingsont capturées à partir des propriétés de message, car elles remplacent les valeurs définies pour la destination. format n'est pas mis à jour. L'exemple ne vérifie pas les erreurs. Si le constructeur Record(BytesMessage) est appelé, il est supposé que JMSBytesMessage est un message de type RECORD . La ligne setStructID(new String(structID, getMessageCharset())) permet de définir le eye-catcher.
    2. Lignes de code qui complètent les zones de désérialisation de la méthode dans le message, dans l'ordre, en mettant à jour les valeurs par défaut définies dans l'instance RECORD.
  4. Créez une méthode put pour écrire les zones d'en-tête dans un JMSBytesMessage.
         protected BytesMessage put(MyProducer myProducer) throws IOException,
                JMSException, UnsupportedEncodingException {
            setHeaderEncoding(myProducer.getEncoding());
            setHeaderCharset(myProducer.getCharset());
            myProducer.setMQClient(true);
            BytesMessage bytes = myProducer.session.createBytesMessage();
            bytes.setStringProperty(WMQConstants.JMS_IBM_FORMAT, getHeaderFormat());
            bytes.setIntProperty(WMQConstants.JMS_IBM_ENCODING, getHeaderEncoding());
            bytes.setIntProperty(WMQConstants.JMS_IBM_CHARACTER_SET, 
                                 myProducer.getCCSID());
            bytes.writeBytes(String.format("%1$-" + RECORD_STRUCT_ID_LENGTH + "."
                             + RECORD_STRUCT_ID_LENGTH + "s", getStructID())
                             .getBytes(getMessageCharset()), 0, RECORD_STRUCT_ID_LENGTH);
            bytes.writeInt(getVersion());
            bytes.writeInt(getStructLength());
            return bytes;
        }
    
    
    Remarque :
    1. MyProducer encapsule les JMS Connection, Destination, Sessionet MessageProducer dans une seule classe. MyConsumer, utilisé plus loin, encapsule les JMS Connection, Destination, Session et MessageConsumer dans une seule classe.
    2. Pour un JMSBytesMessage, si le codage n'est pas Native, il doit être défini dans le message. Le codage de destination est copié dans l'attribut de codage de message, JMS_IBM_CHARACTER_SET, et sauvegardé en tant qu'attribut de la classe RECORD .
      1. setMessageEncoding(myProducer.getEncoding()); appelle (((MQDestination) destination).getIntProperty(WMQConstants.WMQ_ENCODING)); pour obtenir le codage de destination.
      2. Bytes.setIntProperty(WMQConstants.JMS_IBM_ENCODING, getMessageEncoding()); définit le codage des messages.
    3. Le jeu de caractères utilisé pour transformer le texte en octets est obtenu à partir de la destination et sauvegardé en tant qu'attribut de la classe RECORD . Il n'est pas défini dans le message car il n'est pas utilisé par IBM MQ classes for JMS lors de l'écriture d'un JMSBytesMessage.

      Appels messageCharset = myProducer.getCharset();

          public String getCharset() throws UnsupportedEncodingException,
                  JMSException {
              return CCSID.getCodepage(getCCSID());
      }
      

      Il obtient le jeu de caractères Java à partir d'un identificateur de jeu de caractères codés.

      CCSID.getCodepage(ccsid) se trouve dans le package com.ibm.mq.headers. ccsid est obtenu à partir d'une autre méthode dans MyProducer, qui interroge la destination:

          public int getCCSID() throws JMSException {
              return (((MQDestination) destination)
                      .getIntProperty(WMQConstants.WMQ_CCSID));
          }
      
    4. myProducer.setMQClient(true); remplace le paramètre de destination pour le type de client, en le forçant à un IBM MQ MQI client. Vous pouvez préférer omettre cette ligne de code, car elle masque une erreur de configuration administrative.

      Appels de myProducer.setMQClient(true); :
      ((MQDestination) destination).setTargetClient(WMQConstants.WMQ_TARGET_DEST_MQ); }
      if (!getMQDest()) setMQBody();
      
      Le code a pour effet secondaire de définir le style de corps IBM MQ sur une valeur non spécifiée, s'il doit remplacer un paramètre JMS.
      Remarque :

      Les IBM MQ classes for JMS écrivent le format, le codage et l'identificateur de jeu de caractères du message dans le descripteur de message, MQMD, ou dans l'en-tête JMS , MQRFH2. Selon que le message comporte ou non un corps de style IBM MQ . Ne définissez pas les zones MQMD manuellement.

      Il existe une méthode permettant de définir manuellement les propriétés du descripteur de message. Il utilise les propriétés JMS_IBM_MQMD_* . Vous devez définir la propriété de destination WMQ_MQMD_WRITE_ENABLED pour définir les propriétés JMS_IBM_MQMD_* :
      ((MQDestination)destination).setMQMDWriteEnabled(true);
      
      Vous devez définir la propriété de destination, WMQ_MQMD_READ_ENABLED, pour lire les propriétés.

      Utilisez le JMS_IBM_MQMD_* uniquement si vous prenez le contrôle total de la totalité de la charge de message. Contrairement aux propriétés JMS_IBM_* , les propriétés JMS_IBM_MQMD_* ne contrôlent pas la façon dont IBM MQ classes for JMS construit un message JMS . Il est possible de créer des propriétés de descripteur de message en conflit avec les propriétés du message JMS .

    5. Les lignes de code qui complètent la méthode sérialisent les attributs de la classe en tant que zones du message.
      • Les attributs de chaîne sont complétés par des blancs. Les chaînes sont converties en octets à l'aide du jeu de caractères défini pour l'enregistrement et tronquées à la longueur des zones de message.
  5. Terminez la classe en ajoutant les importations.
     package com.ibm.mq.id;
    import java.io.IOException;
    import java.io.Serializable;
    import java.io.UnsupportedEncodingException;
    import jakarta.jms.BytesMessage;
    import jakarta.jms.JMSException;
    import com.ibm.mq.constants.MQConstants;
    import com.ibm.mq.headers.MQDataException;
    import com.ibm.msg.client.wmq.WMQConstants;
    
    
  6. Créez une classe pour étendre la classe RECORD afin d'inclure des zones supplémentaires. Incluez un constructeur par défaut.
     public class MyRecord extends RECORD {
        private static final long serialVersionUID = -370551723162299429L;
        private final static int FLAGS = 1;
        private final static String STRUCT_ID = "MYRD";
        private final static int DATA_LENGTH = 32;
        private final static String FORMAT = "MYRECORD";
        private int flags = FLAGS;
        private String recordData = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
    
        public MyRecord() {
            super();
            super.setStructID(STRUCT_ID);
            super.setHeaderFormat(FORMAT);
            super.setStructLength(super.getStructLength() + MQLONG_LENGTH
                    + DATA_LENGTH);
        }
    
    
    Remarque :
    1. La sous-classe RECORD , MyRecord, personnalise l'identificateur, le format et la longueur de l'en-tête.
  7. Créez ou générez les méthodes d'accès get et set.
    1. Créez les méthodes d'accès get:
           public int getFlags() { return flags; }
          public String getRecordData() { return recordData; } .
          
      
      
    2. Créez les méthodes d'accès set:
           public void setFlags(int flags) { 
              this.flags = flags; }
          public void setRecordData(String recordData) { 
              this.recordData = recordData; }
      }
      
  8. Créez un constructeur pour créer une instance MyRecord à partir d'un JMSBytesMessage.
         public MyRecord(BytesMessage message) throws JMSException, IOException,
                MQDataException {
            super(message);
            setFlags(message.readInt());
            byte[] recordData = new byte[DATA_LENGTH];
            message.readBytes(recordData, DATA_LENGTH);
            setRecordData(new String(recordData, super.getMessageCharset())); 
        }
    
    
    Remarque :
    1. Les zones qui constituent le modèle de message standard sont lues en premier par la classe RECORD .
    2. Le texte recordData est converti en String à l'aide de la propriété de jeu de caractères du message.
  9. Créez une méthode statique pour obtenir un message d'un consommateur et créer une nouvelle instance MyRecord .
         public static MyRecord get(MyConsumer myConsumer) throws JMSException,
                MQDataException, IOException {
            BytesMessage message = (BytesMessage) myConsumer.receive();
            return new MyRecord(message);
        }
    
    
    Remarque :
    1. Dans l'exemple, par souci de concision, le constructeur MyRecord(BytesMessage) est appelé à partir de la méthode get statique. En règle générale, vous pouvez séparer la réception du message de la création d'une nouvelle instance MyRecord .
  10. Créez une méthode d'insertion pour ajouter les zones client à un JMSBytesMessage contenant un en-tête de message.
         public BytesMessage put(MyProducer myProducer) throws JMSException,
                IOException {
            BytesMessage bytes = super.put(myProducer);
            bytes.writeInt(getFlags());
            bytes.writeBytes(String.format("%1$-" + DATA_LENGTH + "."
                             + DATA_LENGTH + "s",getRecordData())
                             .getBytes(super.getMessageCharset()), 0, DATA_LENGTH);
            myProducer.send(bytes);
            return bytes;
        }
    
    
    Remarque :
    1. Les appels de méthode dans le code sérialisent les attributs de la classe MyRecord en tant que zones dans le message.
      • L'attribut recordData String est rempli avec des blancs, converti en octets à l'aide du jeu de caractères défini pour l'enregistrement et tronqué à la longueur des zones RecordData .
  11. Complétez la classe en ajoutant les instructions include.
     package com.ibm.mq.id;
    import java.io.IOException;
    import jakarta.jms.BytesMessage;
    import jakarta.jms.JMSException;
    import com.ibm.mq.headers.MQDataException;
    
    

Résultats

  • Résultats de l'exécution de la classe TryMyRecord :
    • Envoi d'un message dans le jeu de caractères codés 37 et utilisation d'un exit de conversion de gestionnaire de files d'attente:
      Out flags 1 text ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 Encoding 546 CCSID 37 MQ true
      Out flags 1 text ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 Encoding 546 CCSID 37 MQ true
      In flags 1 text ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 Encoding 273 CCSID UTF-8
      
    • Envoi d'un message dans le jeu de caractères codés 37 et non utilisation d'un exit de conversion de gestionnaire de files d'attente:
      Out flags 1 text ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 Encoding 546 CCSID 37 MQ true
      Out flags 1 text ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 Encoding 546 CCSID 37 MQ true
      In flags 1 text ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 Encoding 546 CCSID IBM037
      
  • Les résultats de la modification de la classe TryMyRecord pour ne pas recevoir le message et de sa réception à l'aide de l'exemple amqsget0.c modifié. L'exemple modifié accepte un enregistrement formaté ; voir la figure 2 dans l'échange d'un enregistrement formaté avec une application non JMS.
    • Envoi d'un message dans le jeu de caractères codés 37 et utilisation d'un exit de conversion de gestionnaire de files d'attente:
      Sample AMQSGET0 start
      ccsid <850>, flags <1>, message <ABCDEFGHIJKLMNOPQRSTUVWXYZ012345>
      no more messages
      Sample AMQSGET0 end
      
    • Envoi d'un message dans le jeu de caractères codés 37 et non utilisation d'un exit de conversion de gestionnaire de files d'attente:
      Sample AMQSGET0 start
      MQGET ended with reason code 2110
      ccsid <37>, flags <1>, message <--+-+ãÃ++ÐÊËÈiÐÎÐ+ÔÒõõμþÞÚ-±=¾¶§>
      no more messages
      Sample AMQSGET0 end
      

Pour tester l'exemple et expérimenter avec différentes pages de codes et un exit de conversion de données. Créez les classes Java , configurez IBM MQet exécutez le programme principal, TryMyRecord ; voir #q032150___Try.

  1. Configurez IBM MQ et JMS pour exécuter l'exemple. Les instructions permettent d'exécuter l'exemple sous Windows.
    1. Création d'un gestionnaire de files d'attente
      crtmqm -sa -u SYSTEM.DEAD.LETTER.QUEUE QM1
      strmqm QM1
      
    2. Création d'une file d'attente
      echo DEFINE QL('Q1') REPLACE | runmqsc QM1
      
    3. Créer un répertoire JNDI
      cd c:\
      md JNDI-Directory
      
    4. Passez dans le répertoire bin JMS

      Le programme d'administration JMS doit être exécuté à partir d'ici. Le chemin d'accès est MQ_INSTALLATION_PATH\java\bin.

    5. Créez les définitions JMS suivantes dans un fichier appelé JMSQM1Q1.txt
      DEF CF(QM1) PROVIDERVERSION(7) QMANAGER(QM1)
      DEF Q(Q1) CCSID(37) ENCODING(RRR) MSGBODY(MQ) QMANAGER(QM1) QUEUE(Q1) TARGCLIENT(MQ) VERSION(7)
      END
      
    6. Exécutez le programme JMSAdmin pour créer les ressources JMS
      JMSAdmin < JMSQM1Q1.txt
      
  2. Vous pouvez créer, modifier et parcourir les définitions que vous avez créées à l'aide de l'explorateur IBM MQ .
  3. Exécutez TryMyRecord.

Classes utilisées pour exécuter l'exemple

Les classes répertoriées dans les blocs de code suivants sont également disponibles dans un fichier compressé. Téléchargez jm25529_.zip ou jm25529_.tar.gz.
TryMyRecord
package com.ibm.mq.id;
public class TryMyRecord {
    public static void main(String[] args) throws Exception {
        MyProducer producer = new MyProducer();
        MyRecord outrec = new MyRecord();
        System.out.println("Out flags " + outrec.getFlags() + " text "
                + outrec.getRecordData() + " Encoding "
                + producer.getEncoding() + " CCSID " + producer.getCCSID()
                + " MQ " + producer.getMQDest());
        outrec.put(producer);
        System.out.println("Out flags " + outrec.getFlags() + " text "
                + outrec.getRecordData() + " Encoding "
                + producer.getEncoding() + " CCSID " + producer.getCCSID()
                + " MQ " + producer.getMQDest());
        MyRecord inrec = MyRecord.get(new MyConsumer());
        System.out.println("In  flags " + inrec.getFlags() + " text "
                + inrec.getRecordData() + " Encoding "
                + inrec.getMessageEncoding() + " CCSID "
                + inrec.getMessageCharset());
    }
}
RECORD [ Messagerie Jakarta 3.0]

package com.ibm.mq.id;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import jakarta.jms.BytesMessage;
import jakarta.jms.JMSException;
import com.ibm.mq.constants.MQConstants;
import com.ibm.mq.headers.MQDataException;
import com.ibm.msg.client.wmq.WMQConstants;

public abstract class RECORD implements Serializable {
    private static final long serialVersionUID = -1616617232750561712L;
    protected final static int UTF8 = 1208;
    protected final static int MQLONG_LENGTH = 4;
    protected final static int RECORD_STRUCT_ID_LENGTH = 4;
    protected final static int RECORD_VERSION_1 = 1;
    protected final String RECORD_STRUCT_ID = "BLNK";
    protected final String RECORD_TYPE = "BLANK   ";
    private String structID = RECORD_STRUCT_ID;
    private int version = RECORD_VERSION_1;
    private int structLength = RECORD_STRUCT_ID_LENGTH + MQLONG_LENGTH * 2;
    private int headerEncoding = WMQConstants.WMQ_ENCODING_NATIVE;
    private String headerCharset = "UTF-8";
    private String headerFormat = RECORD_TYPE;

    public RECORD() {
        super();
    }

    public RECORD(BytesMessage message) throws JMSException, IOException,
            MQDataException {
        super();
        setHeaderCharset(message.getStringProperty(WMQConstants.JMS_IBM_CHARACTER_SET));
        setHeaderEncoding(message.getIntProperty(WMQConstants.JMS_IBM_ENCODING));
        byte[] structID = new byte[RECORD_STRUCT_ID_LENGTH];
        message.readBytes(structID, RECORD_STRUCT_ID_LENGTH);
        setStructID(new String(structID, getMessageCharset()));
        setVersion(message.readInt());
        setStructLength(message.readInt());
    }

    public String getHeaderFormat() { return headerFormat; }
    public int getHeaderEncoding() { return headerEncoding;    }
    public String getMessageCharset() { return headerCharset; }
    public int getMessageEncoding() { return headerEncoding; }
    public String getStructID() { return structID; }
    public int getStructLength() { return structLength; }
    public int getVersion() { return version; }


    protected BytesMessage put(MyProducer myProducer) throws IOException,
            JMSException, UnsupportedEncodingException {
        setHeaderEncoding(myProducer.getEncoding());
        setHeaderCharset(myProducer.getCharset());
        myProducer.setMQClient(true);
        BytesMessage bytes = myProducer.session.createBytesMessage();
        bytes.setStringProperty(WMQConstants.JMS_IBM_FORMAT, getHeaderFormat());
        bytes.setIntProperty(WMQConstants.JMS_IBM_ENCODING, getHeaderEncoding());
        bytes.setIntProperty(WMQConstants.JMS_IBM_CHARACTER_SET, 
                             myProducer.getCCSID());
        bytes.writeBytes(String.format("%1$-" + RECORD_STRUCT_ID_LENGTH + "."
                         + RECORD_STRUCT_ID_LENGTH + "s", getStructID())
                         .getBytes(getMessageCharset()), 0, RECORD_STRUCT_ID_LENGTH);
        bytes.writeInt(getVersion());
        bytes.writeInt(getStructLength());
        return bytes;
    }

    public void setHeaderCharset(String charset) { 
        this.headerCharset = charset; }
    public void setHeaderEncoding(int encoding) {
        this.headerEncoding = encoding; }
    public void setHeaderFormat(String headerFormat) {
        this.headerFormat = headerFormat; }
    public void setStructID(String structID) {
        this.structID = structID; }
    public void setStructLength(int structLength) {
        this.structLength = structLength; }
    public void setVersion(int version) {
        this.version = version; }
}
[ JMS 2.0]

package com.ibm.mq.id;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import com.ibm.mq.constants.MQConstants;
import com.ibm.mq.headers.MQDataException;
import com.ibm.msg.client.wmq.WMQConstants;
public abstract class RECORD implements Serializable {
    private static final long serialVersionUID = -1616617232750561712L;
    protected final static int UTF8 = 1208;
    protected final static int MQLONG_LENGTH = 4;
    protected final static int RECORD_STRUCT_ID_LENGTH = 4;
    protected final static int RECORD_VERSION_1 = 1;
    protected final String RECORD_STRUCT_ID = "BLNK";
    protected final String RECORD_TYPE = "BLANK   ";
    private String structID = RECORD_STRUCT_ID;
    private int version = RECORD_VERSION_1;
    private int structLength = RECORD_STRUCT_ID_LENGTH + MQLONG_LENGTH * 2;
    private int headerEncoding = WMQConstants.WMQ_ENCODING_NATIVE;
    private String headerCharset = "UTF-8";
    private String headerFormat = RECORD_TYPE;

    public RECORD() {
        super();
    }
    public RECORD(BytesMessage message) throws JMSException, IOException,
            MQDataException {
        super();
        setHeaderCharset(message.getStringProperty(WMQConstants.JMS_IBM_CHARACTER_SET));
        setHeaderEncoding(message.getIntProperty(WMQConstants.JMS_IBM_ENCODING));
        byte[] structID = new byte[RECORD_STRUCT_ID_LENGTH];
        message.readBytes(structID, RECORD_STRUCT_ID_LENGTH);
        setStructID(new String(structID, getMessageCharset()));
        setVersion(message.readInt());
        setStructLength(message.readInt());
    }

    public String getHeaderFormat() { return headerFormat; }
    public int getHeaderEncoding() { return headerEncoding;    }
    public String getMessageCharset() { return headerCharset; }
    public int getMessageEncoding() { return headerEncoding; }
    public String getStructID() { return structID; }
    public int getStructLength() { return structLength; }
    public int getVersion() { return version; }

    protected BytesMessage put(MyProducer myProducer) throws IOException,
            JMSException, UnsupportedEncodingException {
        setHeaderEncoding(myProducer.getEncoding());
        setHeaderCharset(myProducer.getCharset());
        myProducer.setMQClient(true);
        BytesMessage bytes = myProducer.session.createBytesMessage();
        bytes.setStringProperty(WMQConstants.JMS_IBM_FORMAT, getHeaderFormat());
        bytes.setIntProperty(WMQConstants.JMS_IBM_ENCODING, getHeaderEncoding());
        bytes.setIntProperty(WMQConstants.JMS_IBM_CHARACTER_SET, 
                             myProducer.getCCSID());
        bytes.writeBytes(String.format("%1$-" + RECORD_STRUCT_ID_LENGTH + "."
                         + RECORD_STRUCT_ID_LENGTH + "s", getStructID())
                         .getBytes(getMessageCharset()), 0, RECORD_STRUCT_ID_LENGTH);
        bytes.writeInt(getVersion());
        bytes.writeInt(getStructLength());
        return bytes;
    }

    public void setHeaderCharset(String charset) { 
        this.headerCharset = charset; }
    public void setHeaderEncoding(int encoding) {
        this.headerEncoding = encoding; }
    public void setHeaderFormat(String headerFormat) {
        this.headerFormat = headerFormat; }
    public void setStructID(String structID) {
        this.structID = structID; }
    public void setStructLength(int structLength) {
        this.structLength = structLength; }
    public void setVersion(int version) {
        this.version = version; }
}
MyRecord [ Messagerie Jakarta 3.0]

package com.ibm.mq.id;
import java.io.IOException;
import jakarta.jms.BytesMessage;
import jakarta.jms.JMSException;
import com.ibm.mq.headers.MQDataException;

public class MyRecord extends RECORD {
    private static final long serialVersionUID = -370551723162299429L;
    private final static int FLAGS = 1;
    private final static String STRUCT_ID = "MYRD";
    private final static int DATA_LENGTH = 32;
    private final static String FORMAT = "MYRECORD";
    private int flags = FLAGS;
    private String recordData = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";

    public MyRecord() {
        super();
        super.setStructID(STRUCT_ID);
        super.setHeaderFormat(FORMAT);
        super.setStructLength(super.getStructLength() + MQLONG_LENGTH
                + DATA_LENGTH);
    }

    public MyRecord(BytesMessage message) throws JMSException, IOException,
            MQDataException {
        super(message);
        setFlags(message.readInt());
        byte[] recordData = new byte[DATA_LENGTH];
        message.readBytes(recordData, DATA_LENGTH);
        setRecordData(new String(recordData, super.getMessageCharset())); 
    }

    public static MyRecord get(MyConsumer myConsumer) throws JMSException,
            MQDataException, IOException {
        BytesMessage message = (BytesMessage) myConsumer.receive();
        return new MyRecord(message);
    }

    public int getFlags() { return flags; }
    public String getRecordData() { return recordData; } .
    

    public BytesMessage put(MyProducer myProducer) throws JMSException,
            IOException {
        BytesMessage bytes = super.put(myProducer);
        bytes.writeInt(getFlags());
        bytes.writeBytes(String.format("%1$-" + DATA_LENGTH + "."
                         + DATA_LENGTH + "s",getRecordData())
                         .getBytes(super.getMessageCharset()), 0, DATA_LENGTH);
        myProducer.send(bytes);
        return bytes;
    }

    public void setFlags(int flags) { 
        this.flags = flags; }
    public void setRecordData(String recordData) { 
        this.recordData = recordData; }
}
[ JMS 2.0]

package com.ibm.mq.id;
import java.io.IOException;
import javax.jms.BytesMessage;
import javax.jms.JMSException;
import com.ibm.mq.headers.MQDataException;
public class MyRecord extends RECORD {
    private static final long serialVersionUID = -370551723162299429L;
    private final static int FLAGS = 1;
    private final static String STRUCT_ID = "MYRD";
    private final static int DATA_LENGTH = 32;
    private final static String FORMAT = "MYRECORD";
    private int flags = FLAGS;
    private String recordData = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";

    public MyRecord() {
        super();
        super.setStructID(STRUCT_ID);
        super.setHeaderFormat(FORMAT);
        super.setStructLength(super.getStructLength() + MQLONG_LENGTH
                + DATA_LENGTH);
    }
    public MyRecord(BytesMessage message) throws JMSException, IOException,
            MQDataException {
        super(message);
        setFlags(message.readInt());
        byte[] recordData = new byte[DATA_LENGTH];
        message.readBytes(recordData, DATA_LENGTH);
        setRecordData(new String(recordData, super.getMessageCharset())); 
    }
    public static MyRecord get(MyConsumer myConsumer) throws JMSException,
            MQDataException, IOException {
        BytesMessage message = (BytesMessage) myConsumer.receive();
        return new MyRecord(message);
    }
    public int getFlags() { return flags; }
    public String getRecordData() { return recordData; } .
    
    public BytesMessage put(MyProducer myProducer) throws JMSException,
            IOException {
        BytesMessage bytes = super.put(myProducer);
        bytes.writeInt(getFlags());
        bytes.writeBytes(String.format("%1$-" + DATA_LENGTH + "."
                         + DATA_LENGTH + "s",getRecordData())
                         .getBytes(super.getMessageCharset()), 0, DATA_LENGTH);
        myProducer.send(bytes);
        return bytes;
    }
    public void setFlags(int flags) { 
        this.flags = flags; }
    public void setRecordData(String recordData) { 
        this.recordData = recordData; }
}
EndPoint [ Messagerie Jakarta 3.0]

package com.ibm.mq.id;
import java.io.UnsupportedEncodingException;
import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.Destination;
import jakarta.jms.JMSException;
import jakarta.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.ibm.mq.headers.CCSID;
import com.ibm.mq.jms.MQDestination;
import com.ibm.msg.client.wmq.WMQConstants;
public abstract class EndPoint {
    public Context ctx;
    public ConnectionFactory cf;
    public Connection connection;
    public Destination destination;
    public Session session;
    protected EndPoint() throws NamingException, JMSException {
        System.setProperty("java.naming.provider.url", "file:/C:/JNDI-Directory");
        System.setProperty("java.naming.factory.initial", 
                           "com.sun.jndi.fscontext.RefFSContextFactory");
        ctx = new InitialContext();
        cf = (ConnectionFactory) ctx.lookup("QM1");
        connection = cf.createConnection();
        destination = (Destination) ctx.lookup("Q1");
        ((MQDestination)destination).setReceiveConversion
                                    (WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); }
    protected EndPoint(String cFactory, String dest) throws NamingException,
            JMSException {
        System.setProperty("java.naming.provider.url", "file:/C:/JNDI-Directory");
        System.setProperty("java.naming.factory.initial", 
                           "com.sun.jndi.fscontext.RefFSContextFactory");
        ctx = new InitialContext();
        cf = (ConnectionFactory) ctx.lookup(cFactory);
        connection = cf.createConnection();
        destination = (Destination) ctx.lookup(dest);
        ((MQDestination)destination).setReceiveConversion
                                    (WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  }
    public int getCCSID() throws JMSException {
        return (((MQDestination) destination)
                .getIntProperty(WMQConstants.WMQ_CCSID));  }
    public String getCharset() throws UnsupportedEncodingException,
            JMSException {
        return CCSID.getCodepage(getCCSID());  }
    public int getEncoding() throws JMSException {
        return (((MQDestination) destination)
                .getIntProperty(WMQConstants.WMQ_ENCODING));  }
    public boolean getMQDest() throws JMSException {
        if ((((MQDestination) destination).getMessageBodyStyle() 
               == WMQConstants.WMQ_MESSAGE_BODY_MQ)
            || ((((MQDestination) destination).getMessageBodyStyle() 
                   == WMQConstants.WMQ_MESSAGE_BODY_UNSPECIFIED) 
               && (((MQDestination) destination).getTargetClient() 
                   == WMQConstants.WMQ_TARGET_DEST_MQ)))
            return true;
        else
            return false; }
    public void setCCSID(int ccsid) throws JMSException {
        ((MQDestination) destination).setIntProperty(WMQConstants.WMQ_CCSID,
                ccsid); }
    public void setEncoding(int encoding) throws JMSException {
        ((MQDestination) destination).setIntProperty(WMQConstants.WMQ_ENCODING,
                encoding); }
    public void setMQBody() throws JMSException {
        ((MQDestination) destination)
                     .setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_UNSPECIFIED);  }
    public void setMQBody(boolean mqbody) throws JMSException {
        if (mqbody)  ((MQDestination) destination)
                     .setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_MQ);
        else         ((MQDestination) destination)
                     .setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_JMS);  }
    public void setMQClient(boolean mqclient) throws JMSException {
       if (mqclient){
            ((MQDestination) destination).setTargetClient(WMQConstants.WMQ_TARGET_DEST_MQ);
            if (!getMQDest()) setMQBody();            
        }                  
       else 
            ((MQDestination) destination).setTargetClient(WMQConstants.WMQ_TARGET_DEST_JMS); }
    }
[ JMS 2.0]

package com.ibm.mq.id;
import java.io.UnsupportedEncodingException;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.ibm.mq.headers.CCSID;
import com.ibm.mq.jms.MQDestination;
import com.ibm.msg.client.wmq.WMQConstants;
public abstract class EndPoint {
    public Context ctx;
    public ConnectionFactory cf;
    public Connection connection;
    public Destination destination;
    public Session session;
    protected EndPoint() throws NamingException, JMSException {
        System.setProperty("java.naming.provider.url", "file:/C:/JNDI-Directory");
        System.setProperty("java.naming.factory.initial", 
                           "com.sun.jndi.fscontext.RefFSContextFactory");
        ctx = new InitialContext();
        cf = (ConnectionFactory) ctx.lookup("QM1");
        connection = cf.createConnection();
        destination = (Destination) ctx.lookup("Q1");
        ((MQDestination)destination).setReceiveConversion
                                    (WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); }
    protected EndPoint(String cFactory, String dest) throws NamingException,
            JMSException {
        System.setProperty("java.naming.provider.url", "file:/C:/JNDI-Directory");
        System.setProperty("java.naming.factory.initial", 
                           "com.sun.jndi.fscontext.RefFSContextFactory");
        ctx = new InitialContext();
        cf = (ConnectionFactory) ctx.lookup(cFactory);
        connection = cf.createConnection();
        destination = (Destination) ctx.lookup(dest);
        ((MQDestination)destination).setReceiveConversion
                                    (WMQConstants.WMQ_RECEIVE_CONVERSION_QMGR);
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  }
    public int getCCSID() throws JMSException {
        return (((MQDestination) destination)
                .getIntProperty(WMQConstants.WMQ_CCSID));  }
    public String getCharset() throws UnsupportedEncodingException,
            JMSException {
        return CCSID.getCodepage(getCCSID());  }
    public int getEncoding() throws JMSException {
        return (((MQDestination) destination)
                .getIntProperty(WMQConstants.WMQ_ENCODING));  }
    public boolean getMQDest() throws JMSException {
        if ((((MQDestination) destination).getMessageBodyStyle() 
               == WMQConstants.WMQ_MESSAGE_BODY_MQ)
            || ((((MQDestination) destination).getMessageBodyStyle() 
                   == WMQConstants.WMQ_MESSAGE_BODY_UNSPECIFIED) 
               && (((MQDestination) destination).getTargetClient() 
                   == WMQConstants.WMQ_TARGET_DEST_MQ)))
            return true;
        else
            return false; }
    public void setCCSID(int ccsid) throws JMSException {
        ((MQDestination) destination).setIntProperty(WMQConstants.WMQ_CCSID,
                ccsid); }
    public void setEncoding(int encoding) throws JMSException {
        ((MQDestination) destination).setIntProperty(WMQConstants.WMQ_ENCODING,
                encoding); }
    public void setMQBody() throws JMSException {
        ((MQDestination) destination)
                     .setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_UNSPECIFIED);  }
    public void setMQBody(boolean mqbody) throws JMSException {
        if (mqbody)  ((MQDestination) destination)
                     .setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_MQ);
        else         ((MQDestination) destination)
                     .setMessageBodyStyle(WMQConstants.WMQ_MESSAGE_BODY_JMS);  }
    public void setMQClient(boolean mqclient) throws JMSException {
       if (mqclient){
            ((MQDestination) destination).setTargetClient(WMQConstants.WMQ_TARGET_DEST_MQ);
            if (!getMQDest()) setMQBody();            
        }                  
       else 
            ((MQDestination) destination).setTargetClient(WMQConstants.WMQ_TARGET_DEST_JMS); }
    }
MyProducer [ Messagerie Jakarta 3.0]

package com.ibm.mq.id;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.MessageProducer;
import javax.naming.NamingException;
public class MyProducer extends EndPoint {
    public MessageProducer producer;
    public MyProducer() throws NamingException, JMSException {
        super();
        producer = session.createProducer(destination); }
    public MyProducer(String cFactory, String dest) throws NamingException,
            JMSException {
        super(cFactory, dest);
        producer = session.createProducer(destination); }
    public void send(Message message) throws JMSException {
        producer.send(message); }
}
[ JMS 2.0]

package com.ibm.mq.id;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.naming.NamingException;
public class MyProducer extends EndPoint {
    public MessageProducer producer;
    public MyProducer() throws NamingException, JMSException {
        super();
        producer = session.createProducer(destination); }
    public MyProducer(String cFactory, String dest) throws NamingException,
            JMSException {
        super(cFactory, dest);
        producer = session.createProducer(destination); }
    public void send(Message message) throws JMSException {
        producer.send(message); }
}
MyConsumer [ Messagerie Jakarta 3.0]

package com.ibm.mq.id;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.MessageConsumer;
import javax.naming.NamingException;
public class MyConsumer extends EndPoint {
    public MessageConsumer consumer;
    public MyConsumer() throws NamingException, JMSException {
        super();
        consumer = session.createConsumer(destination);
        connection.start();  }
    public MyConsumer(String cFactory, String dest) throws NamingException,
            JMSException {
        super(cFactory, dest);
        consumer = session.createConsumer(destination);
        connection.start();  }
    public Message receive() throws JMSException {
        return consumer.receive();  }
}
[ JMS 2.0]

package com.ibm.mq.id;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.naming.NamingException;
public class MyConsumer extends EndPoint {
    public MessageConsumer consumer;
    public MyConsumer() throws NamingException, JMSException {
        super();
        consumer = session.createConsumer(destination);
        connection.start();  }
    public MyConsumer(String cFactory, String dest) throws NamingException,
            JMSException {
        super(cFactory, dest);
        consumer = session.createConsumer(destination);
        connection.start();  }
    public Message receive() throws JMSException {
        return consumer.receive();  }
}