WSO2 DSS no soporta datos complejos como IN de datos al ejecutar un Procedure.
Necesitabamos una forma de poder hacerlo y esta es la que mas se adecuo a nuestras necesidades.
La solucion consiste en convertir los datos complejos a CLOB y utilizar la funcionalidad de convertir Objetos a XML y viceversa que provee Oracle DB.
Como ejemplo vamos a crear lo necesario para poder dar de alta un cliente a traves de un procedure que tiene datos complejos.
1) Oracle DB
Datos del cliente.
create or replace TYPE o_client AS OBJECT (
id NUMBER(10),
firstname VARCHAR2(30),
lastname VARCHAR2(30)
);
/
Tabla para soportar alta de muchos clientes
create or replace TYPE t_client AS TABLE OF o_client;
/
Objecto necesario para soportar la conversion de Objeto a XML para la Collection
create or replace TYPE c_client AS OBJECT ( collection t_client);
/
Respuesta del Procedimiento
create or replace TYPE o_client_r AS OBJECT (result VARCHAR2(30));
/
Package y Procedures
Tenemos el procedure insert_client que es el que recibe y devuelve los datos complejos.
Para hacer que los datos complejos se puedan usar en formato simple los convertimos a CLOB utilizando el procedure insert_client_dss.
create or replace package clients as
procedure insert_client(request t_client,response out o_client_r);
procedure insert_client_dss(request clob,response out clob);
function trim_cdata(cdata in clob) return clob;
end clients;
/
create or replace package body clients as
procedure insert_client(request t_client,response out o_client_r) as
begin
response := o_client_r('OK');
end insert_client;
procedure insert_client_dss(request clob,response out clob) as
v_c_client c_client;
v_o_client_r o_client_r;
cxml xmltype;
begin
if request is not null then
cxml := xmltype(clients.trim_cdata(request));
cxml.toObject(v_c_client);
end if;
clients.insert_client(v_c_client.collection, v_o_client_r);
if v_o_client_r is not null then
response := xmltype(v_o_client_r).getstringval();
end if;
end insert_client_dss;
function trim_cdata(cdata in clob) return clob as
rdata clob;
begin
rdata := replace(cdata,'<![CDATA[','');
rdata := replace(rdata,']]>','');
return rdata;
end;
end clients;
/
Codigo para ver como necesitamos armar el XML a enviar.
declare
t_1 t_client;
o_1 o_client;
c_1 c_client;
v_xml XMLTYPE;
BEGIN
t_1 := t_client();
t_1.extend(2);
o_1 := o_client(1,'Juan Pablo','Vadell');
t_1(1) := o_1;
o_1 := o_client(2,'Cesar','Trono');
t_1(2) := o_1;
c_1 := c_client(t_1);
v_xml:=XMLTYPE(c_1);
DBMS_OUTPUT.put_line('<![CDATA[' || v_xml.getstringval || ']]>');
end;
2) WSO2 DSS
Creacion del Servicio en DSS
Fuente:
<data name="ClientsService" transports="http https local">
<config enableOData="false" id="VATROX">
<property name="carbon_datasource_name">LOCAL_VATROX</property>
</config>
<query id="ClientsInsert" useConfig="VATROX">
<sql>call CLIENTS.INSERT_CLIENT_DSS(:request,:response)</sql>
<result element="Response" rowName="">
<element column="response" name="response" xsdType="string"/>
</result>
<param name="request" sqlType="CLOB"/>
<param name="response" sqlType="CLOB" type="OUT"/>
</query>
<operation name="insertClient">
<call-query href="ClientsInsert">
<with-param name="request" query-param="request"/>
</call-query>
</operation>
</data>
Paso a paso.
Ejemplo de ejecucion.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://ws.wso2.org/dataservice">
<soapenv:Header/>
<soapenv:Body>
<dat:insertClient>
<dat:request><![CDATA[<C_CLIENT><COLLECTION><O_CLIENT><ID>1</ID><FIRSTNAME>Juan Pablo</FIRSTNAME><LASTNAME>Vadell</LASTNAME></O_CLIENT><O_CLIENT><ID>2</ID><FIRSTNAME>Cesar</FIRSTNAME><LASTNAME>Trono</LASTNAME></O_CLIENT></COLLECTION></C_CLIENT>]]></dat:request>
</dat:insertClient>
</soapenv:Body>
</soapenv:Envelope>
Respuesta:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<Response xmlns="http://ws.wso2.org/dataservice">
<response><O_CLIENT_R><RESULT>OK</RESULT></O_CLIENT_R></response>
</Response>
</soapenv:Body>
</soapenv:Envelope>