Компания IBM
Опубликован: 14.08.2008 | Доступ: свободный | Студентов: 1090 / 150 | Оценка: 4.75 / 3.75 | Длительность: 27:55:00
Лекция 9:

Реализация. Создание корпоративной сервисной шины

9.7 Создание кода ESQL для потоков сообщений

Последний этап конфигурирования потоков сообщений в брокере – это написание ESQL-кода для вычислительных узлов. Чтобы просмотреть все созданные нами для потоков ESQL-модули, откройте свойства любого вычислительного узла и нажмите кнопку Browse (Обзор) ( рис. 9.106).

Обзор ESQL-модулей

Рис. 9.106. Обзор ESQL-модулей

На рис. рис. 9.107 показан список ESQL-модулей, необходимых для proxyAssessorSystem, плюс модуль объявлений, common.esql.

ESQL-модули, которые необходимо написать

Рис. 9.107. ESQL-модули, которые необходимо написать

Нам нужно написать 14 ESQL-модулей. Может показаться, что это очень много кода, но этот код делится лишь на такие четыре категории, как:

  1. Реализация агрегации SOAP/http, для которой 5-я версия брокера не имеет готовой поддержки (6 модулей).
  2. Обработка ошибок. С помощью этого кода мы пытаемся ввести несколько больше диагностической информации в стандартные средства вывода данных об ошибках (6 модулей).
  3. Конструирование SOAP-адреса для отправки запроса на отчет выбранному оценщику.
  4. Повышение удобства чтения кода путем определения префиксов пространств имен в модуле common.esql.

На рис. 9.108 приводятся 15 связующих узлов, которые выполняют большую часть посреднических функций и манипуляций с данными и не требуют написания ESQL-кода.

Связующие модули

Рис. 9.108. Связующие модули

9.7.1 ESQL-функции, поддерживающие агрегацию

В табл. 9.10 перечислены семь ESQL-модулей, необходимых для конкретных потоков сообщений.

Таблица 9.10. ESQL-модули для конкретных потоков сообщений
ESQL-модуль Описание
Flow4_PrepareMQ Преобразует входящее HTTP-сообщение в WebSphere MQ
Flow4_Fan_Out Конструирование сообщений-запросов к индивидуальным оценщикам, создание и сохранение идентификатора ответа и указание для каждого оценщика адреса SOAP/http
Flow4_PrepareMQControl Создание управляющего сообщения WebSphere MQ для отправки в узел Aggregate Reply
Flow4_Save_Assessor_Request Сохранение сообщения-запроса, направляемого оценщику, в базе данных CLAIMSASSESSOR
Flow3a_Prepare_Reply Корреляция данных о готовности оценщика с идентификатором ответа и вставка в папку LocalEnvironment
Flow3a_Generate_Output3a Создание агрегированного ответа о готовности оценщиков для отправки в процесс ExternalClaimAssessors
Flow7_Set_SOAP_Address Задание SOAP/http-адреса оценщика для отправки запроса на отчет об оценке
Flow4_PrepareMQ

В примере 9.9 входное сообщение копируется в выходную папку с удалением HTTP-заголовков и заменой их новым MQMD.

CREATE COMPUTE MODULE Flow4_PrepareMQ
   CREATE FUNCTION Main() RETURNS BOOLEAN
   BEGIN
      SET OutputRoot = InputRoot;
      SET OutputRoot.HTTPInputHeader = null;
      SET OutputRoot.HTTPResponseHeader = null;
      CREATE NEXTSIBLING OF OutputRoot.Properties domain 'MQMD';
      SET OutputRoot.MQMD.StrucId = MQMD_STRUC_ID; -- create MQMD
      SET OutputRoot.MQMD.Version = MQMD_CURRENT_VERSION;
      SET OutputRoot.MQMD.Format = '          ';
      SET OutputRoot.MQMD.MsgType = MQMT_DATAGRAM;
      RETURN TRUE;
   END;
