Ejecutar un servicio de WCF con PL/SQL

En este articulo vamos a ver como podemos ejecutar un servicio de WCF creado con C# desde un script de PL/SQL.

Aclaremos antes de nada decir que no podemos ejecutar todos los servicios de WCF desde PL/SQL directamente – solo aquellos que se expongan a través de un binding basicHttpBinding – aunque para ser honestos no sé si es posible con wsHttpBinding. En todo caso el protocolo será siempre Http. Por supuesto siempre podemos hacer un wrapper en Java

Lo primero que necesitamos es crear nuestro servicio. Para ello creamos un nuevo proyecto en Visual Studio – el tipo de proyecto que seleccionemos debe ser WCF Service Application, nuestra idea es utilizar IIS como host para el servicio.

wcfpl1

Una vez que tenemos el proyecto borramos los archivos que crea Visual Studio por defecto y creamos nuestra propia interfaz e implementación.

La interfaz del servicio es muy sencilla, contiene un único método HacerAlgo y devuelve una instancia de la clase ServiceResult que contiene información sobre el resultado de la ejecución y un mensaje de texto.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfPLSQLSample
{    
    [ServiceContract(Namespace="http://servicessample.devjoker.com/")]
    public interface ISampleService
    {
        [OperationContract()]
        ServiceResult HacerAlgo( string inparam);
    }
    
    [DataContract()]
    public class ServiceResult
    {
        [DataMember ]
        public string Resultado;
        [DataMember]
        public string Mensaje;
    }

}

Y la implementación de la clase – también extremadamente compleja – el clásico “HolaMundo” con otro nombre.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfPLSQLSample
{    
    public class SampleService : ISampleService
    {       
        public ServiceResult HacerAlgo(string inparam)
        {
            ServiceResult resultado = new ServiceResult();
            try
            {
                resultado.Resultado = "OK";
                resultado.Mensaje = String.Format("Hola amigo {0}", inparam);
                return resultado;
            }
            catch (Exception )
            {
                resultado.Resultado = "ERROR";
                resultado.Mensaje = "Se ha producido un error";
                return resultado;
            }
        }
    }
}

El archivo .svc para hospedar el servicio en IIS.

<%@ ServiceHost Language="C#" Debug="true" 
    Service="WcfPLSQLSample.SampleService" 
    CodeBehind="SampleService.svc.cs" %>

La configuración del servicio, sin duda la parte mas delicada. Esta es la seccion system.serviceModel del web.config que hemos utilizado para el ejemplo:

<system.serviceModel>
<services>
  <service 
      behaviorConfiguration="WcfPLSQLSample.SampleServiceBehavior" 
      name="WcfPLSQLSample.SampleService">
      <endpoint 
        address="http://servicessample.devjoker.com/SampleService.svc" 
        binding="basicHttpBinding" 
        contract="WcfPLSQLSample.ISampleService">
          <identity>
              <dns value="localhost"/>
          </identity>
      </endpoint>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
    <behaviors>
        <serviceBehaviors>                
            <behavior name="WcfPLSQLSample.SampleServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

Utilizamos la configuración por defecto para un endpoint con binding basicHttpbinding. Por supuesto debemos revisar la dirección donde exponemos el servicio, ya que la URL que utilizamos - http://servicessample.devjoker.com/SampleService.svc - es un entorno de pruebas de devjoker.com y lógicamente si intentáis utilizarla no os funcionara.

Ahora es el momento de probar el probar el servicio. Personalmente cada día me gusta más SOAP UIuna herramienta muy sencilla pero muy potente de la que ya hemos hablado anteriormente. Además tiene la ventaja de estar hecha en Java con lo que no solo probamos que nuestro servicio funciona correctamente sino que además en interoperable con otras plataformas. Una petición al servicio tendría esta forma:

<soapenv:Envelope 
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
  xmlns:ser="http://servicessample.devjoker.com/">
  <soapenv:Header/>
  <soapenv:Body>
    <ser:HacerAlgo>
      <ser:inparam>devjoker.com</ser:inparam>
    </ser:HacerAlgo>
  </soapenv:Body>
</soapenv:Envelope>

Y la respuesta del servicio si todo ha ido bien:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <HacerAlgoResponse xmlns="http://servicessample.devjoker.com/">
      <HacerAlgoResult 
        xmlns:a="http://schemas.datacontract.org/2004/07/WcfPLSQLSample" 
        xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:Mensaje>Hola amigo devjoker.com</a:Mensaje>
        <a:Resultado>OK</a:Resultado>
      </HacerAlgoResult>
    </HacerAlgoResponse>
  </s:Body>
</s:Envelope>

Ahora tenemos que consumir el servicio desde un programa cliente con PL/SQL. Son requisitos previos tener una instancia de ORACLE instalada y que el exista conectividad y comunicación entre el servidor IIS y ORACLE.

