Разработка заглушек бизнес-процесса на языке BPEL на основе Oracle SOA Suite и Weblogic

  • Tutorial

В этой статье я расскажу как реализовать заглушки веб-сервисов бизнес-процесса на BPEL используя Oracle SOA Suite и сервер Weblogic


Задача


Есть проект по нагрузочному тестированию одной системы. В схеме взаимодействия между серверами есть внешние системы, которые не участвуют в объекте тестирования — надо их заменить эмуляторами или заглушками. Протокол SOAP. Композиты на BPEL. Стенда нет. Ужасно интересно!




Решение


Ну, думаю, все просто. Запрошу WSDL, XSD-схемы, примеры запросов и ответов. Возьму любимый Eclipse, Tomcat, быстро сгенерирую классы, вставлю пример ответа, потом деплой и проверка.


Eclipse сильно возмущался: в WSDL нет необходимой информации для нормальной генерации классов. Я стал его править, прописывать endpoint, но все равно не работало. Затем выяснил что это BPEL-процесс, и его надо делать по другому.


Сам BPEL — язык на основе XML для формального описания бизнес-процессов и протоколов их взаимодействия между собой. И Eclipse все это умеет, есть плагины, есть сервер приложений Apache ODE. Похоже, что проект BPEL-процесса в Eclipse надо собирать вручную, тех файлов что есть в композите, он не создает. Импорт выгруженного композита из функционального стенда тоже не работает. Это было удивительно, если бы он импортировал композит из Weblogic в Eclipse.


Посетила мысль сделать точно также, как на продуктиве: Oracle Database + Oracle Weblogic + Oracle SOA Suite, разработка в Oracle JDeveloper.


Далее я расскажу про:


  • Разворачивание своего стенда
  • Подключение MDS
  • Импорт существующего композита
  • Выпиливание вызова внешних систем
  • Вставку примера успешного ответа
  • Примеры использования операторов
  • Добавление в композит нового веб-сервиса
  • Вызов асинхронного сервиса
  • Деплой композита
  • Проверку модифицированного композита
  • Анализ проблем при проведении тестирования
  • Мониторинг и замечания при работе

BPEL — язык на основе XML для формального описания бизнес-процессов и протоколов их взаимодействия между собой.


Надо сказать, что BPEL довольно большая и удобная штука, позволяющая вставлять разные операторы, дебаг и куски кода, например Java.


Бизнес процесс выглядит примерно так:




Давайте развернем свой стенд. И так, что нам потребуется и какие версии:


  • JDK 1.7.79
  • Oracle Database 11g release 2
  • Oracle SOA Suite 11.1.1.7.0
  • Oracle RCU 11.1.1.7.0
  • Weblogic 10.3.6
  • JDeveloper 11.1.1.7.0
  • Готовые композиты бизнес-процессов
  • Архив MDS
  • Примеры запросов и ответов

Разворачивание своего стенда


Инструкции по установке и настройке софта


Установка Weblogic
  1. Запуск установщика.


    java -jar wls1036_generic.jar

  2. Выбор пути для домашней папки.



  3. Пропустим регистрацию для обновлений.



  4. Выберем типичную установку.



  5. Укажем папку с JDK.



  6. Далее укажем папку куда поставить сам Weblogic.



  7. Установка и поздравления.



Установка Oracle

В установке нет ничего сложного, остановлюсь только на некоторых моментах.
Пропустим минимальные требования и поставим Oracle Database 11g Release 2 x32 для Windows, выберем Desktop Class. Нам для разработки хватит.
В интернете, в том числе и на хабре есть много статей по установке. Отмечу только установку под локальным админом и задание переменных окружения. Хотя ошибка с отсутствием ORACLE_UNQNAME не помешала и все завелось.




Установка SOA Suite
  1. Для запуска установщика надо указать путь к JRE или JDK.


    ofm_soa_generic_11.1.1.7.0/Disk1/setup.exe -jreLoc c:\Oracle\Middleware\jdk160_24

  2. Пропустим обновление софта.



  3. Проверка операционной системы и физической памяти, в случае ошибки можно проигнорировать.



  4. Выбор Middleware Home и название директории для нашего SOA.



  5. Далее установщик нашел Weblogic в домашней папке.



  6. Установка и поздравления. Проверим подключение.


    sqlplus sys@ORCL as sysdba

  7. Или запустим SQL Developer и настроим подключение.


    c:\app\admin\product\11.2.0\dbhome_1\sqldeveloper\sqldeveloper.exe


