2009-07-27 3 views
2

Фон: У нас есть веб-сервис, который работает под осью 2 на Tomcat. Мы хотели бы, чтобы наш Oracle (10g Enterprise Edition Release 10.2.0.1.0) db вызывал наш Webservice, когда новая строка была введена в одну из наших таблиц. Мы обнаружили, что мы можем использовать триггер для вызова хранимой процедуры Java (JSP) или PL/SQL PLUS и утилиты UTL_DBWS. Однако мы не работаем для нас. Использование web-сервиса из автономного класса java с использованием либо реализации javax.xml.rpc оси, либо реализации oracle работает вне db.Использование Webservice с использованием UTL_DBWS

UTL_DBWS попытка:

распакованные содержание dbws-callout-utility-10131.zip в C: \ оракул \ продукт \ 10.2.0 \ db_5 \ SQLJ \ Lib, которая была разобрана из http://www.oracle.com/technology/sample_code/tech/java/jsp/dbwebservices.html

побежал loadjava команду

loadjava -u <USER>/<PASSWORD>@<MACHINE>:1521:<INSTANCE> -r -v -f -genmissing -s -grant public C:\oracle\product\10.2.0\db_5\sqlj\lib\dbwsclientws.jar C:\oracle\product\10.2.0\db_5\sqlj\lib\dbwsclientdb102.jar 

Добавлена ​​куча разрешений

execute dbms_java.grant_permission('<<user>>', 'SYS:java.lang.RuntimePermission', 'getClassLoader', '') 
    execute dbms_java.grant_permission('<<user>>', 'SYS:oracle.aurora.security.JServerPermission', 'Verifier', ''); 
    execute dbms_java.grant_permission('<<user>>', 'SYS:java.lang.RuntimePermission', 'accessClassInPackage.sun.util.calendar', '') ; 
    execute dbms_java.grant_permission('<<user>>', 'SYS:java.net.SocketPermission', '<<machineName>>', 'resolve'); 
    execute dbms_java.grant_permission('<<user>>', 'SYS:java.net.SocketPermission', '<<machineIP>>', 'connect,resolve'); 
    execute dbms_java.grant_permission('<<user>>', 'SYS:java.lang.RuntimePermission', 'createClassLoader', ''); 

Наш PL/SQL:

FUNCTION wsproxy_send_request 
return varchar2 
as 
l_service   SYS.UTL_DBWS.service; 
l_call    SYS.UTL_DBWS.call; 
l_result    ANYDATA; 
l_wsdl_url   VARCHAR2(32767); 
l_namespace   VARCHAR2(32767); 
l_service_qname  SYS.UTL_DBWS.qname; 
l_port_qname   SYS.UTL_DBWS.qname; 
l_operation_qname SYS.UTL_DBWS.qname; 
l_input_params  SYS.UTL_DBWS.anydata_list; 
boolean_type_qname SYS.UTL_DBWS.QNAME; 

begin 

l_wsdl_url := 'http://<<host>>/axis2/services/<<serviceName>>?wsdl'; 
l_namespace := 'http://<<namespace>>'; 
l_service_qname := SYS.UTL_DBWS.to_qname(l_namespace, '<<serviceName>>'); 
l_port_qname := SYS.UTL_DBWS.to_qname(l_namespace, '<<myendpoint>>'); 
l_operation_qname := SYS.UTL_DBWS.to_qname(l_namespace, 'send'); 

l_service := SYS.UTL_DBWS.create_service (wsdl_document_location => URIFACTORY.getURI(l_wsdl_url), service_name => l_service_qname); 
l_call := SYS.UTL_DBWS.create_call (service_handle => l_service, port_name => l_port_qname, operation_name => l_operation_qname); 

SYS.UTL_DBWS.SET_PROPERTY(l_call, 'OPERATION_STYLE', 'rpc'); 