Пример 9.9. Flow4_PrepareMQ
Flow4_Fan_Out

В примере 9.10 представлен ESQL-код для модуля Flow4_Fan_out. Код имеет восемь частей.

Почти весь код (за исключением данных в SQL-инструкциях Insert и ссылках LocalEnvironment) сгенерирован с помощью функции автозаполнения (Autocomplete), так что этот код написать гораздо проще, чем кажется на первый взгляд.

  1. Объявление локальных переменных.
  2. Цикл while, в котором перебираются оценщики в списке оценщиков.
  3. Копирование InputLocalEnvironment в OutputLocalEnvironment.
  4. Задание пункта назначения SOAP/http в папке LocalEnvironment для динамического использования в узле HTTPRequest.
  5. Копирование данных сообщения-запроса к оценщику из входного сообщения в выходное сообщение.
  6. Передача сообщения для каждого оценщика и его папки LocalEnvironment далее по потоку сообщений.
CREATE COMPUTE MODULE Flow4_Fan_Out
 CREATE FUNCTION Main() RETURNS BOOLEAN
 BEGIN
  DECLARE numberOfAssessors INTEGER CARDINALITY (InputRoot.MRM.soap11:Body.
      fl3:requestAssessorAvailability.fl3:assessorList.fl3:assessors[]);
  DECLARE assessorCount INTEGER 0;
  WHILE assessorCount < numberOfAssessors DO
-- Эти инструкции должны быть в цикле, т.к. при передаче OutputRoot
очищается
     CALL CopyMessageHeaders();
     SET OutputLocalEnvironment = InputLocalEnvironment;
     SET OutputRoot.MQMD.MsgType = MQMT_REQUEST;
     SET OutputRoot.MQMD.ReplyToQ = 'AggIn';
     SET OutputRoot.MQMD.Report = MQRO_COPY_MSG_ID_TO_CORREL_ID;
     SET assessorCount = assessorCount + 1;
-- Адрес SOAP/Http для узла RequestHttp в качестве пункта назначения
    SET OutputLocalEnvironment.Destination.HTTP.RequestURL = InputRoot.
MRM.soap11:Body.
fl3:requestAssessorAvailability.fl3:assessorList.fl3:assessors[assessorCount].
fl3:assessorURL;
-- Копирование данных сообщения из списка (f17 – синоним f14 – то же
пространство имен)
-- Выходные поля должны быть в том же порядке, что и элементы
    SET OutputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
claimID
    = InputRoot.MRM.soap11:Body.fl3:requestAssessorAvailability.fl3:
claimID;
   SET OutputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
assessorID=
     InputRoot.MRM.soap11:Body.fl3:requestAssessorAvailability.fl3:
assessorList.
     fl3:assessors[assessorCount].fl3:assessorID;
   SET OutputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
cardet.
    fl7:makeOfCar =
       InputRoot.MRM.soap11:Body.fl3:requestAssessorAvailability.fl3:
makeOfCar;
   SET OutputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
cardet.
     fl7:registration = 'JB 007'; -- Fixup as the registration wasn't
provided
   SET OutputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
location =
  InputRoot.MRM.soap11:Body.fl3:requestAssessorAvailability.fl3:location;
  SET OutputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
reqDate =
  InputRoot.MRM.soap11:Body.fl3:requestAssessorAvailability.fl3:
requiredDate;
SET OutputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
responseTime=
  InputRoot.MRM.soap11:Body.fl3:requestAssessorAvailability.fl3:
responseTime;
  PROPAGATE;
    END WHILE;
-- Все сообщения передаются явно, поэтому пустое сообщение не передается
   RETURN FALSE;
END;
Пример 9.10. Вычислительный модуль Flow4_Fan_Out
Flow4_Control_Message

Вычислительный узел Flow4_Control_Message передает выходное сообщение с терминала Control узла Aggregate Control на узел MQOutput, который помещает его в очередь, предназначенную для узла AggregateReply.

