Manipulación de mensajes en el domino BLOB

Este tema proporciona información específica para tratar los mensajes que pertenecen al dominio BLOB y que se analizan mediante el analizador BLOB.

El contenido de un mensaje BLOB no puede manipularse porque no tiene ninguna estructura predefinida. No obstante, puede hacer referencia a su contenido utilizando su posición conocida dentro de la corriente de bits y procesar el mensaje con un conocimiento mínimo de su contenido.

El analizador de cuerpos de mensajes BLOB no crea una estructura de árbol de la misma forma que otros analizadores del cuerpo de mensaje. No tiene un BLOB de elemento raíz que es un elemento dependiente, llamado también BLOB, que contiene datos.

Puede hacer referencia al contenido del mensaje utilizando subseries si se sabe la ubicación de un trozo de información concreto dentro de los datos BLOB. Por ejemplo, la siguiente expresión identifica el décimo byte del cuerpo del mensaje:

InputBody.BLOB.BLOB[10]

La siguiente expresión hace referencia a 10 bytes de los datos del mensaje empezando en el desplazamiento 10:

SUBSTRING(InputBody.BLOB.BLOB from 10 for 10)

Ejemplo de manipulación de mensajes BLOB

En este ejemplo se muestra cómo manipular un mensaje BLOB de longitud variable. En el ejemplo se da por supuesto que se ha configurado un flujo de mensajes que recibe un mensaje BLOB de longitud variable, analiza algunos de los campos invocando el analizador MRM y direcciona el mensaje de salida a la cola de salida correcta en función de la información analizada.

El mensaje de entrada está en formato BLOB y se supone que contiene nulos incorporados ('x00'), por lo que no se puede definir como terminado por nulo.

En este ejemplo se muestra el ESQL necesario para:

  • Calcular la longitud del mensaje BLOB
  • Pasarlo a formato hexadecimal
  • Añadirlo al principio del mensaje BLOB

Al hacerlo puede definir el modelo de mensaje con un campo de longitud de entero seguido del mensaje BLOB.

Este mensaje también muestra cómo convertir el mensaje BLOB a CWF, procesarlo y eliminar el campo de longitud añadido.

En este ejemplo, el registro de entrada tiene el formato siguiente:

  • Número de versión: serie de caracteres, 11 caracteres
  • Nombre de tienda: serie de caracteres, 10 caracteres

    Este campo se utiliza un entero para direccionar el mensaje a colas distintas en función de los criterios definidos por el cliente.

  • Datos de tienda: datos binarios de longitud variable

Definir un nuevo mensaje

Defina un nuevo mensaje BLOB_Example que incluya los siguientes elementos y tipos:

  • B_LEN, xsd:integer
  • VERSION_NUM, xsd:string, Length 11
  • STORE_NUM, xsd:string, Length 10
  • BIN_BLOB, xsd:binary, Length Value B_LEN

Crear un flujo de mensajes

