WSDL (III) – wsdl:types

Esta entrada es la tercera que estoy dedicando al interesante mundo del WSDL. En esta entrada encontrarás en detalle el elemento wsdl:types, que contiene la definición de los tipos de datos que se utilizan en las operaciones del servicio web. Es muy importante definir estos tipos de datos para garantizar que la comunicación entre el cliente y el proveedor del servicio se entienden sin errores.

Descripción

Wsdl:types forma parte del objeto wsdl:definitions.

El elemento wsdl:types define directamente los tipos de datos que se utilizan en las operaciones del servicio web. Esta definición de tipos se realiza mediante Esquemas XML (XSD) que son los encargados de validar el correcto formato de los mensajes en la comunicación entre cliente y proveedor.

Gramática

La gramática del elemento wsdl:types es la siguiente (? –> es opcional, * –> pueden ser de 0 a N elementos):

<wsdl:types> ?
   <wsdl:documentation .... />?
     <xsd:schema .... />*
     <-- extensibility element --> *
</wsdl:types>

SubElementos

El elemento wsdl:documentation es opcional y muestra la información general de los tipos de datos que se definen en este apartado. 

El elemento xsd:schema define los tipos de datos haciendo uso de esquemas XML. Esta definición puede hacerse de dos maneras: 

  • Directamente en el WSDL utilizando el lenguaje XSD.
  • Importando un XSD ya existente en el WSDL.

Ejemplo de WSDL con tipos de datos incluidos implícitamente.

Este ejemplo muestra la definición del tipo de dato ConsultaDuplicidadesTratamientoNuevoPet que es la entrada (input) de la operación ConsultaDuplicidadesTratamientoNuevo que proporciona el servicio web AsistenteProductoWS. 

<xsd:schema

   xmlns:Q1=»http://VDM/esquemas/comun»

   xmlns:this=»http://VDM/esquemas/asistenteproducto»

   xmlns:xsd=»http://www.w3.org/2001/XMLSchema»

   targetNamespace=»http://VDM/esquemas/asistenteproducto»>

     

  <xsd:complexType nametipoCabecera«>

    <xsd:annotation>
    <xsd:documentation>
   Todas las peticiones que reciba el sistema universal de prescripción tendrán una cabecera    fija. Los datos de esta cabecera están en este tipo.
      </xsd:documentation>
      </xsd:annotation>
      <xsd:sequence>
      <xsd:element nameFechaHoraPet« typexsd:dateTime«>
      <xsd:annotation>
      <xsd:documentation>Fecha y hora de la petición</xsd:documentation>
      </xsd:annotation>
      </xsd:element>
      <xsd:element nameIdioma« typethis:tipoIdioma«>
      <xsd:annotation>
      <xsd:documentation>
     Idioma de la petición. Pudiendo ser los valores indicados en el tipo tipoIdioma: Euskera y Castellano.
      </xsd:documentation>
      </xsd:annotation>
      </xsd:element>
      <xsd:element nameIdTransaccion« typexsd:string«>
      <xsd:annotation>
       <xsd:documentation>
      El id de transacción es único para cada petición y generado por la aplicación cliente de la plataforma SUPRE.
       </xsd:documentation>
      </xsd:annotation>
      </xsd:element>
      </xsd:sequence>
     </xsd:complexType>

     <xsd:complexType nametipoElementoConsultaDuplicidades«>
     <xsd:annotation>
      <xsd:documentation>Información para la consulta de duplicidades</xsd:documentation>
     </xsd:annotation>
     <xsd:sequence>
     <xsd:element nameIdPrescripcion« typexsd:string«>
      <xsd:annotation>
       <xsd:documentation>Identificador de prescripción</xsd:documentation>
      </xsd:annotation>
     </xsd:element>
     <xsd:element nameIdUnicoProducto« typexsd:long«>
      <xsd:annotation>
       <xsd:documentation>Identificador único de producto de la prescripción</xsd:documentation>
      </xsd:annotation>
     </xsd:element>
     </xsd:sequence>
     </xsd:complexType>

     <xsd:complexType name=»tipoConsultaDuplicidadesTratamientoNuevoPet»>

       <xsd:annotation>

          <xsd:documentation>Información de la petición</xsd:documentation>

       </xsd:annotation>

       <xsd:sequence>

          <xsd:element name=»Cabecera» type=»this:tipoCabecera»>

             <xsd:annotation>

               <xsd:documentation>Información de la cabecera</xsd:documentation>

             </xsd:annotation>

          </xsd:element>

          <xsd:element name=»TratamientoNuevo» type=»this:tipoElementoConsultaDuplicidades»>

            <xsd:annotation>

              <xsd:documentation>

              Datos del tratamiento nuevo para comprobar su duplicidad

              </xsd:documentation>

            </xsd:annotation>

          </xsd:element>

          <xsd:element 

              maxOccurs=»unbounded» 

              name=»TratamientosComparacion» 

              type=»this:tipoElementoConsultaDuplicidades»>

             <xsd:annotation>

               <xsd:documentation>

                 Lista de datos de tratamiento que ya tenía el paciente para comprobar su duplicidad

               </xsd:documentation>

             </xsd:annotation>

          </xsd:element>

       </xsd:sequence>

     </xsd:complexType>


     <xsd:element 

         name=»ConsultaDuplicidadesTratamientoNuevoPet»

         type=»this:tipoConsultaDuplicidadesTratamientoNuevoPet»>

        <xsd:annotation>

           <xsd:documentation>Consulta de duplicidades que permite comprobar si un Principio Activo ATC no está duplicado en otros con el resto de prescripciones ya creadas. La respuesta esperada es una lista de pares del Tratamiento Nuevo con alguno de los tratamientos que ya tenía el paciente

           </xsd:documentation>

        </xsd:annotation>

     </xsd:element>

