使用UTL_DBWS使用Webservice

时间:2009-07-27 17:11:29

标签: oracle web-services plsql

背景: 我们有一个在Tomcat上运行在axis2下的Web服务。我们希望我们的Oracle(10g企业版10.2.0.1.0版)数据库在我们的一个表中输入新行时调用我们的Web服务。我们发现我们可以使用触发器来调用Java存储过程(JSP)或我们的PL / SQL和UTL_DBWS实用程序。但是,两者都没有为我们工作。使用轴javax.xml.rpc实现或oracle实现从独立的java类中使用web服务确实可以在db之外工作。

UTL_DBWS尝试:

将dbws-callout-utility-10131.zip的内容解压缩到C:\ oracle \ product \ 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是调用调用)

2 个答案:

答案 0 :(得分: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;
/

我在密切关注oracle论坛上发布的指南后终于看到了这一点 http://forums.oracle.com/forums/thread.jspa?threadID=633268&tstart=0

我现在的响应为空,但参数问题已经解决。

答案 1 :(得分: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');