Создание репозитория для Oracle SOA c помощью RCU
  1. Запустим RCU.


    ofm_rcu_win_11.1.1.7.0_64_disk1_1of1/rcuHome/bin/rcu.bat

  2. Выбираем Create Repository.



  3. Указываем параметры БД, в нашем случае это localhost, 1521, sys и пароль. Далее идет проверка.


  4. Следом надо указать префикс для имен схем данных (по умолчанию DEV) и выбрать компоненты репозитория, нам нужны Metadata Services и SOA Infrastructure, User Messaging Service выбирается автоматически.



  5. Укажем пароль для пользователей, владельцев схем с данными для репозитория.



  6. Потом можно выбрать табличные пространства для схем данных репозитория.



  7. Запуск создания tablespaces.



  8. Готово.




Создание WebLogic домена и запуск серверов
  1. Запускаем установку.
    Чтобы его создать запустим файл config.cmd в папке


    C:\Oracle\Middleware\Oracle_SOA1\common\bin

    У меня JDK 1.7, поэтому он ругнулся


    Мы ее обойдем — меняем javaw на java в файле


    c:\Oracle\Middleware\wlserver_10.3\common\bin\config.cmd

    и получаем описание Unrecognized VM option 'UseSpinning'
    Удаляем опцию -XX:+UseSpinning (которой больше нет с 1.6) в файле


    c:\Oracle\Middleware\wlserver_10.3\common\bin\commEnv.cmd

    и снова запускаем.


  2. Выбираем создание нового домена.



  3. Выбираем Oracle SOA Suite, Enterprise Manager. WSM Policy Manager и JRF выберутся автоматически.



  4. Указываем имя и путь к домену и приложениям.



  5. Пароль для пользователя weblogic.



  6. JDK и тип инсталляции. Оставим Development Mode.



  7. Пропишем пароли к вашим схемам, хост и sid:.



  8. Проверка.



  9. Настраивать не будем, оставим пустыми.



  10. Жмем создать.


  11. Готово. Запустим Admin Server.



  12. Дождемся сообщения "Server state changed to RUNNING"


  13. Запустим soa_server1.


    c:\Oracle\Middleware\user_projects\domains\base_domain\bin\startManagedWebLogic.cmd soa_server1

  14. Когда будет просить ввод логина и пароля, вводим от администратора домена. Чтобы больше не просил создадим файл.


    c:\Oracle\Middleware\user_projects\domains\base_domain\servers\soa_server1\security\boot.properties



    username=weblogic
    password=welcome1


Проверка консолей и настройка JDeveloper
  1. Проверка WebLogic Administration Console: http://localhost:7001/console (если вы использовали порт по умолчанию при установке).



  2. Проверка Enterprise Manager: http://localhost:7001/em
    В Enterprise Manager должна быть доступна вкладка “SOA” в дереве слева.





  1. Необходимо установить JDeveloper что бы создавать композиты. Берем версию 11.1.1.9.0.
    Ставим, используя существующий Middleware Home.


  2. Для работы с композитами, необходимо установить расширение для нашего JDeveloper.








Подготовка к разработке


Композиты, которые мы будем деплоить, используют схемы, которые хранятся в MDS в БД. Его можно запросить или выкачать из стенда для функционального тестирования.


Подключение к MDS и импорт архива
  1. Импорт MDS архива.





  2. Создание подключения к БД под пользователем схемы MDS. View->Resource palette->New Connection->Database



  3. Создание подключения к MDS. View->Resource palette->New Connection->SOA-MDS




Импорт существующего композита
  1. Создание пустого проекта. (File->New).







  2. Импорт существующего композита. Композиты также можно выкачать с функционального стенда. Выбираем созданный проект, File->Import.








Разработка


Расковыряем композит и задеплоим


Выпиливание вызовов внешних систем. Редактирование BPEL-файла