El procedimiento es un poco rudimentario, ya que tendremos que construir manualmente la petición http.  Para realizar una llamada vamos a utilizar el paquete UTL_HTTP que proporciona ORACLE de forma integrada. En realidad este paquete permite realizar cualquier llamada http – a una página o cualquier servicio web – y no solo a un servicio de WCF.

Veamos el código que es que busca la mayoría de la gente :-)

DECLARE
  req         UTL_HTTP.req := NULL;
  resp_http   UTL_HTTP.resp := NULL;
  respVal CLOB;
  reqXML      VARCHAR2(32760);

BEGIN
  
  /*Generamos la petición Http */
  req := UTL_HTTP.begin_request('http://servicessample.devjoker.com/SampleService.svc', --URL DESTINO
                                'POST'); --METODO POST

  UTL_HTTP.set_body_charset('UTF-8');
  UTL_HTTP.set_body_charset(req,'UTF-8');

  /* MENSAJE SOAP  */
  reqXML := '<soapenv:Envelope 
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                xmlns:ser="http://servicessample.devjoker.com/">
       <soapenv:Header/>
       <soapenv:Body>
          <ser:HacerAlgo>
             <ser:inparam>devjoker.com:DESDE PLSQL</ser:inparam>
          </ser:HacerAlgo>
       </soapenv:Body>
    </soapenv:Envelope>';

  /*EL CONTENIDO QUE ENVIAMOS ES XML: */
  UTL_HTTP.set_header(req, 'Content-Type', 'text/xml');
  
  /*ESTABLECEMOS EL SOAPACTION A INVOCAR: */
  UTL_HTTP.set_header(req,
                      'SOAPAction',
                      'http://servicessample.devjoker.com/ISampleService/HacerAlgo');
  
  /*INDICAMOS EN EL HEADER EL TAMAÑO DEL MENSAJE ENVIADO: */
  UTL_HTTP.set_header(req, 'Content-Length', LENGTH(reqxml));
   
  /*Escrimos la solicitud */
  UTL_HTTP.write_text(req, reqxml);
 
  /*OBTENEMOS LA RESPUESTA */
  resp_http := UTL_HTTP.get_response(req);
 
  /*CARGAMOS EN LA VARIABLE RESPVAL LA DEVOLUCIÓN DEL SERVIDOR */
  UTL_HTTP.read_text(resp_http, respVal);
  /*Mostramos el resultado devuelto por el servidor */
  DBMS_OUTPUT.PUT_LINE(TO_CHAR(respVal));

  /*FINALIZAMOS LA CONEXIÓN HTTP */
  UTL_HTTP.end_response(resp_http);
 
EXCEPTION
  WHEN UTL_HTTP.end_of_body THEN
    UTL_HTTP.end_response(resp_http);
    DBMS_OUTPUT.PUT_LINE('EXCEPCION UTL_HTTP.end_of_body ');
END;

Como vemos – el código es sencillo pero artesanal – construimos el mensaje SOAP en una variable de tipo VARCHAR2 y vamos invicando a los diferentes métodos del paquete UTL_HTTP para ir construyendo la petición.

El resultado devuelve (una vez formateado es el siguiente):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <HacerAlgoResponse xmlns="http://servicessample.devjoker.com/">
      <HacerAlgoResult 
          xmlns:a="http://schemas.datacontract.org/2004/07/WcfPLSQLSample" 
          xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:Mensaje>Hola amigo devjoker.com:DESDE PL/SQL</a:Mensaje>
        <a:Resultado>OK</a:Resultado>
      </HacerAlgoResult>
    </HacerAlgoResponse>
  </s:Body>
</s:Envelope>

Eso es todo, por supuesto es un ejemplo muy sencillo pero con una aplicación practica enorme.

Agradecer a Luis  Berbel – compañero de trabajo - el código de ejemplo de PL/SQL para este ejemplo.

Saludos, y hasta la próxima (espero no tardar tanto en dar señales de vida).

DJK

Pedro  Herrarte  Sánchez
Ejecutar un servicio de WCF con PL/SQL
Pedro Herrarte Sánchez

Pedro Herrarte, es consultor independiente, ofreciendo servicios de consultoría, análisis, desarrollo y formación. Posee mas de diez años de experiencia trabajando para las principales empresas de España. Es especialista en tecnologías .NET, entornos Web (ASP.NET, ASP.NET MVC,jQuery, HTML5), bases de datos (SQL Server y ORACLE) e integración de sistemas. Es experto en desarrollo (C#, VB.Net, T-SQL, PL/SQL, , ASP, CGI , C, Pro*C, Java, Essbase, Vignette, PowerBuilder y Visual Basic ...) y bases de datos (SQL Server y ORACLE). Pedro es MCP y MAP 2012, es fundador, diseñador y programador de www.devjoker.com..
Fecha de alta:08/09/2010
Última actualizacion:08/09/2010
Visitas totales:9429
Valorar el contenido:
Últimas consultas realizadas en los foros
Últimas preguntas sin contestar en los foros de devjoker.com