En esta sección se describen las características del flujo de mensajes. Si desea implementar este flujo de mensajes, debe completar la definición de flujo de mensajes (por ejemplo, creando los tres subflujos de modo que sustituyan los nodos de salida utilizados aquí para manejar casos falsos, desconocidos o anómalos) y proporcionar todo el soporte necesario para su difusión y ejecución (por ejemplo, crear las colas de entrada y las colas de salida del gestor de colas para el intermediario al que se difunde el flujo).

  1. Crear el subflujo LESS_THAN. Esta tarea se describe en Crear el subflujo LESS_THAN.
  2. Crear un flujo de mensajes. Añada nodos a la vista de editor del flujo de mensajes: un nodo MQInput, un nodo Compute, un nodo ResetContentDescriptor, un nodo Filter, tres nodos MQOutput y el subflujo LESS_THAN.
  3. Cambie el nombre del nodo MQInput por INQUEUE y establezca su propiedad Nombre de cola en INQUEUE.
  4. Conecte el terminal de salida al nodo Compute.
  5. Cambie el valor por omisión del nombre del nodo Compute por Add_length. Configure el nodo Compute para que calcule la longitud de BIN_BLOB y añádala al principio del mensaje BLOB_Example en el campo B_LEN:
    1. Pulse el botón derecho del ratón en el nodo y pulse Abrir ESQL.
    2. Escriba el siguiente código ESQL en el módulo para este nodo:
      -- Declare local variables
      DECLARE I      INTEGER 1;
      DECLARE J      INTEGER CARDINALITY(InputRoot.*[]);
      DECLARE MSGLEN CHARACTER; 
      DECLARE NUMBER INTEGER; 
      DECLARE RESULT INTEGER; 
      DECLARE REM    INTEGER; 
      
      -- Copy message headers
      WHILE I < J DO
        	SET OutputRoot.*[I] = InputRoot.*[I];
        SET I  = I + 1;
      END WHILE;
      -- 
      -- Set MSGLEN to non NULL to avoid errors when concatenating the first time -- 
      SET MSGLEN = 'X'; 
      -- 
      -- Get the length of the BLOB and substract the length of VERSION_NUM and STORE_NUM (11+10) 
      SET NUMBER = LENGTH("InputRoot"."BLOB"."BLOB")-21; 
      -- 
      -- Convert NUMBER to hexadecimal. The remainder of dividing by 16 is calculated recursively. -- 
      WHILE NUMBER > 15 DO      
         SET RESULT = NUMBER/16;      
         SET REM    = NUMBER - RESULT*16;      
         SET MSGLEN = 
          CASE
            WHEN REM < 10  THEN CAST(REM AS CHARACTER) || MSGLEN               
            WHEN REM = 10  THEN 'A' || MSGLEN              
            WHEN REM = 11  THEN 'B' || MSGLEN              
            WHEN REM = 12  THEN 'C' || MSGLEN              
            WHEN REM = 13  THEN 'D' || MSGLEN               
            WHEN REM = 14  THEN 'E' || MSGLEN              
            ELSE                'F' || MSGLEN          
          END;      
         SET NUMBER = RESULT; 
      END WHILE; 
      SET REM = NUMBER;     
      SET MSGLEN =           
         CASE                
           WHEN REM < 10  THEN CAST(REM AS CHARACTER) || MSGLEN               
           WHEN REM = 10  THEN 'A' || MSGLEN              
           WHEN REM = 11  THEN 'B' || MSGLEN              
           WHEN REM = 12  THEN 'C' || MSGLEN              
           WHEN REM = 13  THEN 'D' || MSGLEN               
           WHEN REM = 14  THEN 'E' || MSGLEN              
           ELSE                'F' || MSGLEN          
         END; 
      -- 
      -- Add leading '0's up to a length of 9 to be able to cast as BLOB. 
      -- Remember it started with MSGLEN set to X (length 1) 
      WHILE LENGTH(MSGLEN) < 9 DO       
         SET MSGLEN = '0' || MSGLEN; END WHILE; 
      -- 
      -- Change to appropriate endian (PLATFORM DEPENDENT) 
      -- If no endian swapping needed then remember to get rid of the last character as below -- 
      SET MSGLEN = SUBSTRING(MSGLEN FROM 1 FOR 8); 
      -- 
      SET MSGLEN = SUBSTRING(MSGLEN FROM 7 FOR 2) || SUBSTRING(MSGLEN FROM 5 FOR 2) ||
                   SUBSTRING(MSGLEN FROM 3 FOR 2) || SUBSTRING(MSGLEN FROM 1 FOR 2);
      SET "OutputRoot"."BLOB"."BLOB" = CAST(MSGLEN AS BLOB) || "InputRoot"."BLOB"."BLOB"; 
      
  6. Conecte el terminal de salida del nodo Compute al nodo ResetContentDescriptor.
  7. Cambie el nombre de nodo ResetContentDescriptor por ResetContent_2_MRM. Configure el nodo como se indica a continuación:
    1. Establezca Dominio del mensaje en MRM.
    2. Seleccione el recuadro Restablecer dominio de mensaje.
    3. Establezca Conjunto de mensajes para el identificador del conjunto de mensajes en el que se ha definido el mensaje BLOB_Example.
    4. Seleccione el recuadro de selección Restablecer conjunto de mensajes.
    5. Establezca Tipo de mensaje en BLOB_Example.
    6. Seleccione el recuadro de selección Restablecer tipo de mensaje.
    7. Establezca en el nombre del formato físico CWF que se ha definido (por ejemplo, el valor por omisión CWF1).
    8. Seleccione el recuadro de selección Restablecer formato del mensaje.
  8. Conecte el terminal de salida del nodo ResetContentDescriptor en el nodo Filter.
  9. Cambie el nombre del nodo Filter por Route_2_QUEUE. Configure el nodo como se indica a continuación:
    1. Pulse el botón derecho del ratón en el nodo y pulse Abrir ESQL.
    2. Escriba la siguiente sentencia ESQL en el módulo ESQL para este nodo:
      CAST("Body"."e_STORE_NUM" AS INTEGER) < 151    

      Esta sentencia se basa en la suposición arbitraria de que un mensaje de entrada de un número de tienda es inferior a 151 y que se direcciona a una cola específica. Puede escribir otro código para la prueba, si lo desea.

  10. Conecte los terminales de salida de filtro como se indica a continuación:
    1. El terminal verdadero a un nodo del subflujo (vea a continuación) llamado LESS_THAN.
    2. El terminal falso a un nodo MQOutput denominado GREATER_THAN con la propiedad Nombre de cola establecida en GREATER_THAN.
    3. El terminal desconocido a un nodo MQOutput denominado INVALID con la propiedad Nombre de cola establecida en INVALID.
    4. El terminan de anomalías a un nodo MQOutput denominado ERROR con la propiedad Nombre de cola establecida en ERROR.