На картинке выше можно видеть в правой части имеется внешняя система и бизнес-процесс ее вызывает методом invoke.
Давайте же уберем это ненужное. Я буду делать это в блокноте. Но можно и в интерфейсе.




  1. Краткий экскурс.
    Файл состоит из блоков, вариаций больше, я перечислю некоторые:
    process — корневой тег для процесса
    partnerLinks — партнерские соглашения между сервисами
    variables — декларация переменные
    faultHandlers — обработчики ошибок
    sequence main — бизнес-процесс
    receive — получение запроса от клиента
    assign — блок присвоения переменных
    сopy — копирование данных из одного объекта в другой
    invoke — вызов веб-сервиса
    if, elseif, else — объявление условий
    condition — описание условия
    forEach — объявление цикла
    startCounterValue — начало цикла
    finalCounterValue — конец цикла
    scope — объединение


  2. Убрать часть соглашения, касающееся внешней системы.


    <partnerLink name="GetCustomerPartyAccountBS"
             partnerLinkType="ns2:GetCustomerPartyAccount"
             partnerRole="GetCustomerPartyAccountProvider"
             myRole="GetCustomerPartyAccountRequester"/>

  3. Для простоты обработчик ошибок я тоже удалю. Весь тег faultHandlers.


    <faultHandlers/>

  4. Удаляем assign запроса к внешней системе, оставим только копирование данных из запроса для идентификации запроса.


    <copy>
        <from>$inputVariable.payload/SYSTEM/MSG_ID/@Value</from>
        <to>$outputVariable.payload/SYSTEM/MAIN_ID/@Value</to>
    </copy>

  5. Удаляем все вызовы внешних систем invoke, кроме последнего в файле, где должен быть ответ нашему клиенту.


    <invoke name="callbackClient"
            partnerLink="getcustomerpartyaccountsystreqa_client"
            portType="ns1:GetCustomerPartyAccountsystReqACallback"
            operation="processResponse" inputVariable="outputVariable"/>

  6. Посмотрим переменную, в которую нужно записать ответ. В нашем случае это outputVariable


  7. Берем пример ответа, который наш дружелюбно предоставили разработчики или мы сами вытащили из SOA на функциональном стенде. И прописываем значения в нужные теги. Например
    Метод payload, операция ответа AnsSearchGetCustomerPartyAcc и xpath поставим свои.
    BEGIN[$itr] — элемент в цикле, означает $itr-итый элемент BEGIN внутри родительского.



    <copy bpelx:insertMissingToData="yes"
          ignoreMissingFromData="yes">
        <from>"0"</from>
        <to>$outputVariable.payload/DATA/AnsSearchGetCustomerPartyAcc/BEGIN_/accClntList/BEGIN_[$itr]/accClnt/BEGIN_/status/BEGIN_/code/@Value</to>
    </copy>