l_input_params(0) := ANYDATA.ConvertNumber(1); 
l_input_params(1) := ANYDATA.ConvertNumber(24387236726); 
l_input_params(2) := ANYDATA.ConvertVarchar2('CTE'); 
l_input_params(3) := ANYDATA.ConvertVarchar2('STORE_RECORD_LOCATOR'); 
l_input_params(4) := ANYDATA.ConvertVarchar2('a'); 

boolean_type_qname := sys.utl_dbws.to_qname('http://www.w3.org/2001/XMLSchema', 'boolean'); 
sys.utl_dbws.set_return_type(l_call, boolean_type_qname); 

l_result := SYS.UTL_DBWS.invoke (call_handle => l_call, input_params => l_input_params); 

SYS.UTL_DBWS.release_call (call_handle => l_call); 
SYS.UTL_DBWS.release_service(service_handle => l_service); 

RETURN ANYDATA.AccessVarchar2(l_result); 
END; 

Когда мы выполняем:

select wsproxy_send_request from dual; 

мы получаем:

Error: ORA-29532: Java call terminated by uncaught Java exception: java.lang.ArrayIndexOutOfBoundsException 
ORA-06512: at "SYS.UTL_DBWS", line 568 
ORA-06512: at "SYS.UTL_DBWS", line 492 
ORA-06512: at "SYS.UTL_DBWS", line 380 
ORA-06512: at "WSPROXY.WSPROXY_SEND_REQUEST", line 37 

SQLState: 99999 
ErrorCode: 29532 
Position: 37 

(Позиция 37 является Invoke вызова)

+0

Заметили этот вопрос после того, как я спросил http://stackoverflow.com/questions/37586/consuming-web-services-from-oracle-pl-sql Мы можем попробовать UTL_HTTP и посмотреть, если это работает. – Josh

+0

Я обнаружил, что если я удалю все параметры, кроме первого, что является недействительным вызовом для нашего webservice, я получаю другое исключение ORA-29532: вызов Java завершен неперехваченным исключением Java: javax.xml. rpc.soap.SOAPFaultException: неизвестно ORA-06512: в строке «SYS.UTL_DBWS», строка 388 ORA-06512: по строке «SYS.UTL_DBWS», строка 385 ORA-06512: на «WSPROXY.WSPROXY_SEND_REQUEST ", строка 41 но классная вещь ... что это сгенерировано, потому что Axis получает запрос и отклоняется, потому что он не содержит правильных параметров. – Josh

ответ

2

Хитрость в том, чтобы добавить типы параметров/имена ... Я не нашел метод UTL_DBWS.add_parameter задокументирован в любом месте, но я должен угаданный это существование, так как вы должны делать то же самое в Java реализация.

Во всяком случае вот что я добавил

string_type_qname := SYS.UTL_DBWS.to_qname('http://www.w3.org/2001/XMLSchema', 'string'); 
long_type_qname := SYS.UTL_DBWS.to_qname('http://www.w3.org/2001/XMLSchema', 'long'); 

SYS.UTL_DBWS.add_parameter(l_call, 'args0', long_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args1', long_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args2', string_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args3', string_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args4', string_type_qname, 'ParameterMode.IN'); 

Так что все, что сейчас:

CREATE OR REPLACE 
FUNCTION wsproxy_send_request 
return varchar2 
as 
l_service    SYS.UTL_DBWS.service; 
l_call    SYS.UTL_DBWS.call; 
l_result    ANYDATA; 
l_wsdl_url    VARCHAR2(32767); 
l_namespace    VARCHAR2(32767); 
l_service_qname   SYS.UTL_DBWS.qname; 
l_port_qname   SYS.UTL_DBWS.qname; 
l_operation_qname  SYS.UTL_DBWS.qname; 
l_input_params   SYS.UTL_DBWS.ANYDATA_LIST; 
boolean_type_qname  SYS.UTL_DBWS.QNAME; 
string_type_qname  SYS.UTL_DBWS.QNAME; 
long_type_qname   SYS.UTL_DBWS.QNAME; 