Crear el subflujo LESS_THAN

Este subflujo maneja un error que tiene un formato esperado (la prueba realizada en el nodo Filter ha devuelto true). El mensaje satisfactorio se escribe en la cola de salida en su formato original; el mensaje se vuelve a convertir de MRM a BLOB y se eliminan los cuatro bytes que se han añadido (campo B_LEN).

Para este subflujo:

  1. Cree un nuevo flujo de mensajes denominado LESS_THAN.
  2. En la vista del editor, añada un nodo Input, un nodo ResetContentDescriptor, un nodo Compute y un nodo MQOutput.
  3. Cambie el nombre del nodo Input por InputTerminal1 y conecte su terminal de salida al nodo ResetContentDescriptor.
  4. Cambie el nombre ResetContentDescriptor por ResetContent_2_BLOB y configure el nodo:
    1. Establezca Dominio del mensaje en BLOB
    2. Seleccione el recuadro Restablecer dominio de mensaje.
  5. Conecte terminal de salida del nodo ResetContentDescriptor al nodo Compute.
  6. Cambie el nombre del nodo Compute por Remove_length y configure el nodo:
    1. Pulse el botón derecho del ratón en el nodo y pulse Abrir ESQL.
    2. Escriba el siguiente código ESQL en el módulo para este nodo:
      -- Copy message headers
      DECLARE I INTEGER 1;
      DECLARE J INTEGER CARDINALITY(InputRoot.*[]);
      
      WHILE I < J DO
        	SET OutputRoot.*[I] = InputRoot.*[I];
        SET I  = I + 1;
      END WHILE;
      -- 
      -- Remove the 4 bytes length field added previously -- 
      SET "OutputRoot"."BLOB"."BLOB" = SUBSTRING("InputRoot"."BLOB"."BLOB" FROM 5);

      Este nodo Compute elimina los cuatro bytes que se añadieron al principio del mensaje BLOB para dar soporte a esta manipulación.

      Observe la utilización de la variable, J, que se ha inicializado con el valor de cardinalidad de las cabeceras existentes en el mensaje. Es más eficaz que calcular la cardinalidad de cada iteración del bucle, que sucede si codifica la siguiente sentencia WHILE:

      WHILE I < CARDINALITY(InputRoot.*[]) DO
  7. Conecte el terminal de salida del nodo Compute al nodo MQOutput.
  8. Cambie el nombre del nodo MQOutput por Output_success y configure el nodo, estableciendo el Nombre del gestor de colas y el Nombre de cola. Puede encontrarlo útil para promocionar estas propiedades del nodo MQOutput para poder especificarlas a nivel del flujo de mensajes.

Conceptos relacionados
Flujos de mensajes
Dominio y analizador BLOB
Propiedades promocionadas
ESQL
Diseño de mensajes

Tareas relacionadas
Diseño de un flujo de mensajes
Definición del contenido del flujo de mensajes
Configuración de un nodo
Gestión de archivos ESQL
Definición de propiedades promocionadas

Referencia relacionada
Nodo Compute
Nodo Database
Nodo Filter
Nodo MQInput
Nodo MQOutput
Nodo ResetContentDescriptor
ESQL
Función CARDINALITY
Función CASE
Función CAST
Sentencia DECLARE
Sentencia SET
Función SUBSTRING
Sentencia WHILE