Выпиливание вызовов внешних систем. Правим composit.xml
  1. Удалим импорт wsdl от внешнего сервиса.
    <import importType="wsdl" location="oramds:/apps/EDM/EnterpriseBusinessServiceLibrary/GetCustomerPartyAccountBS/V1/GetCustomerPartyAccountBSV1.wsdl" 
    namespace="http://www.ru/EnterpriseBusinessServiceLibrary/GetCustomerPartyAccountBS/V1"/>
  2. Уберем еще ссылку на внешний сервис.
    <reference name="GetCustomerPartyAccountBS">
  3. И еще соединение wire к удаляемому сервису GetCustomerPartyAccountBS
    <wire>
    ```GetCustomerPartyAccountsystReqA/GetCustomerPartyAccountBS</source.uri>
        <target.uri>GetCustomerPartyAccountBS</target.uri>
    </wire>

Выпиливание вызовов внешних систем. Правим .componentType и soaconfigplan.xml
  1. Убираем ссылку на внешний сервис в этих файлах.
    <reference name="GetCustomerPartyAccountBS">
  2. Пробуем собрать. Right Click на проекте -> Make.
    Если все ОК, то деплоим, нет — разбираемся.

Деплой заглушки на локальный Weblogic
  1. Пробуем задеплоить.



  2. Выбор операции.



  3. Можно создать несколько сервисов с одинаковым именем, но разной версии.
    Вызывать можно все, но по стандартному адресу будет работать только default-ревизии. В Enterprise Manager можно применить default на задеплоенном композите.



  4. Выбор сервера.



  5. Добавим локальный сервер. Жмем плюс.





  6. Выбор SOA сервера.



  7. Summary.



  8. Лог деплоя.




Примеры использования операторов

Несколько примеров интересных возможностей.


  1. Регулярные выражения.


    <if name="If_ChooseSync">
        <documentation>sender_bic</documentation>
        <condition>xp20:matches($sender_bic,'(?!044525716|046577413|044030811|043602955|045004751|042007738|040349585|040813827)\d{9}') = true()</condition>
    ...

  2. Присвоение строки


    <extId Value="0000000001CA3B1"/>

    <copy ignoreMissingFromData="yes" bpelx:insertMissingToData="yes">
        <from>"0000000001CA3B1"</from>
        <to>$CITResponse/DATA/ReqSyncFinancialTransactionBatch/BEGIN_/documentList/BEGIN_/document/BEGIN_/extId/@Value</to>
    </copy>                                

  3. Цикл и итератор.


    <forEach parallel="no" counterName="ForEach1CounterSync" name="ForEachSync">
    <startCounterValue>1</startCounterValue>
    <finalCounterValue>count($onMessage_ExecuteFinancialTransactionBatch_InputVariable.part1/DATA/ReqExecFinancialTransactionBatch/BEGIN_/documentList/BEGIN_)</finalCounterValue>
    ...

  4. Использование итератора в цикле.


    <copy ignoreMissingFromData="yes" bpelx:insertMissingToData="yes">
        <from>"BQ.00000.1415807097.277059967"</from>
        <to>$CITResponse/DATA/ReqSyncFinancialTransactionBatch/BEGIN_/documentList/BEGIN_[$ForEach1CounterInc]/document/BEGIN_/extId/@Value</to>
    </copy>

  5. Много встроенный функций, например генерация guid.


    <copy>
        <from>oraext:generate-guid()</from>
        <to>$CITResponse/SYSTEM/MSG_ID/@Value</to>
    </copy>

  6. Или сравнение.


    <condition>xp20:compare($sender_bic,$recipient_bic) != 0</condition>

  7. Вкусное. Можно вставить Java.


    <extensionActivity>
     <bpelx:exec language="java">
         <![CDATA[XMLElement elem = (XMLElement) getVariableData("output",
          "payload");
         String t = elem.getTextContent();
         elem.setTextContent(t + ", set by java exec 2");]]>
     </bpelx:exec>
    </extensionActivity>


Добавление в композит вызов сервиса

Есть бизнес-процесс который вызывает внешнюю систему, которая через какое-то время делает запрос в тестируемую систему. Этого в нашем бизнес-процессе нет.
Необходимо настроить партнерские соглашения с новым сервисом, прописать переменные и вставить invoke сервиса запросом ReqSyncFinancialTransactionBatch в наш бизнес-процесс.
Сервис-провайдер, который принимает запрос ReqSyncFinancialTransactionBatch тоже построен на SOA и по хорошему стечению обстоятельств от него есть композит.
Нужно его распаковать и перетащить все, что относится к вызову провайдера в наш композит.


  1. Добавляем пространства имен от провайдера и типа запроса в список.


    xmlns:ns27="urn:syst-ws:ws_soap-provider_ta" 
    xmlns:ns28="http://www.mybank.ru/ApplicationObjectLibrary/syst/Providers/DistributedFinancialTransactionProcessingBatchsystProvA/V1/SyncFinancialTransactionBatch_Request"   

  2. Добавление партнерского соглашения.


    <import namespace="urn:syst-ws:ws_soap-provider_ta"
          location="oramds:/apps/EDM/mybank/ApplicationObjectLibrary/syst/wsdls/ProviderTA/V1/PROVIDER_TA.wsdl"
          importType="http://schemas.xmlsoap.org/wsdl/"/>

  3. Мне потребовалось еще и импортировать схемы.


    <import namespace="urn:syst-ws:ws_soap-provider_ta"
          location="oramds:/apps/EDM/mybank/ApplicationObjectLibrary/syst/wsdls/ProviderTA/V1/PROVIDER_TA.wsdl"
          importType="http://schemas.xmlsoap.org/wsdl/"/>
    <import namespace="http://www.mybank.ru/ApplicationObjectLibrary/syst/Providers/DistributedFinancialTransactionProcessingBatchsystProvA/V1/SyncFinancialTransactionBatch_Request"
          location="oramds:/apps/EDM/mybank/ApplicationObjectLibrary/syst/schemas/Providers/DistributedFinancialTransactionProcessingBatchsystProvA/V1/SyncFinancialTransactionBatch_Request.xsd"
          importType="http://www.w3.org/2001/XMLSchema"/>    

  4. Пропишем переменные.


    <variable name="CITResponse" element="ns28:CIT_REQUEST"/>       
    <variable name="processPutSoapIn" messageType="ns27:PROCESSPUTSoapIn"/>

  5. Делаем присвоения в новом запросе, там где необходимо в соответствии со схемой.


    <assign name="AssignOK">
        <copy ignoreMissingFromData="yes" bpelx:insertMissingToData="yes">
            <from>"cm.System.syst"</from>
            <to>$CITResponse/DATA/ReqSyncFinancialTransactionBatch/BEGIN_/systemTo/@Value</to>
        </copy>
        <copy ignoreMissingFromData="yes" bpelx:insertMissingToData="yes">
            <from>"cm.System.BQ"</from>
            <to>$CITResponse/DATA/ReqSyncFinancialTransactionBatch/BEGIN_/systemFrom/@Value</to>
        </copy>                                     
        <copy ignoreMissingFromData="yes" bpelx:insertMissingToData="yes">
            <from>$onMessage_ExecuteFinancialTransaction_InputVariable.part2/DATA/ReqExecFinancialTransaction/BEGIN_/document/BEGIN_/id/@Value</from>
            <to>$CITResponse/DATA/ReqSyncFinancialTransactionBatch/BEGIN_/documentList/BEGIN_/document/BEGIN_/id/@Value</to>
        </copy> 
    </assign>       

  6. Присвоение переменной во входную переменную для вызова сервиса. Смотрим в wsdl провайдера на сообщение, которое он понимает.


    <wsdl:message name="PROCESSPUTSoapIn">
        <wsdl:part name="parameters" element="tns:PROCESSPUT"/>
    </wsdl:message>

    <assign name="assignResponse">
        <copy ignoreMissingFromData="yes" bpelx:insertMissingToData="yes">
            <from>$CITResponse</from>
            <to>$processPutSoapIn.parameters/ns27:REQUESTPUT</to>
        </copy>
    </assign>

  7. Делаем вызов сервиса invoke, и вычитывание ответа receive, если нужно.
    Если нужно, проставляем необходимые хедеры к запросу с помощью bpelx:toProperties.


    <sequence>
    <invoke name="sendResponse"
        inputVariable="processPutSoapIn"
        partnerLink="ProviderTAWSImport" portType="ns27:PROVIDER_TASoap"
        operation="Async_PROCESSPUT"
        bpelx:invokeAsDetail="no">
        <bpelx:toProperties>
            <bpelx:toProperty name="replyToAddress">'null'</bpelx:toProperty>
        </bpelx:toProperties>
    </invoke>                           
    <receive name="receiveResponse"
        createInstance="no"
        partnerLink="ProviderTAWSImport"
        portType="ns27:PROVIDER_TACallbackSoap"
        operation="Async_PROCESSPUTCallback"
        variable="processPutSoapOut"
        xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"/>
    </sequence> 

  8. Добавим отношение к новому сервису в файл .componentType


    ...
    <reference name="ProviderTAWSImport" ui:wsdlLocation="PROVIDER_TAWrapper.wsdl">
      <interface.wsdl interface="urn:syst-ws:ws_soap-provider_ta#wsdl.interface(PROVIDER_TASoap)" callbackInterface="urn:syst-ws:ws_soap-provider_ta#wsdl.interface(PROVIDER_TACallbackSoap)"/>
    </reference>      
    </componentType>

  9. Положим wsdl PROVIDER_TAWrapper.wsdl от сервиса в наш проект


  10. Добавим reference в файл сfgplan


    <composite name="DistributedFinancialTransactionProcessingBatchsystReqA">
      <reference name="ProviderTAWSImport">
         <binding type="ws">
            <attribute name="location">
               <replace>@@@systDistributedFinancialTransactionProviderTAWSDL@@@</replace>
            </attribute>
            <property name="oracle.webservices.httpConnTimeout">
               <replace>@@@systDistributedFinancialTransactionTAWSDL_httpConnTimeout@@@</replace>
            </property>
            <property name="oracle.webservices.httpReadTimeout">
               <replace>@@@systDistributedFinancialTransactionTAWSDL_httpReadTimeout@@@</replace>
            </property>
         </binding>
      </reference>
    </composite>  

  11. Добавим импорт wsdl, reference и wire в файл composit.xml
    Обратим внимание на ссылку к wsdl сервиса-провайдера location="http://k10systwp.mybank.ru:7030/webproxy/WS/PROVIDER_TA?wsdl


    <import importType="wsdl" location="PROVIDER_TAWrapper.wsdl" namespace="urn:syst-ws:ws_soap-provider_ta"/>
    <import importType="wsdl" location="PROVIDER_TAWrapper1.wsdl" namespace="urn:syst-ws:ws_soap-provider_ta"/>
    <import importType="wsdl" location="PROVIDER_TAWrapper2.wsdl" namespace="urn:syst-ws:ws_soap-provider_ta"/>      


    <reference name="ProviderTAWSImport" ui:wsdlLocation="oramds:/apps/EDM/mybank/ApplicationObjectLibrary/syst/wsdls/ProviderTA/V1/PROVIDER_TA.wsdl">
      <interface.wsdl callbackInterface="urn:syst-ws:ws_soap-provider_ta#wsdl.interface(PROVIDER_TACallbackSoap)" interface="urn:syst-ws:ws_soap-provider_ta#wsdl.interface(PROVIDER_TASoap)"/>
      <binding.ws location="http://k10systwp.mybank.ru:7030/webproxy/WS/PROVIDER_TA?wsdl" port="urn:syst-ws:ws_soap-provider_ta#wsdl.endpoint(PROVIDER_TA/PROVIDER_TASoap)" soapVersion="1.1">
         <property many="false" name="weblogic.wsee.wsat.transaction.flowOption" type="xs:string">WSDLDriven</property>
      </binding.ws>
      <callback>
         <binding.ws port="urn:syst-ws:ws_soap-provider_ta#wsdl.endpoint(PROVIDER_TA/PROVIDER_TACallbackSoap_pt)"/>
      </callback>
   </reference>      

   <wire>
```DistributedFinancialTransactionProcessingBatchsystReqA/ProviderTAWSImport</source.uri>
      <target.uri>ProviderTAWSImport</target.uri>
   </wire>  

  1. Все, пробуем собрать и деплоить

