Разбор сообщения MQ в кодировке base64 - PullRequest
0 голосов
/ 26 ноября 2018

Событие мониторинга начала транзакции потока IIB с узлом MQ Input создает закодированный в base64 байтовый массив сообщения MQ.Теперь я хотел бы написать программу на Java, которая восстанавливает этот байтовый массив, чтобы я мог читать заголовки и тело.

Сообщения MQ base64 выглядят так:

TUQgIAIAAAAAAAAACAAAAP////8AAAAAEQEAALgEAABNUUhSRjIgIAQAAAABAAAAQU1RIENFTUJSQSAgICAgIKVV+Fslx7YCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENFTUJSQSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhbmllbCAgICAgIBYBBRUAAADiboF1+wHSKOpNUf3pAwAAAAAAAAAAAAALICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICALAAAAMC45XGNvbW1vblxqZGtcYmluXGphdmF3LmV4ZTIwMTgxMTI1MTQzNjEyNDcgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA/////1JGSCAAAAACAAAAvAAAAREAAAS4TVFTVFIgICAAAAAAAAAEuAAAACA8bWNkPjxNc2Q+am1zX3RleHQ8L01zZD48L21jZD4gIAAAAEg8am1zPjxEc3Q+cXVldWU6Ly8vTU9OSTwvRHN0PjxUbXM+MTU0MzE1NjU3MjQ1NjwvVG1zPjxEbHY+MjwvRGx2Pjwvam1zPiAAAAAkPHVzcj48VGhlS2V5PlRoZVZhbHVlPC9UaGVLZXk+PC91c3I+PGZvbz5iYXI8L2Zvbz4=

Я сделал следующие тестычтобы разобрать это в Java:

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
import com.ibm.mq.headers.CCSID;
import com.ibm.mq.headers.MQHeaderList;
import com.ibm.mq.headers.MQMD;
import com.ibm.mq.headers.MQRFH2;

public class MqMsgTest {

    @Test
    public void allGood() throws Exception {
        String msgBase64 = IOUtils.toString(getClass().getResourceAsStream("/mq-msg.base64"), "UTF-8");
        byte[] msgBytes = DatatypeConverter.parseBase64Binary(msgBase64);
        DataInputStream msgStream = new DataInputStream(new ByteArrayInputStream(msgBytes));
        MQMD mqmd = new MQMD(msgStream);
        Assert.assertEquals("MQHRF2  ", mqmd.getFormat());
        Assert.assertEquals("daniel      ", mqmd.getUserIdentifier());
        MQRFH2 mqrfh2 = new MQRFH2(msgStream);
        Assert.assertEquals("TheValue", mqrfh2.getStringFieldValue("usr", "TheKey"));
        String body = IOUtils.toString(msgStream, CCSID.getCodepage(mqrfh2.nextCharacterSet()));
        Assert.assertEquals("<foo>bar</foo>", body);
    }

    @Test
    public void doesNotWork() throws Exception {
        String msgBase64 = IOUtils.toString(getClass().getResourceAsStream("/mq-msg.base64"), "UTF-8");
        byte[] msgBytes = DatatypeConverter.parseBase64Binary(msgBase64);
        DataInputStream msgStream = new DataInputStream(new ByteArrayInputStream(msgBytes));
        MQHeaderList headers = new MQHeaderList(msgStream, true);
        Assert.assertEquals(2, headers.size());
    }
}

allGood() тест хорошо разбирает заголовки и тело.Но он потерпит неудачу, если сообщение не будет содержать заголовок RFH2.Тест doesNotWork() должен анализировать заголовки общим способом, но он не работает.

Как можно гибко проанализировать закодированное в base64 сообщение MQ, чтобы у меня был доступ к заголовкам и телу?

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Класс MQHeaderList - не волшебная палочка, хотя я бы хотел, чтобы IBM фактически расширила его использование, включив в него КАЖДЫЙ заголовок MQ.Ваша проблема в том, что вы предполагаете, что класс MQHeaderList может делать больше, чем он может.Класс MQHeaderList может обрабатывать только 11 внутренних заголовков / структур MQ (или классов).Смотрите здесь: https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_9.1.0/com.ibm.mq.dev.doc/q030880_.htm

т.е. MQRFH, MQRFH2, MQCIH, MQDLH, MQIIH, MQRMH, MQSAPH, MQWIH, MQXQH, MQDH & MQEPH