begin 

l_wsdl_url := 'http://<<host>>/axis2/services/<<serviceName>>?wsdl'; 
l_namespace := 'http://<<namespace>>'; 
l_service_qname := SYS.UTL_DBWS.to_qname(l_namespace, '<<serviceName>>'); 
l_port_qname := SYS.UTL_DBWS.to_qname(l_namespace, '<<endPoint>>'); 
l_operation_qname := SYS.UTL_DBWS.to_qname(l_namespace, 'send'); 

l_service := SYS.UTL_DBWS.create_service (URIFACTORY.getURI(l_wsdl_url), l_service_qname); 
l_call := SYS.UTL_DBWS.create_call (l_service, l_port_qname, l_operation_qname); 

boolean_type_qname := SYS.UTL_DBWS.to_qname('http://www.w3.org/2001/XMLSchema', 'boolean'); 
string_type_qname := SYS.UTL_DBWS.to_qname('http://www.w3.org/2001/XMLSchema', 'string'); 
long_type_qname := SYS.UTL_DBWS.to_qname('http://www.w3.org/2001/XMLSchema', 'long'); 

SYS.UTL_DBWS.add_parameter(l_call, 'args0', long_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args1', long_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args2', string_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args3', string_type_qname, 'ParameterMode.IN'); 
SYS.UTL_DBWS.add_parameter(l_call, 'args4', string_type_qname, 'ParameterMode.IN'); 

SYS.UTL_DBWS.SET_PROPERTY(l_call, 'SOAPACTION_USE', 'TRUE'); 
SYS.UTL_DBWS.SET_PROPERTY(l_call, 'SOAPACTION_URI', ''); 
SYS.UTL_DBWS.SET_PROPERTY(l_call, 'ENCODINGSTYLE_URI', ''); 
SYS.UTL_DBWS.SET_PROPERTY(l_call, 'OPERATION_STYLE', 'rpc'); 

l_input_params(0) := ANYDATA.ConvertNumber(1); 
l_input_params(1) := ANYDATA.ConvertNumber(24387236726); 
l_input_params(2) := ANYDATA.ConvertVarchar2('CTE'); 
l_input_params(3) := ANYDATA.ConvertVarchar2('STORE_RECORD_LOCATOR'); 
l_input_params(4) := ANYDATA.ConvertVarchar2('a'); 

sys.utl_dbws.set_return_type(l_call, boolean_type_qname); 

l_result := SYS.UTL_DBWS.invoke(l_call, l_input_params); 

SYS.UTL_DBWS.release_call (l_call); 
SYS.UTL_DBWS.release_service(l_service); 

RETURN ANYDATA.AccessVarchar2(l_result); 
END; 
/

я наконец-то увидел это после того, как обращать более пристальное внимание руководства, публикуемую в гадательных форумах http://forums.oracle.com/forums/thread.jspa?threadID=633268&tstart=0

Теперь я получаю null для ответа, но проблема с параметром решена.

+0

Таким образом, ответ был не нулевым, но AccessVarcar2 не знал, как преобразовать логический ответ в varchar2. После установки типа возврата в строку он работал : sys.utl_dbws.set_return_type (l_call, string_type_qname); – Josh

0

Я не использовал этот пакет еще, но обычно в Oracle массивы пронумерованы от 1 до N. Не могли бы вы заменить строки 28-32 на:

l_input_params(1) := ANYDATA.ConvertNumber(1); 
l_input_params(2) := ANYDATA.ConvertNumber(24387236726); 
l_input_params(3) := ANYDATA.ConvertVarchar2('CTE'); 
l_input_params(4) := ANYDATA.ConvertVarchar2('STORE_RECORD_LOCATOR'); 
l_input_params(5) := ANYDATA.ConvertVarchar2('a'); 
+0

Спасибо за ответ, это на самом деле одна из вещей, которые мы но мы получаем тот же ответ, начинающийся с 0 или 1. – Josh

Смежные вопросы