Все, что нам нужно сделать в этом модуле, – это создать сообщение WebSphere MQ и передать ему сообщение, переданное от узла Aggregate Control в виде неструктурированного XML-сообщения.

CREATE COMPUTE MODULE Flow4_PrepareMQControl
  CREATE FUNCTION Main() RETURNS BOOLEAN
    BEGIN
      SET OutputRoot.MQMD.StrucId = MQMD_STRUC_ID;
      SET OutputRoot.MQMD.Version = MQMD_CURRENT_VERSION;
      SET OutputRoot.XML = InputRoot.XML;
    RETURN TRUE;
  END;
END MODULE;
Пример 9.11. Вычислительный модуль Flow4_PrepareMQControl
Flow4_Save_AssessorRequest

После генерации сообщения-запроса мы сохраняем запрос к оценщику в базе данных CLAIMASSESSOR, чтобы у нас было записанное узлом AggregateRequest значение msgid. Обратите внимание, что мы сохраняем URL оценщика в Local Environment.

CREATE COMPUTE MODULE Flow4_Save_AssessorRequest
  CREATE FUNCTION Main() RETURNS BOOLEAN
  BEGIN
    CALL CopyEntireMessage();
    SET OutputLocalEnvironment = InputLocalEnvironment;
-- Сохраняем сообщение в таблице CLAIMASSESSOR
    INSERT INTO Database.EMERGE.CLAIMASSESSOR (claimID, assessorID,
  assessorURL,location, reqdate, makeofcar, registration, replytoq,
replytoqmgr,
  correlid) VALUES (
    InputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
claimID,
    InputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
assessorID,
    InputLocalEnvironment.Destination.HTTP.RequestURL,
    InputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
location,
    InputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
reqDate,
    InputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
cardet.fl7:makeOfCar,
    InputRoot.MRM.soap11:Body.fl7:requestAssessorAvailability.fl7:
cardet.fl7:registration,
    'NoReplytoQ',
    'NoReplytoQmgr',
-- Сохранение корреляционного маркера из id сгенерированного сообщения
InputLocalEnvironment.WrittenDestination.MQ.DestinationData.msgId);
RETURN TRUE;
END;
Пример 9.12. Flow4_Save_AssessorRequest
Flow3a_Prepare_Reply

Узел Flow3a_Prepare_Reply получает ответы с информацией о готовности от оценщиков. Его функция – извлечь для узла Aggregate Reply идентификатор ответа и создать сообщение-запрос WebSphere MQ, которое будет послано узлу MQ Reply для возврата реального сообщения-ответа с правильной корреляционной информацией. В примере 9.13 приводится SQL-код, решающий эти задачи.

CREATE COMPUTE MODULE Flow3a_Prepare_Reply
 CREATE FUNCTION Main() RETURNS BOOLEAN
  BEGIN
   SET OutputRoot = InputRoot;
   SET OutputRoot.HTTPInputHeader = null;
   SET OutputRoot.HTTPResponseHeader = null;
-- Создание MQ-сообщения-запроса – оно будет преобразовано в ответ в
MQReply
   CREATE NEXTSIBLING OF OutputRoot.Properties domain 'MQMD';
   SET OutputRoot.MQMD.StrucId = MQMD_STRUC_ID; -- create MQMD
   SET OutputRoot.MQMD.Version = MQMD_CURRENT_VERSION;
   SET OutputRoot.MQMD.Format = ' ';
   SET OutputRoot.MQMD.Report = MQRO_COPY_MSG_ID_TO_CORREL_ID;
   SET OutputRoot.MQMD.MsgType = MQMT_REPLY;