</xsd:schema>

 

El elemento base que define el tipo de dato ConsultaDuplicidadesTratamientoNuevoPet está definido en verde.

<xsd:element 
     name="ConsultaDuplicidadesTratamientoNuevoPet"
     type="this:tipoConsultaDuplicidadesTratamientoNuevoPet"
</xsd:element>

 

Entre sus atributos destacan el nombre del tipo de dato y el tipo, que en este caso es un tipo de dato complejo definido en el elemento tipoConsultaDuplicidadesTratamientoNuevoPet de wsdl:types. Este elemento, tal y como indica el prefijo this, se tiene que encontrar en este mismo fichero. Si nos fijamos en los namespaces incluidos en el elemento xsd:schema veremos que hace referencia a sí mismo http://VDM/esquemas/asistenteproduto

xsd:schema
   targetNamespace="http://VDM/esquemas/asistenteproducto"
   xmlns:Q1="http://VDM/esquemas/comun"
   xmlns:this="http://VDM/esquemas/asistenteproducto"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"   

 

El objeto tipoConsultaDuplicidadesTratamientoNuevoPet está definido por una secuencia de tres elementos, una cabecera, un tratamiento nuevo y una lista de tratamientos de comparación. 

<xsd:complexType name="tipoConsultaDuplicidadesTratamientoNuevoPet">
  <xsd:sequence>
    <xsd:element name="Cabecera" type="this:tipoCabecera">
    <xsd:element name="TratamientoNuevo" type="this:tipoElementoConsultaDuplicidades">
    <xsd:element 
       maxOccurs="unbounded" 
       name="TratamientosComparacion
       type="this:tipoElementoConsultaDuplicidades">
  </xsd:sequence>
</xsd:complexType>


El elemento Cabecera es un elemento complejo definido en un objeto this.tipoCabecera que está definido en el propio WSDL. El elemento TratamientoNuevo es un elemento complejo definido en el objeto this.tipoElementoConsultaDuplicidades también definido en el propio WSDL. El elemento TratamientosComparacion es un elemento complejo definido por el mismo objeto que TratamientoNuevo, sólo que esta vez se repite ilimitadamente (maxOccurs=»unbounded»). 

Si un elemento no tiene definido el atributo maxOccurs por defecto tomará el valor «1«. El valor «unbounded» indica que el elemento puede repetirse de forma ilimitada.

