2009-07-27 10 views
2

Contexte: Nous avons un Webservice qui s'exécute sous axis2 sur un Tomcat. Nous aimerions que notre base de données Oracle (10g Enterprise Edition version 10.2.0.1.0) appelle notre Webservice lorsqu'une nouvelle ligne est entrée dans l'une de nos tables. Nous avons découvert que nous pouvons utiliser un déclencheur pour appeler un JSP (Java Stored Procedure) ou nous PL/SQL et l'utilitaire UTL_DBWS. Aucun ne travaille pour nous cependant. Consommer le service Web à partir d'une classe Java autonome à l'aide de l'implémentation de l'axe javax.xml.rpc ou de l'implémentation d'Oracle fonctionne en dehors de la base de données.Webservice consommateur utilisant UTL_DBWS

UTL_DBWS tentative:

contenu décompressés de dbws-callout-utility-10131.zip à C: \ oracle \ product \ 10.2.0 \ db_5 \ sqlj \ lib qui a été tiré vers le bas de http://www.oracle.com/technology/sample_code/tech/java/jsp/dbwebservices.html

a couru loadjava commande

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 

Ajout d'un groupe d'autorisations

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', ''); 

Notre 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; 

Lorsque nous exécutons:

select wsproxy_send_request from dual; 

nous obtenons:

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 

(position 37 est l'appel Invoke)

+0

Remarqué cette question après avoir demandé http://stackoverflow.com/questions/37586/consuming-web-services-from-oracle-pl-sql Nous pouvons essayer le UTL_HTTP et voir si cela fonctionne. – Josh

+0

J'ai trouvé que si je supprime tous les paramètres sauf le premier, qui est un appel invalide pour notre webservice, je reçois une autre exception ORA-29532: Java appel terminé par uncaught Java exception: javax.xml. rpc.soap.SOAPFaultException: inconnu ORA-06512: à "SYS.UTL_DBWS", ligne 388 ORA-06512: à "SYS.UTL_DBWS", ligne 385 ORA-06512: à "WSPROXY.WSPROXY_SEND_REQUEST ", ligne 41 mais ce qui est génial, c'est que cela est généré parce que Axis reçoit la demande et rechigne parce qu'il ne contient pas les bons paramètres – Josh

Répondre

2

L'astuce est d'ajouter les types de paramètres/noms ... Je n'ai pas trouvé la méthode UTL_DBWS.add_parameter documenté nulle part, mais je aurais dû le deviner son existence puisque vous devez faire la même chose dans un java la mise en oeuvre.

Quoi qu'il en soit voici ce que j'ai ajouté

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'); 

Donc, la chose est maintenant:

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; 
/

je vis enfin ce après avoir payé une plus grande attention au guide posté dans les forums oracle http://forums.oracle.com/forums/thread.jspa?threadID=633268&tstart=0

Je reçois la valeur null pour ma réponse maintenant, mais le problème de paramètre a été résolu.

+0

Donc la réponse n'était pas nulle mais AccessVarcar2 ne savait pas comment convertir la réponse booléenne en varchar2. : sys.utl_dbws.set_return_type (l_call, string_type_qname); – Josh

0

Je n'ai pas utilisé ce paquet encore mais généralement dans Oracle les tableaux sont numérotés de 1 à N. Pourriez-vous remplacer les lignes 28-32 avec:

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

Merci pour la réponse, c'est en fait l'une des choses que nous Nous avons aussi la même réponse en commençant par 0 ou 1. – Josh