В этой статье я расскажу как реализовать заглушки веб-сервисов бизнес-процесса на 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.
Бизнес процесс выглядит примерно так:
Весь бизнес-процесс строится в виде композита и устанавливается на сервер-приложений. Запросил рабочий композит с функционального стенда, настроил Eclipse для работы с BPEL (плагины, Apache ODE и прочее). Снова попытки импорта композита в Eclipse. Снова неудача.
Посетила мысль сделать точно также, как на продуктиве, итого мы имеем в хозяйстве: Oracle Database, Oracle Weblogic, Oracle SOA Suite, JDeveloper. И так, что нам потребуется и какие версии:
- 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:OracleMiddlewarejdk160_24
-
Пропустим обновление софта.
-
Проверка операционной системы и физической памяти, в случае ошибки можно проигнорировать.
-
Выбор Middleware Home и название директории для нашего SOA.
-
Далее установщик нашел Weblogic в домашней папке.
- Установка и поздравления. Проверим подключение.
sqlplus sys@ORCL as sysdba
- Или запустим SQL Developer и настроим подключение.
c:appadminproduct11.2.0dbhome_1sqldevelopersqldeveloper.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:OracleMiddlewareOracle_SOA1commonbin
У меня JDK 1.7, поэтому он ругнулся
Мы ее обойдем — меняем javaw на java в файлеc:OracleMiddlewarewlserver_10.3commonbinconfig.cmd
и получаем описание Unrecognized VM option 'UseSpinning'
Удаляем опцию -XX:+UseSpinning (которой больше нет с 1.6) в файлеc:OracleMiddlewarewlserver_10.3commonbincommEnv.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:OracleMiddlewareuser_projectsdomainsbase_domainbinstartManagedWebLogic.cmd soa_server1
- Когда будет просить ввод логина и пароля, вводим от администратора домена. Чтобы больше не просил создадим файл.
c:OracleMiddlewareuser_projectsdomainsbase_domainserverssoa_server1securityboot.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.PROCESS_ID AS PROCESS_ID,
CI.CIKEY AS INSTANCE_ID,
CI.CREATION_DATE AS CREATION_DATE,
CI.STATUS AS STEP,
SOA_UTIL.GET_AUDIT_TRAIL('ORABPEL', CI.CIKEY) AS AUDIT_TRAIL_XML
FROM
ORABPEL.CUBE_INSTANCE CI
WHERE
CI.PROCESS_ID = 'MyBPEL'
AND CI.CREATION_DATE BETWEEN (sysdate - 1) AND (sysdate)
ORDER BY CI.CREATION_DATE DESC;
Картинки кликабельны.
Тут ничего сложного
- Для мониторинга системных ресурсов и метрик soa eсть замечательная вкладка Perfomace summary.
- Есть свой скрипт, который будет слать soap запросы к заглушке раз в 30 секунд и замеряет время ответа. Можно его прикрутить к чему угодно, Grafana, Zabbix, Sitescope
- При работах потребовалось увеличить память для heap до 4096, сама машина с 16 gb ram.
- Так как история запросов растет, соответственно схема soa также пухнет. Требовалось расширять табличное пространство. Код можно найти в интернете, я приведу на всякий случай
ALTER TABLESPACE DEV_SOAINFRA
ADD DATAFILE 'C:APPKALISTRATOVKAORADATAORCLDEV_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/
Автор: Bell Integrator