Как видите, MQMD естьсписок.Итак, ваше декодированное сообщение Base64 НЕ будет работать с классом MQHeaderList.

Кроме того, вы должны прочитать мои комментарии о том, что MQRFH2 - это встроенное сообщение здесь: Проблема при установке заголовка MQRFH2 в IBM MQ

Вы должны подключиться и выполнить поток данных, созданный IIB.Вот некоторый базовый код для выполнения этой работы:

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import javax.xml.bind.DatatypeConverter;
import com.ibm.mq.headers.MQMD;
import com.ibm.mq.headers.MQRFH2;

public class Test_IIB_Data
{
   public static void main(String[] args)
   {
      String msgBase64 = "TUQgIAIAAAAAAAAACAAAAP////8AAAAAEQEAALgEAABNUUhSRjIgIAQAAAABAAAAQU1RIENFTUJSQSAgICAgIKVV+Fslx7YCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENFTUJSQSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhbmllbCAgICAgIBYBBRUAAADiboF1+wHSKOpNUf3pAwAAAAAAAAAAAAALICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICALAAAAMC45XGNvbW1vblxqZGtcYmluXGphdmF3LmV4ZTIwMTgxMTI1MTQzNjEyNDcgICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA/////1JGSCAAAAACAAAAvAAAAREAAAS4TVFTVFIgICAAAAAAAAAEuAAAACA8bWNkPjxNc2Q+am1zX3RleHQ8L01zZD48L21jZD4gIAAAAEg8am1zPjxEc3Q+cXVldWU6Ly8vTU9OSTwvRHN0PjxUbXM+MTU0MzE1NjU3MjQ1NjwvVG1zPjxEbHY+MjwvRGx2Pjwvam1zPiAAAAAkPHVzcj48VGhlS2V5PlRoZVZhbHVlPC9UaGVLZXk+PC91c3I+PGZvbz5iYXI8L2Zvbz4=";

      try
      {
         byte[] msgBytes = DatatypeConverter.parseBase64Binary(msgBase64);
         DataInputStream msgStream = new DataInputStream(new ByteArrayInputStream(msgBytes));

         MQMD md = new MQMD(msgStream);

         System.out.println("md.getFormat="+md.getFormat());
         System.out.println("md.getPutApplName="+md.getPutApplName());
         System.out.println("md.getUserIdentifier="+md.getUserIdentifier());

         MQRFH2 rfh2 = new MQRFH2(msgStream);

         System.out.println("rfh2.getFormat="+rfh2.getFormat());
         System.out.println("rfh2.usr.TheKey="+rfh2.getStringFieldValue("usr", "TheKey"));

         int bodyLen = msgBytes.length - rfh2.getStrucLength() - md.size();
         byte[] body = new byte[bodyLen];
         msgStream.read(body);
         System.out.println("body="+new String(body));
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }
}

И когда вы запустите его, результат будет:

md.getFormat=MQHRF2  
md.getPutApplName=0.9\common\jdk\bin\javaw.exe
md.getUserIdentifier=daniel      
rfh2.getFormat=MQSTR   
rfh2.usr.TheKey=TheValue
body=<foo>bar</foo>
0 голосов
/ 26 ноября 2018

Событие мониторинга начала транзакции потока IIB с узлом MQ Input создает закодированный в base64 байтовый массив сообщения MQ.Теперь я хотел бы написать программу на Java, которая восстанавливает этот байтовый массив, чтобы я мог читать заголовки и тело.

Почему?Почему вы объединяете структуры MQMD и MQRFH2, а затем кодируете его с помощью Base64, чтобы извлечь его с помощью Java-программы?

Звучит как очень плохой дизайн.

Я поместил ваше сообщение Base64 в программу, которая выводит шестнадцатеричный дамп:байты.

Класс MQHeaderList чрезвычайно требователен к анализу MQMessage.Сообщение ДОЛЖНО начинаться с одного из известных классов MQ, иначе оно выдаст исключение.Использование класса MQHeaderList для сообщений о проблемах, вероятно, приведет только к большему количеству проблем.

Было бы лучше просто выбросить сообщение в шестнадцатеричном виде, как я, а затем позволить специалисту службы поддержки или разработчику выяснить, в чем проблема.

...