La definición de los elementos tipoCabecera y tipoElementoConsultaDuplicidades se encuentran también en el elemento wsdl:types. En el ejemplo se muestran en azul. Estos objetos complejos están definidos por elementos primitivos. Por ejemplo, el tipo complejo tipoElementoConsultaDuplicidades está formado por dos tipos primitivos, IdPrescripcion que es un xsd:string y IdUnicoProducto que es un xsd:long.  

     <xsd:complexType name="tipoElementoConsultaDuplicidades">
     <xsd:sequence>
     <xsd:element nameIdPrescripcion« typexsd:string«>
   <xsd:element nameIdUnicoProducto« typexsd:long«>
  </xsd:sequence>
     </xsd:complexType>

Los tipos primitivos válidos se pueden encontrar en el apartado datatypes de la especificación Schema XML. 

Ejemplo de WSDL con tipos de datos importados.

Importar el tipo de datos aporta sencillez al diseño del WSDL facilitando la identificación a primera vista de los tipos de datos. Si se quiere profundizar en los mismos se podrá acceder a través de la URI de schemaLocation al detalle del tipo de dato que está definido en su correspondiente XSD.

En el siguiente ejemplo se define el tipo de dato ConsultaDuplicidadesTratamientoNuevoPet pero utilizando ésta vez un fichero xsd. 

<wsdl:types>
  <xsd:schema 
     xmlns:asp="http://VDM/esquemas/asistenteproducto"
     xmlns:ns1="http://cxf.apache.org/bindings/xformat"       
     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
     xmlns:tns="http://VDM/wsdls/AsistenteProductoWSDL" 
     xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"     
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     elementFormDefault="unqualified" 
     targetNamespace="http://VDM/wsdls/AsistenteProductoWSDL" 
     version="1.0">
   
   <xsd:import 
                      xsd=xsd/ConsultaDuplicidadesTratamientoNuevoPet.xsd«/>
 </xs:schema>
</wsdl:types>

Claramente se ve que el diseño del WSDL es mucho más sencillo que en el ejemplo anterior. Sin embargo, si queremos ver el detalle de la información se hace necesario navegar a la URI del atributo schemaLocation y acceder al XSD.

Este XSD contendrá un código similar al del ejemplo anterior, pudiendo tener a su vez importaciones a otros XSDs que especifiquen los objetos complejos tipoCabecera y tipoElementoConsultaDuplicidades que podrían estar definidos en sus propios XSDs.

Ejemplo de generación de objeto de entrada a partir de los wsdl:types de ejemplo anteriores.

Si generamos el cliente para cualquiera de las operaciones del servicio web obtendremos un código similar al siguiente: 

<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:asis="http://VDM/esquemas/asistenteproducto">
   <soapenv:Header/>
   <soapenv:Body>
      <asis:ConsultaDuplicidadesTratamientoNuevoPet>
         <Cabecera>
             <FechaHoraPet>?</FechaHoraPet>
             <Idioma>?</Idioma>
             <IdTransaccion>?</IdTransaccion>
         </Cabecera>
         <TratamientoNuevo>
             <IdPrescripcion>?</IdPrescripcion>
             <IdUnicoProducto>?</IdUnicoProducto>
         </TratamientoNuevo>
         <!--1 or more repetitions:-->
         <TratamientosComparacion>
             <IdPrescripcion>?</IdPrescripcion>
             <IdUnicoProducto>?</IdUnicoProducto>
         </TratamientosComparacion>
      </asis:ConsultaDuplicidadesTratamientoNuevoPet>
   </soapenv:Body>
</soapenv:Envelope>

Conclusión

El apartado wsdl:types es uno de los más importantes en la descripción del Web Service ya que permite generar una correcta comunicación entre proveedor y cliente. 

Esta claro que hay que encontrar un equilibrio en la definición de los tipos de datos a través de XSDs. Si hay pocos XSDs, nos encontraremos con un fichero inmenso difícil de manejar, y si por el contrario, definimos demasiados XSDs, tendremos que navegar por todos ellos para enterarnos de los datos que participan en el servicio web, y si no disponemos de un buen mapa de objetos podemos perder la visión de lo datos. 

Links