пятница, 3 сентября 2010 г.

Запрос к WebService из PL/SQL

Наша проектная группа сопровождает информационную систему, введенную в эксплуатацию еще в 1998 году. Естественно, если в те прекрасные времена кто-то и слышал про WebService, то слухи эти воспринимались, как сказочное будущее...

Но вот оно настало. Это будущее... А средства, на которых была написана система, не изменились... Портировать ее на новые версии накладно. Заказчик оплачивать данный проект не захочет, а самим инвестировать в эту деятельность тяжело. Придется остановить производство (выпуск новых версий со всякими фичами и исправлением багов). Это никому не понравиться...

И в этот момент возникло у Заказчика желание формировать в системе PDF-документы. И для этих целей как нельзя лучше подходил ему BI Publisher. И лицензии уже есть и опыт использования через Web-интерфейс тоже, а из системы своей его не вызвать.
Можно конечно, как url вызывать и в окне браузера показывать, но хотелось Заказчику текст PDF в базе сохранять.

И решили мы эту задачу так...
В BIPublisher есть WebService, через который можно управлять формированием отчетов и получать в ответ на запрос поток byte, представляющий собой текст отчета.
Но средства, на которых написана система вызов WS не поддерживают.
Остался один выход....
Вызывать WS из PL/SQL кода.

В результате получилось нечто следующее...

Это функция делает запрос к какому-то Webсервису

function makeDealInformationReport(in_report_path in varchar2) return varchar2
IS
ret_value sys.xmltype;
temp xmltype;
begin
ret_value:=xmltype(
start_abstract_process1(
'http://balorasits2.baltros.ru/KugiReports-Reports-context-root/RevisionActWSSoapHttpPort',
'makeDealInformationReport',
'<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body xmlns:ns1="http://reports/types/"><ns1:makeDealInformationReportElement><ns1:reportAbsolutePath>'
in_report_path
'</ns1:reportAbsolutePath></ns1:makeDealInformationReportElement></soap:Body></soap:Envelope>'
));

temp := ret_value.extract('//env:Body','xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"');
return temp.extract('//ns0:makeDealInformationReportResponseElement/ns0:result/child::text()', 'xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns0="http://reports/types/"').getstringval();
end;
/

Запрос выполняется с помощью функции, которую мы написали для запуска произвольного WebService. Поначалу мы использовали ее для старта BPEL-процесса, а потом использовали уже для любого WS

function start_abstract_process1



(
bpel_endpoint in varchar2, -- можно найти в WSDL сервиса
bpel_action in varchar2, -- Это собственно метод сервиса
bpel_input in clob -- Это значение входных данных (soap-сообщение) 
) return varchar2  - возвращает результат WS


IS
soap_request varchar2(30000);
soap_respond varchar2(30000);
http_req utl_http.req;
http_resp utl_http.resp;
launch_url varchar2(240) ;
name VARCHAR2(256);
value VARCHAR2(1024);


begin
soap_request:= bpel_input;
http_req:= utl_http.begin_request(bpel_endpoint,'POST','HTTP/1.1');
utl_http.set_header(http_req, 'Content-Type', 'text/xml;charset=Windows-1251') ;
utl_http.set_header(http_req, 'Content-Length', length(soap_request)) ;
utl_http.set_header(http_req, 'SOAPAction',bpel_action );
utl_http.write_text(http_req, soap_request) ;
http_resp:= utl_http.get_response(http_req) ;
utl_http.read_text(http_resp, soap_respond) ;
utl_http.end_response(http_resp);


return soap_respond;
EXCEPTION
WHEN utl_http.end_of_body THEN
utl_http.end_response(http_resp);
return soap_respond;
when others then raise;
END; 
/

Ну вот собственно и все.
Если кому-то поможет - буду рад.
В свое время потратили на поиски решения несколько дней...

Комментариев нет: