В этой статье я расскажу как реализовать заглушки веб-сервисов бизнес-процесса на 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
- Примеры запросов и ответов
Разворачивание своего стенда
Инструкции по установке и настройке софта
Запуск установщика.
java -jar wls1036_generic.jar
Выбор пути для домашней папки.
Пропустим регистрацию для обновлений.
Выберем типичную установку.
Укажем папку с JDK.
Далее укажем папку куда поставить сам Weblogic.
Установка и поздравления.
В установке нет ничего сложного, остановлюсь только на некоторых моментах.
Пропустим минимальные требования и поставим Oracle Database 11g Release 2 x32 для Windows, выберем Desktop Class. Нам для разработки хватит.
В интернете, в том числе и на хабре есть много статей по установке. Отмечу только установку под локальным админом и задание переменных окружения. Хотя ошибка с отсутствием ORACLE_UNQNAME не помешала и все завелось.
Для запуска установщика надо указать путь к JRE или JDK.
ofm_soa_generic_11.1.1.7.0/Disk1/setup.exe -jreLoc c:\Oracle\Middleware\jdk160_24
Пропустим обновление софта.
Проверка операционной системы и физической памяти, в случае ошибки можно проигнорировать.
Выбор Middleware Home и название директории для нашего SOA.
Далее установщик нашел Weblogic в домашней папке.
Установка и поздравления. Проверим подключение.
sqlplus sys@ORCL as sysdba
Или запустим SQL Developer и настроим подключение.
c:\app\admin\product\11.2.0\dbhome_1\sqldeveloper\sqldeveloper.exe
Запустим RCU.
ofm_rcu_win_11.1.1.7.0_64_disk1_1of1/rcuHome/bin/rcu.bat
Выбираем Create Repository.
Указываем параметры БД, в нашем случае это localhost, 1521, sys и пароль. Далее идет проверка.
Следом надо указать префикс для имен схем данных (по умолчанию DEV) и выбрать компоненты репозитория, нам нужны Metadata Services и SOA Infrastructure, User Messaging Service выбирается автоматически.
Укажем пароль для пользователей, владельцев схем с данными для репозитория.
Потом можно выбрать табличные пространства для схем данных репозитория.
Запуск создания tablespaces.
Готово.
Запускаем установку.
Чтобы его создать запустим файл 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
и снова запускаем.
Выбираем создание нового домена.
Выбираем Oracle SOA Suite, Enterprise Manager. WSM Policy Manager и JRF выберутся автоматически.
Указываем имя и путь к домену и приложениям.
Пароль для пользователя weblogic.
JDK и тип инсталляции. Оставим Development Mode.
Пропишем пароли к вашим схемам, хост и sid:.
Проверка.
Настраивать не будем, оставим пустыми.
Жмем создать.
Готово. Запустим Admin Server.
Дождемся сообщения "Server state changed to RUNNING"
Запустим soa_server1.
c:\Oracle\Middleware\user_projects\domains\base_domain\bin\startManagedWebLogic.cmd soa_server1
Когда будет просить ввод логина и пароля, вводим от администратора домена. Чтобы больше не просил создадим файл.
c:\Oracle\Middleware\user_projects\domains\base_domain\servers\soa_server1\security\boot.properties
username=weblogic password=welcome1
Проверка WebLogic Administration Console: http://localhost:7001/console (если вы использовали порт по умолчанию при установке).
Проверка Enterprise Manager: http://localhost:7001/em
В Enterprise Manager должна быть доступна вкладка “SOA” в дереве слева.
Необходимо установить JDeveloper что бы создавать композиты. Берем версию 11.1.1.9.0.
Ставим, используя существующий Middleware Home.
Для работы с композитами, необходимо установить расширение для нашего JDeveloper.
Подготовка к разработке
Композиты, которые мы будем деплоить, используют схемы, которые хранятся в MDS в БД. Его можно запросить или выкачать из стенда для функционального тестирования.
Разработка
Расковыряем композит и задеплоим
На картинке выше можно видеть в правой части имеется внешняя система и бизнес-процесс ее вызывает методом invoke.
Давайте же уберем это ненужное. Я буду делать это в блокноте. Но можно и в интерфейсе.
Краткий экскурс.
Файл состоит из блоков, вариаций больше, я перечислю некоторые:
process — корневой тег для процесса
partnerLinks — партнерские соглашения между сервисами
variables — декларация переменные
faultHandlers — обработчики ошибок
sequence main — бизнес-процесс
receive — получение запроса от клиента
assign — блок присвоения переменных
сopy — копирование данных из одного объекта в другой
invoke — вызов веб-сервиса
if, elseif, else — объявление условий
condition — описание условия
forEach — объявление цикла
startCounterValue — начало цикла
finalCounterValue — конец цикла
scope — объединение
Убрать часть соглашения, касающееся внешней системы.
<partnerLink name="GetCustomerPartyAccountBS" partnerLinkType="ns2:GetCustomerPartyAccount" partnerRole="GetCustomerPartyAccountProvider" myRole="GetCustomerPartyAccountRequester"/>
Для простоты обработчик ошибок я тоже удалю. Весь тег faultHandlers.
<faultHandlers/>
Удаляем assign запроса к внешней системе, оставим только копирование данных из запроса для идентификации запроса.
<copy> <from>$inputVariable.payload/SYSTEM/MSG_ID/@Value</from> <to>$outputVariable.payload/SYSTEM/MAIN_ID/@Value</to> </copy>
Удаляем все вызовы внешних систем invoke, кроме последнего в файле, где должен быть ответ нашему клиенту.
<invoke name="callbackClient" partnerLink="getcustomerpartyaccountsystreqa_client" portType="ns1:GetCustomerPartyAccountsystReqACallback" operation="processResponse" inputVariable="outputVariable"/>
Посмотрим переменную, в которую нужно записать ответ. В нашем случае это outputVariable
Берем пример ответа, который наш дружелюбно предоставили разработчики или мы сами вытащили из 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>
- Удалим импорт wsdl от внешнего сервиса.
<import importType="wsdl" location="oramds:/apps/EDM/EnterpriseBusinessServiceLibrary/GetCustomerPartyAccountBS/V1/GetCustomerPartyAccountBSV1.wsdl" namespace="http://www.ru/EnterpriseBusinessServiceLibrary/GetCustomerPartyAccountBS/V1"/>
- Уберем еще ссылку на внешний сервис.
<reference name="GetCustomerPartyAccountBS">
- И еще соединение wire к удаляемому сервису GetCustomerPartyAccountBS
<wire> ```GetCustomerPartyAccountsystReqA/GetCustomerPartyAccountBS</source.uri> <target.uri>GetCustomerPartyAccountBS</target.uri> </wire>
- Убираем ссылку на внешний сервис в этих файлах.
<reference name="GetCustomerPartyAccountBS">
- Пробуем собрать. Right Click на проекте -> Make.
Если все ОК, то деплоим, нет — разбираемся.
Пробуем задеплоить.
Выбор операции.
Можно создать несколько сервисов с одинаковым именем, но разной версии.
Вызывать можно все, но по стандартному адресу будет работать только default-ревизии. В Enterprise Manager можно применить default на задеплоенном композите.
Выбор сервера.
Добавим локальный сервер. Жмем плюс.
Выбор SOA сервера.
Summary.
Лог деплоя.
Несколько примеров интересных возможностей.
Регулярные выражения.
<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> ...
Присвоение строки
<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>
Цикл и итератор.
<forEach parallel="no" counterName="ForEach1CounterSync" name="ForEachSync"> <startCounterValue>1</startCounterValue> <finalCounterValue>count($onMessage_ExecuteFinancialTransactionBatch_InputVariable.part1/DATA/ReqExecFinancialTransactionBatch/BEGIN_/documentList/BEGIN_)</finalCounterValue> ...
Использование итератора в цикле.
<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>
Много встроенный функций, например генерация guid.
<copy> <from>oraext:generate-guid()</from> <to>$CITResponse/SYSTEM/MSG_ID/@Value</to> </copy>
Или сравнение.
<condition>xp20:compare($sender_bic,$recipient_bic) != 0</condition>
Вкусное. Можно вставить 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 и по хорошему стечению обстоятельств от него есть композит.
Нужно его распаковать и перетащить все, что относится к вызову провайдера в наш композит.
Добавляем пространства имен от провайдера и типа запроса в список.
xmlns:ns27="urn:syst-ws:ws_soap-provider_ta" xmlns:ns28="http://www.mybank.ru/ApplicationObjectLibrary/syst/Providers/DistributedFinancialTransactionProcessingBatchsystProvA/V1/SyncFinancialTransactionBatch_Request"
Добавление партнерского соглашения.
<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="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"/>
Пропишем переменные.
<variable name="CITResponse" element="ns28:CIT_REQUEST"/> <variable name="processPutSoapIn" messageType="ns27:PROCESSPUTSoapIn"/>
Делаем присвоения в новом запросе, там где необходимо в соответствии со схемой.
<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>
Присвоение переменной во входную переменную для вызова сервиса. Смотрим в 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>
Делаем вызов сервиса 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>
Добавим отношение к новому сервису в файл .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>
Положим wsdl PROVIDER_TAWrapper.wsdl от сервиса в наш проект
Добавим 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>
Добавим импорт 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>
- Все, пробуем собрать и деплоить
Тестирование композита
Проверим то, что мы наделали.
- Берем SoapUI, генерируем mosk-сервис, используя wsdl от задеплоенного нами сервиса.
- Берем пример запроса к нашему сервису, прописываем в настройках в ReplyTo адрес mosk, которого только что создали. В Action прописываем операцию. Картинка кликабельна.
- Делаем запрос
- Смотрим, сервис отработал и прислал ответ. Картинка кликабельна.
- Также возьмем SoapUI, генерируем mosk-сервис, используя wsdl от сервис-провайдера.
- Копируем адрес 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">
- Сохраняем, деплоим с другой версией. Снимаем также галочку в default, чтобы наш дебаг никому не помешал.
- Проверим, что все собралось без ошибок и идем в EM. Ищем наш сервис с новой ревизией.
- Сделаем запрос и проверим что внедренный вызов пришел на наш stub. Картинка кликабельна.
Анализ проблем при работе
Что делать если разработчики скажут, что наша заглушка тормозит, а у них все отлично?
Будем разбираться.
Потребовалось найти запросы по содержимому, чтобы понять что с ним случилось. Таблица 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%';
Картинки кликабельны.
Тут ничего сложного
- Для мониторинга системных ресурсов и метрик soa eсть замечательная вкладка Perfomace summary.
- Есть свой скрипт, который будет слать soap запросы к заглушке раз в 30 секунд и замеряет время ответа. Можно его прикрутить к чему угодно, Grafana, Zabbix, Sitescope
- При работах потребовалось увеличить память для heap до 4096, сама машина с 16 gb ram.
- Так как история запросов растет, соответственно схема 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/