-- Тот же msgid как в сообщении-запросе, сохраненном в таблице Claim-
Assessor. MQReply скопирует его в correlid
   SET OutputRoot.MQMD.MsgId =
   THE (SELECT ITEM A.correlid FROM Database.EMERGE.CLAIMASSESSOR AS A
   WHERE A.assessorID =
     InputRoot.MRM.soap11:Body.fl8:assessorAvailability.fl8:assessorID
   AND A.claimID =
     InputRoot.MRM.soap11:Body.fl8:assessorAvailability.fl8:claimID);
   SET OutputRoot.MQMD.ReplyToQ = 'AggIn';
   RETURN TRUE;
Пример 9.13. Вычислительный модуль Flow3a_Prepare_Reply

Этот код очищает все HTTP-данные, создает MQMD и конфигурирует его как сообщение-запрос с исходным MsgId.

Flow3a_Generate_Output3a

Модуль Flow3a_Generate_Output3a создает результирующее сообщение Flow3a, включающее список оценщиков, возвращаемый процессу ExternalClaimAssessor.

Объединенное сообщение сохраняется в массиве ComIbmAggregateReplyBody. Flow4. По некоторым причинам нужно переустановить значение MessageSet в свойствах (Properties). Значение то же, которое мы устанавливали для всех входных папок.

CREATE COMPUTE MODULE Flow3a_Generate_Output3a
 CREATE FUNCTION Main() RETURNS BOOLEAN
  BEGIN
-- Сколько ответов получено? Папка Flow4 определена в узле Aggregate
Request?
   DECLARE noofreplies INTEGER
     CARDINALITY(InputRoot.ComIbmAggregateReplyBody.Flow4[]);
   DECLARE replyno INTEGER 1;
   DECLARE assessorID INTEGER;
   SET OutputRoot.Properties =
     InputRoot.ComIbmAggregateReplyBody.Flow4.Properties;
   SET OutputRoot.Properties.MessageSet = 'PIJ0MIK002001';
   IF noofreplies > 0 THEN
     SET OutputRoot.MRM.soap11:Body.fl3a:AvailableAssessorsList.claimID =
InputRoot.ComIbmAggregateReplyBody.Flow4[replyno].MRM.soap11:Body.fl8:
assessorAvailability.fl8:claimID;
   WHILE noofreplies >= replyno DO
     SET assessorID = InputRoot.ComIbmAggregateReplyBody.
Flow4[replyno].
     MRM.soap11:Body.fl8:assessorAvailability.fl8:assessorID;
     SET
OutputRoot.MRM.soap11:Body.fl3a:AvailableAssessorsList.resultAssessor-
Collection[
       replyno].assessorEstimations.assessorID = assessorID;
-- assessorURL отсутствует в ответе, поэтому нужно брать его из базы
данных
     SET
OutputRoot.MRM.soap11:Body.fl3a:AvailableAssessorsList.resultAssessor-
Collection[
replyno].assessorEstimations.assessorURL = THE (SELECT ITEM A.assessor
URL FROM
Database.EMERGE.CLAIMASSESSOR AS A WHERE A.assessorID = assessorID);
     SET
OutputRoot.MRM.soap11:Body.fl3a:AvailableAssessorsList.resultAssessorCo
llection[replyno].assessorEstimations.preCost =
InputRoot.ComIbmAggregateReplyBody.Flow4[replyno].
MRM.soap11:Body.fl8:assessorAvailability.fl8:predCost;
     SET
OutputRoot.MRM.soap11:Body.fl3a:AvailableAssessorsList.resultAssessorCo
llection[replyno].assessorEstimations.preDate =
InputRoot.ComIbmAggregateReplyBody.Flow4[replyno].
MRM.soap11:Body.fl8:assessorAvailability.fl8:predDate;
     SET replyno = replyno + 1;
   END WHILE;
  RETURN TRUE;
 ELSE
-- Не передавать сообщение, если ответов нет
  RETURN FALSE;
 END IF;
END;
Пример 9.14. Вычислительный модуль Flow3a_Generate_Output3a
Надежда Белякова
Надежда Белякова
Россия
Pavel Pelevin
Pavel Pelevin
Украина, Одесса