Тестирование композита


Проверим то, что мы наделали.


Проверка своего сервиса
  1. Берем SoapUI, генерируем mosk-сервис, используя wsdl от задеплоенного нами сервиса.
  2. Берем пример запроса к нашему сервису, прописываем в настройках в ReplyTo адрес mosk, которого только что создали. В Action прописываем операцию. Картинка кликабельна.


  3. Делаем запрос
  4. Смотрим, сервис отработал и прислал ответ. Картинка кликабельна.



Проверка внедренного вызова в сервис
  1. Также возьмем SoapUI, генерируем mosk-сервис, используя wsdl от сервис-провайдера.
  2. Копируем адрес wsdl и прописываем его в файле composite.xml в нашем сервисе. Таким образом мы указываем куда будет идти внедренный запрос.
    <binding.ws location="http://k10-emul:8089/mockPROVIDER_TASoap?WSDL" port="urn:ws:ws_soap-provider_ta#wsdl.endpoint(PROVIDER_TA/PROVIDER_TASoap)" soapVersion="1.1">
  3. Сохраняем, деплоим с другой версией. Снимаем также галочку в default, чтобы наш дебаг никому не помешал.


  4. Проверим, что все собралось без ошибок и идем в EM. Ищем наш сервис с новой ревизией.




  5. Сделаем запрос и проверим что внедренный вызов пришел на наш stub. Картинка кликабельна.



Анализ проблем при работе


Что делать если разработчики скажут, что наша заглушка тормозит, а у них все отлично?
Будем разбираться.


Поиск запросов в БД SOA

Потребовалось найти запросы по содержимому, чтобы понять что с ним случилось. Таблица CUBE_INSTANCE в нашей схеме DEV_SOAINFRA содержит всю историю по композитам. Но для просмотра надо ее вытащить из блоба.
Нашел тут функцию, которая это делает


код
        CREATE OR REPLACE PACKAGE SOA_UTIL AS

           -------------------------------------------------------------------------------------------
           -- Written by   : Gilberto Holms (https://gibaholms.wordpress.com/)
           -- Last update  : 07/11/2014
           -- Version      : 1.1
           -- Description  : Utility code to handle Oracle SOA Suite tables
           -- Release notes:
           --   1.0: Initial release
           --   1.1: Bug fix to work properly on SOA 10g
           -------------------------------------------------------------------------------------------

          FUNCTION GET_AUDIT_TRAIL(P_SCHEMA_NAME VARCHAR2, P_CIKEY NUMBER) RETURN CLOB;

        END SOA_UTIL;

        /

        CREATE OR REPLACE PACKAGE BODY SOA_UTIL AS

           -------------------------------------------------------------------------------------------
           -- Written by   : Gilberto Holms (https://gibaholms.wordpress.com/)
           -- Last update  : 07/11/2014
           -- Version      : 1.1
           -- Description  : Utility code to handle Oracle SOA Suite tables
           -- Release notes:
           --   1.0: Initial release
           --   1.1: Bug fix to work properly on SOA 10g
           -------------------------------------------------------------------------------------------

          FUNCTION GET_AUDIT_TRAIL(P_SCHEMA_NAME VARCHAR2, P_CIKEY NUMBER) RETURN CLOB
          AS
            V_AUDIT_BLOB BLOB;
            V_AUDIT_CLOB CLOB;

            V_CUR_AUDIT SYS_REFCURSOR;

            TYPE TP_AUDIT_RECORD IS RECORD(
              BLOCK NUMBER(38,0),
              LOG BLOB
            );
            TYPE TP_AUDIT_ARRAY IS TABLE OF TP_AUDIT_RECORD;
            V_AUDIT_ARRAY TP_AUDIT_ARRAY;
            V_AUDIT_COMPLETE BLOB;

            V_BUFFER_LENGTH PLS_INTEGER := 32767;
            V_BUFFER VARCHAR2(32767);
            V_READ_START PLS_INTEGER := 1;
        BEGIN

            DBMS_LOB.CREATETEMPORARY(V_AUDIT_BLOB, TRUE);
            DBMS_LOB.CREATETEMPORARY(V_AUDIT_CLOB, TRUE);
            DBMS_LOB.CREATETEMPORARY(V_AUDIT_COMPLETE, TRUE);

            OPEN V_CUR_AUDIT FOR 'SELECT BLOCK, LOG FROM ' || P_SCHEMA_NAME || '.AUDIT_TRAIL WHERE CIKEY = :cikey ORDER BY COUNT_ID' USING P_CIKEY;
            FETCH V_CUR_AUDIT BULK COLLECT INTO V_AUDIT_ARRAY;
            CLOSE V_CUR_AUDIT;

            FOR j IN 1..V_AUDIT_ARRAY.COUNT LOOP
                IF j = 1 THEN
                    DBMS_LOB.APPEND (V_AUDIT_BLOB, V_AUDIT_ARRAY(j).LOG);
                ELSE
                    IF ( V_AUDIT_ARRAY(j).BLOCK = V_AUDIT_ARRAY(j-1).BLOCK ) THEN
                        DBMS_LOB.APPEND (V_AUDIT_BLOB, V_AUDIT_ARRAY(j).LOG);
                    ELSE
                        DBMS_LOB.APPEND (V_AUDIT_COMPLETE, UTL_COMPRESS.LZ_UNCOMPRESS(V_AUDIT_BLOB));
                        DBMS_LOB.CREATETEMPORARY(V_AUDIT_BLOB, TRUE);
                        DBMS_LOB.APPEND (V_AUDIT_BLOB, V_AUDIT_ARRAY(j).LOG);
                    END IF;
                END IF;
            END LOOP;

            DBMS_LOB.APPEND (V_AUDIT_COMPLETE, UTL_COMPRESS.LZ_UNCOMPRESS(V_AUDIT_BLOB));
            V_AUDIT_ARRAY.DELETE;

            FOR i IN 1..CEIL(DBMS_LOB.GETLENGTH(V_AUDIT_COMPLETE) / V_BUFFER_LENGTH) LOOP
                V_BUFFER := UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(V_AUDIT_COMPLETE, V_BUFFER_LENGTH, V_READ_START));
                DBMS_LOB.WRITEAPPEND(V_AUDIT_CLOB, LENGTH(V_BUFFER), V_BUFFER);
                V_READ_START := V_READ_START + V_BUFFER_LENGTH;
            END LOOP;

            RETURN V_AUDIT_CLOB;

        END;

        END SOA_UTIL;

        /

и пример использования


SELECT
  ci.ecid,
  CI.COMPOSITE_NAME,
  SOA_UTIL.GET_AUDIT_TRAIL('DEV_SOAINFRA', CI.CIKEY) AS AUDIT_TRAIL_XML,
  ci.*
FROM
  DEV_SOAINFRA.CUBE_INSTANCE CI
WHERE
  CI.CREATION_DATE > to_date('21.04.2017 09:57:00','dd.mm.yyyy hh24:mi:ss') and
  CI.CREATION_DATE < to_date('21.04.2017 19:59:00','dd.mm.yyyy hh24:mi:ss') and
  CI.CREATION_DATE > sysdate-0.3 and
  SOA_UTIL.GET_AUDIT_TRAIL('DEV_SOAINFRA', CI.CIKEY) like '%40702810312080005917%';

Картинки кликабельны.


  1. Ищем проблемный запрос. Картинка кликабельна.


  2. Берем его индентификатор ECID
  3. Идем в EM и ищем запрос по ECID


  4. Смотрим что случилось и главное за какое мы ответили системе





Мониторинг и замечания по работе

Тут ничего сложного


  1. Для мониторинга системных ресурсов и метрик soa eсть замечательная вкладка Perfomace summary.


  2. Есть свой скрипт, который будет слать soap запросы к заглушке раз в 30 секунд и замеряет время ответа. Можно его прикрутить к чему угодно, Grafana, Zabbix, Sitescope
  3. При работах потребовалось увеличить память для heap до 4096, сама машина с 16 gb ram.
  4. Так как история запросов растет, соответственно схема soa также пухнет. Требовалось расширять табличное пространство. Код можно найти в интернете, я приведу на всякий случай

Расширение табличного пространства
ALTER TABLESPACE DEV_SOAINFRA
ADD DATAFILE 'C:\APP\KALISTRATOVKA\ORADATA\ORCL\DEV_SOAINFRA07.DBF' size 20000M
AUTOEXTEND ON
NEXT 100M
MAXSIZE 20000M;

Размер табличного пространства можно смотреть в таблице dba_tablespace_usage_metrics


Заключение


За неизвестное можно и нужно браться и не бояться ошибиться. Да, и JDev мне понравился больше чем Eclipse.


Ссылки на источники:


http://www.oracle-adf.info/2014/03/oracle-soa-suite.html
https://shouab.wordpress.com/oracle-soa-11g-step-by-step-installation-guide/
http://www.theserverside.com/news/1364554/BPEL-and-Java
http://samolisov.blogspot.ru/2009/06/soa-bpel.html
http://docs.oracle.com/cd/E15586_01/integration.1111/e10224/bp_java.htm
https://gibaholms.wordpress.com/2014/02/03/export-audit-trail-from-database-soa-10g-and-11g/
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 10

    0
    Нет, конечно, добавляю логику формирования ответа в зависимости от данных в запросе.
    Имеете ввиду MockService Scripting? Надо будет попробовать.
    Интересно сравнение производительности заглушек на SoapUI и Weblogic.

    Мне понравилось, что SOA дает возможности анализа проблемных запросов что называется из коробки, без написания своего логирования.

    Если будет wsdl будет конкретный с wsdl:service без партнер линков, как мне достался (тот что валяется в композите), то да, можно юзать jdev, eclipse и деплоить в любимый апп сервер
      0
      Я имел ввиду SOAP Mock Service, также есть логирование запросов/ответов, на groovy есть возможность писать скрипты, который позволяют в зависимости от получаемых данных возвращать определенный Response.
      Я так понимаю вы тестеровщик?
        0
        Я понял, посмотрел, но не нашел как написать вызов веб-сервиса на groovy. Подозреваю что можно записать свой класс, импортировать и тут уже вызвать.
        Вообщем главная проблема в том, что это будет заглушка на коленке для отладки со всеми вытекающими. При проведении нагрузочного тестирования (да, я инженер по нагрузке) все это ляжет и потом не разберешься где, что и почему упало.
        Я уже вижу глаза разработчиков, если бы я сказал что у меня стабы на soapui. Я бы сам стал плеваться.
        Нормальный подход — разработка, деплой в апп сервер, перфоманс тюнинг.
          0
          Допустим вам приходит в разработку какой-то БС, который вызывает какую-то конечную систему. Вы берете, создаете копию этого проекта и вместо вызова конечной системы делайте заглушку? Итого, 2 копии БС?
            0
            Нет. Это отдельный стенд. В целевой тестируемой системе меняются реальные ссылки на веб-сервисы-заглушки.
              0
              Есть композит GetCustomerPartyAccount в нем вызывается конечная система. Это одна копия.
              Вы берете композит, убираете вызов конечной системы меняете на заглушку. Это вторая копия.
              По это логике, если приходит баг на композит GetCustomerPartyAccount, вы должны его еще и во второй копии поправить?
                0
                Ну в своей заглушке да, конечно я поправлю. В исходной правит разработчик.
                  0
                  Это же капец как неудобно, нужно менять исходник. Если бы это был Soapui ничего бы менять не пришлось ;)
                    0
                    при изменении wsdl на основе которого был сгенерен стаб, он меняется?
                    Но все равно придется менять скрипт и ответ, если баг затрагивает нужные теги.
                    На моей памяти пока еще не было бага в интеграции, чтобы приходилось сильно париться. В этом проекте как раз надо было метод поменять на другой. 5 минут.
      0
      Серьезно? Вы просто удаляете вызов конечной системы? Вы так со всеми сервисами работаете? Месье знает толк…
      Заглушка на SoapUI, чем плоха? Создать заглушку в SOA Suite, если есть MDS с wsdl конечной системы и xsd?

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое