Comprender las especificaciones de servicios web, Parte 3: Interfaz de Descripción, Localización e Integración Universal (UDDI)

El énfasis actual en las Arquitecturas Orientadas a Servicios (SOA) se ha enfocado en los servicios web, pero es fácil perderse entre toda la información disponible. Esta serie le brinda la historia correcta acerca de las especificaciones sobre los principales servicios web, comenzando con el Protocolo Simple de Acceso a Objetos (SOAP) hasta el Lenguaje de Ejecución de Procesos de Negocios para servicios web (WS-BPEL). Este tutorial, la Parte 3 de la serie, explica los conceptos básicos acerca de la Interfaz de Descripción, Localización e Integración Universal y cómo acceder a ésta usando una aplicación Java.

Nicholas Chase, Freelance writer, Backstop Media

Nicholas Chase participó en el desarrollo de sitios Web para empresas como Lucent Technologies, Sun Microsystems, Oracle y Tampa Bay Buccaneers. Nick fue profesor de física en escuela secundaria, gerente de instalaciones para tratamiento de desechos con bajo nivel de radioactividad, editor de una revista online de ciencia ficción, ingeniero multimedios, instructor de Oracle y Director de Tecnología en una empresa de comunicaciones interactivas. Es autor de varios libros, entre ellos XML Primer Plus (Sams).



08-08-2011

Antes de comenzar

Este tutorial explica la Interfaz de Descripción, Localización e Integración Universal, o UDDI. La misma especifica un registro de los servicios web y otra información corporativa y su intención es brindar una forma de descubrir nuevos servicios web a utilizar, y, bajo circunstancias ideales, poder automatizar su uso.

Este tutorial parte de la base de que usted se encuentra familiarizado con los conceptos generales acerca de los servicios web y de SOAP. También le resultará de ayuda contar con conocimientos acerca de WSDL, no obstante, el tutorial realiza un repaso de sus conceptos generales.

Para avanzar con el código contenido en la última sección, debería estar familiarizado con Java, pero los conceptos, al igual que el resto del tutorial, se aplican al lenguaje de programación.

Acerca de esta serie

Este tutorial enseña los conceptos básicos acerca de los servicios web siguiendo las hazañas del periódico imaginario, The Daily Moon, a medida que el personal utilice los servicios web para crear un sistema de flujo de trabajo que incremente la productividad en el medio de tanto cambio.

La Parte 1 explica las conceptos básicos subyacentes a los servicios web y demuestra el uso de SOAP, la especificación que subyace la mayoría de lo que está por venir, al conectar el área de clasificados con el Sistema de Gestión de Contenidos (Content Management System).

La Parte 2 va un paso más allá y explica el modo de utilizar el Lenguaje de Descripción de servicios web (WSDL) para definir los mensajes producidos esperados por el servicio web, permitiéndole al equipo crear servicios de una manera más sencilla y los clientes que se conectarán a ellos.

La Parte 3 encuentra al equipo con una cantidad de servicios en el lugar y el deseo de ubicarlos fácilmente. Como respuesta, UDDI brinda un registro que permite realizar búsquedas de los servicios disponibles de una manera que permite dar a conocer sus servicios propios a otros.

Las Partes 4 y 5, WS-Security y WS-Policy, permiten que los equipos encuentren una meta para asegurar los servicios del periódico y los cambios que los equipos necesitan realizar para acceder a aquellos servicios recientemente asegurados.

Interoperabilidad es la palabra clave de la Parte 6, dado que los servicios obtenidos a partir de las distintas implementaciones deben accederse desde un sistema único. La Parte seis contiene los requisitos y las pruebas comprendidas en la certificación WS-I.

Finalmente, la Parte 7 muestra cómo utilizar el Lenguaje de Ejecución de Procesos de Negocios para servicios web (WS-BPEL) para crear aplicaciones complejas a partir de servicios individuales.

Entonces, démosle una mirada un poco más detallada a los temas comprendidos en este tutorial

Acerca de este tutorial

La Parte 1 de esta serie le brindó una introducción acerca de los servicios web y enfatizó la importancia de SOAP. Lo hicimos a través de las hazañas de un departamento de Clasificados del periódico imaginario Daily Moon. En la Parte 2 de esta serie, el Departamento de Avisos Clasificados decidió crear un servicio web propio, documentando su uso con el Lenguaje de Descripción de servicios web (WSDL). En esta Parte 3, el editor de este periódico ha decidido que vaya todo a través de los servicios web y ha ordenado el uso de un registro UDDI para llevar un registro de todos los servicios disponibles.

En el transcurso de este tutorial, usted aprenderá lo siguiente:

  • De qué se trata UDDI
  • Para qué se usa UDDI
  • La estructura de datos de UDDI
  • Cómo representar efectivamente el WSDL utilizando la UDDI
  • Las operaciones que se pueden realizar sobre los datos de UDDI
  • Las interacciones que puede realizar con un registro UDDI utilizando Java

Requisitos previos

Para poder continuar con el código correspondiente a este tutorial necesitará disponer del siguiente software:

Apache Geronimo u otra implementación UDDI. Para poder seguir con el código necesitará acceder a un registro UDDI. A tal fin, no es importante saber qué tipo de registro utiliza, dado que UDDI es fundamentalmente un servicio web y se debería poder acceder al mismo desde cualquier plataforma o lenguaje a cualquier plataforma o lenguaje. Dicho esto, el servidor de la aplicación Apache Geronimo, que constituye también la base de WebSphere Community Edition de IBM, y que hemos estado utilizando en las Partes 1 y 2 de esta serie, posee la implementación del registro UDDI de Apache, jUDDI, preinstalada y configurada como parte de una instalación estándar. Puede descargar la aplicación Apache Geronimo desde Apache.org. Para obtener mayor información acerca de la instalación de Geronimo, consulte Parte 1 de esta serie.

UDDI4J – Para acceder al registro, el presente tutorial demuestra el uso del proyecto UDDI4J, el cual brinda una importante integración entre los conceptos de UDDI y el código de Java. Puede descargar UDDI4J de Sourceforge.net.

Apache Axis2 u otra implementación SOAP – Puede crear mensajes de SOAP a mano y puede interpretarlos a mano, pero resulta más sencillo contar con una implementación a mano. Utilizará el Apache Axis2, el cual contiene las implementaciones de varias API relacionadas con SOAP para simplificarle la vida en gran medida. Puede descargar Apache Axis2 desde Apache.org. Este tutorial utiliza la versión 0.94, pero pueden funcionar versiones posteriores también.

Java 2 Standard Edition versión 1.4.x—Todas estas herramientas se basan en Java, como los servicios y clientes que construirá en este tutorial. Puede descargar J2SE SDK Desde la Red de Desarrolladores de Sun. Geronimo no funcionará correctamente con Java 1.5.

También necesitará un navegador Web y un editor de texto, pero estoy seguro de que ya los tiene. Si lo desea, puede también utilizar un Entorno de Desarrollo Integrado, tal como Eclipse, pero dado que nos concentramos en las tecnologías en lugar de las herramientas, estaremos utilizando simplemente un editor de textos y la línea de comandos para editar nuestros archivos y compilarlos.


Generalidades

Miremos entonces a dónde nos encontramos hasta ahora.

La historia hasta ahora es la siguiente

Esta serie va tras el personal del periódico imaginario Daily Moon A medida que moviliza varias de las operaciones cotidianas a un sistema basado en servicios web. En la Parte 1, el Departamento de Clasificados aprendió acerca del SOAP mediante la interacción con el Sistema de Gestión de Contenidos, en la Parte 2, crearon su propio servicio, y lo definieron utilizando el Lenguaje de Descripción de servicios web (WSDL). Ahora, Rudy, el editor del periódico, está tan impresionado con el modo en que funcionan los servicios web dentro de la organización que desea que se los utilice más seguido, hasta el grado de interactuar con otras organizaciones.

Con esa finalidad, les solicita a dos miembros de su equipo de IT, Gene y Francis, que creen un registro de los servicios web, que espera que les permita a los demás departamentos que puedan encontrar con mayor facilidad lo que necesitan para migrar sus propias operaciones a los servicios web.

Ambos deciden que la mejor manera de hacerlo será implementando un registro de la Interfaz de Descripción, Localización e Integración Universal (UDDI), que les permitirá, no solamente almacenar información sobre los servicios propios del periódico, sino también interactuar con registros de otros periódicos.

Actualizador de WSDL

Parte del proceso de registro de un servicio con un registro UDDI implica la manipulación de la definición del WSDL, entonces, antes de pasar al proyecto nuevo, Gene revisa los conceptos básicos acerca de WSDL volviendo a los archivos creados en su último proyecto. Consulte el Listado 1.

Listado 1. Archivo WSDL
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:tns="http://www.daily-moon.com/classifieds"
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://www.daily-moon.com/classifieds">

<wsdl:types>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">

    <xs:element name="createNewAdRequest">
      <xs:complexType>

        <xs:sequence>
          <xs:element type="xs:string" name="content" />
          <xs:element type="xs:string" name="endDate" />
        </xs:sequence>
      </xs:complexType>
    </xs:element>

    <xs:element name="createNewAdResponse">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:int" name="newAdId" />
        </xs:sequence>
      </xs:complexType>

    </xs:element>
...
  </xs:schema>

</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
  <wsdl:part name="part1" element="ns1:createNewAdRequest" />
</wsdl:message>

<wsdl:message name="createNewAdResponseMessage">
  <wsdl:part name="part1" element="ns1:createNewAdResponse" />
</wsdl:message>

<wsdl:message name="getExistingAdsResponseMessage">
...
</wsdl:message>

<wsdl:portType name="ClassifiedServicePortType">

  <wsdl:operation name="createNewAd">
    <wsdl:input message="tns:createNewAdRequestMessage" />
    <wsdl:output message="tns:createNewAdResponseMessage" />
  </wsdl:operation>

  <wsdl:operation name="finalizeIssue">...</wsdl:operation>

  <wsdl:operation name="editExistingAd">...</wsdl:operation>
  <wsdl:operation name="getExistingAds">...</wsdl:operation>

</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding" 
              type="tns:ClassifiedServicePortType">

  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
                style="document" />

  <wsdl:operation name="createNewAd">
    <soap:operation soapAction="createNewAd" style="document" />
    <wsdl:input>
      <soap:body use="literal" 
                 namespace="http://ws.apache.org/axis2" />
    </wsdl:input>

    <wsdl:output>
      <soap:body use="literal" 
                 namespace="http://ws.apache.org/axis2" />
    </wsdl:output>
  </wsdl:operation>

  <wsdl:operation name="finalizeIssue">...</wsdl:operation>

  <wsdl:operation name="editExistingAd">...</wsdl:operation>
  <wsdl:operation name="getExistingAds">...</wsdl:operation>

</wsdl:binding>

<wsdl:service name="ClassifiedService">
  <wsdl:port name="ClassifiedServicePort" 
             binding="tns:ClassifiedServiceBinding">

    <soap:address location=
"http://www.daily-moon.com:8080/axis2/services/ClassifiedService" />
  </wsdl:port>
</wsdl:service>

</wsdl:definitions>

Hemos eliminado algunas partes de este documento, por razones de espacio, pero repasemos los conceptos generales.

Comenzando por abajo, tenemos el servicio real, el cual está disponible en una ubicación específica e implementa la ClassifiedServiceBinding. Esa interfaz se representa como un enlace, ya que especifica operaciones definidas en el tipo de puerto ClassifiedServicePortType. El portType define los mensajes de entrada y salida utilizando los elementos definidos en la sección correspondiente a los tipos.

Un cliente XML puede leer esta información y utilizarla para acceder al servicio web. (O más precisamente, una herramienta de generación de clientes de servicios web puede leer esta información y generar un cliente que pueda acceder al servicio web.)

A dónde vamos desde aquí

En el transcurso de este tutorial, Gene y Francis desglosarán la información del periódico Daily Moon's En estructuras amigables para la UDDI, inclusive la información comercial y acerca de los servicios. La utilizarán para ingresar la información y los servicios del periódico al registro de la UDDI utilizando UDDI4J. También trabajarán con el registro privado de otro periódico, el Daily Star, para encontrar un servicio que proporcione las puntuaciones de los deportes en curso.

Ahora veamos de qué se trata UDDI.


Presentación de UDDI

UDDI es básicamente un servicio web, pero es tan diferente a SOAP o a WSDL que resulta apropiado comprender un poco más acerca de sus antecedentes antes de comenzar.

¿Por qué UDDI?

Cuando todas las aplicaciones son locales, es muy sencillo encontrar lo que desea. Sin embargo, cuando posee un sistema distribuido, tal como el de servicios web, no posee el beneficio que brinda un repositorio centralizado. Los sistemas distribuidos también son propensos al cambio. Este es el mundo en el que se creó UDDI. Se creó con dos finalidades. En su encarnación inicial, fue concebida como una clase de “Registro Universal de Empresas”. La idea era que las empresas podrían buscar socios utilizando uno de los tres métodos que se describen a continuación:

  • "Páginas blancas": Las páginas blancas eran como las páginas blancas de una guía telefónica, en las que uno puede buscar información acerca de la empresa. Por ejemplo, si usted conocía el nombre de la empresa, podría encontrar su ubicación, cómo contactarla, y más aún, a quién contactar dentro de esa organización.
  • "Páginas amarillas": Las páginas amarillas, otra vez, eran como las páginas amarillas de la guía telefónica, en las que se pueden buscar empresas en función de una clasificación. UDDI especificó varias taxonomías que las empresas podrían utilizar para clasificarse a sí mismas. Por ejemplo, si se buscaban artículos deportivos, podría buscar empresas con el código 339920 del Sistema de Clasificación de Industrias de Norteamérica (NAICS).
  • "Páginas verdes": No, no existen páginas verdes en su guía telefónica, pero la idea era que las empresas pudieran utilizar este método de búsqueda para encontrar socios comerciales que habían implementado un servicio en particular. Por ejemplo, puede realizar una búsqueda de empresas mediante un tipo de búsqueda que calcula la distancia utilizando los códigos postales.

UDDI fue también concebida como un modo de mantener la ejecución de aplicaciones distribuidas a largo plazo. La idea era que se podría copiar en caché la información acerca de cómo accederá a un servicio en particular, y si su cliente iba a la quiebra, la aplicación iría automáticamente nuevamente hacia el registro y verificaría si se había cambiado la información. De haber cambiado, podría simplemente realizar los cambios en su aplicación (automáticamente, en un mundo ideal) y reintentar su solicitud.

UDDI en el mundo real

Cuando Francis fue en busca del Registro Universal de Empresas (UBR, por sus siglas en inglés), descubrió que ya no existía. De hecho, el UBR había sido discontinuado por sus auspiciantes corporativos cuando salió la versión 3.0 de UDDI. ¿Por qué motivo? Bien, no importaba en qué medida era buena la idea del UBR, la realidad era que casi nadie lo utilizaba. El motivo tenía dos explicaciones; en primer lugar, había muy poca información útil en el UBR -- salvo, es decir, que esté buscando un servicio de cotización del valor de las acciones, en cuyo caso podría encontrarlos en abundancia. La segunda razón es que las empresas, como norma, no realizan negocios con organizaciones con las que no están familiarizadas. Muy pocas organizaciones, de haberlas, van a realizar una búsqueda automatizada de socios comerciales y luego abrirles sus sistemas sin aplicar la debida diligencia. Entonces la búsqueda automatizada y el modelo de invocación no despegaron realmente.

Se vio también obstaculizado por el hecho de que de alguna manera UDDI estaba adelantada a su época. Diseñada para manejar todo tipo de servicios y no solamente SOAP sobre HTTP, no se prestó inmediatamente al uso de las definiciones de WSDL, al menos en vistas de aquellos que trataban de utilizarla.

No resulta sencillo de decir, sin embargo, que UDDI no se está utilizando para nada. En su lugar, se la está utilizando como un “registro privado”. Las empresas crean sus propios registros e ingresan sus propios servicios. Se puede utilizar también UDDI y es un tipo de registro empresarial interno, tal como lo ha utilizado tradicionalmente el LDAP.

Más aún, a medida que pasamos de un modo de pensamiento de "servicios web únicamente" a una mentalidad más relacionada con la Arquitectura Orientada a los Servicios (SOA), esta capacidad de manejar más que solamente el SOAP podrá comprobarse a largo plazo.

La estructura de datos de UDDI

La información contenida en un registro UDDI contiene cinco tipos diferentes:

  • businessEntity, o la organización corporativa real. Esto puede significar una organización global o puede ser una filial o subdivisión.
  • publisherAssertion, o la relación entre varias businessEntities. publisherAssertions deben ser reclamadas por ambas partes para ser válidas (por lo cual no se puede reclamar que se trata de una subdivisión de otra empresa) a menos que ambas entidades sean responsables ante el editor o excepto que ambas partes ingresen al registro por la misma cuenta de usuario.
  • bindingTemplate, el cual es esencialmente la especificación de una interfaz del servicio. Puede ser implementado por múltiples businessServices.
  • businessService, o un servicio provisto por un negocio. Entonces, puede parecer simple, pero en el mundo de UDDI no significa necesariamente que se trata de un servicio web. Por ejemplo, se puede especificar el servicio de soporte telefónico de su empresa (lo cual significa el número telefónico real que marca el usuario y todo lo que ello conlleva) como un servicio UDDI. Por supuesto, no se obtendría un documento WSDL ficticio, pero constituiría un servicio que brinda su empresa.
  • tModels, o modelos de metadatos. Al investigar la UDDI, Francis llega a la conclusión de que el tModel constituye quizás el motivo principal por el que no comenzó a tener éxito, tal como se esperaba. Como registro de servicios, usted esperaría encontrar una manera directa de especificar la interfaz de un servicio, tal como lo hace WSDL. Pero, tal como se especifica, no era la intención que UDDI se relacione exclusivamente con servicios web, y fue designado con mucha más flexibilidad. tModels un punto de ayuda para los documentos XML, tal como lo veremos más tarde, pero de hecho, tienen como finalidad especificar información acerca de algo vía un servicio, negocio o algo más.

Esas son las estructuras básicas de datos de UDDI. Ahora veamos las formas en que UDDI dice que podemos interactuar con ellos.

La API de UDDI

UDDI posee la reputación de ser extremadamente compleja, pero en esencia está conformada por los cinco tipos de datos detallados anteriormente, combinados con cuatro operaciones: Find (Encontrar), Get (Tomar), Save (Guardar), y Delete (Borrar). En otras palabras, las notas de especificación de UDDI establecen que se puede realizar lo siguiente con los datos:

  • find_xx: Estos métodos, tales como find_businessEntity, find_businessService, etc., brindan una manera de poder buscar un registro en el registro de UDDI. Estos métodos devuelven la clave que identifica al objeto.
  • get_xx: Una vez que posee la clave única para identificar un objeto, puede utilizar get_xx methods, tal como get_businessService etc., para recuperar el propio objeto real. Por ejemplo, get_businessService permite visualizar todo el objeto businessService, desde el cual puede obtener la información que necesita.
  • save_xx: Tal como seguramente ha podido ya adivinar, estos métodos agregan información a la base de datos o alteran información que ya se encuentra en la base de datos.
  • delete_xx: Estos métodos, tales como delete_bindingTemplate, delete_tModel, etc., toman la clave única del objeto como parámetro y la sacan de la base de datos. El comportamiento real de estos métodos depende de lo que está eliminando. Por ejemplo, dado que tModels son frecuentemente referentes de otros objetos de la base de datos, no pueden ser eliminados; en lugar de ellos se los oculta.

Virtualmente toda la UDDI descansa en las 20 intersecciones de estos cinco objetos (businessService, bindingTemplate, publisherAssertion, businessEntity, y tModel) y cuatro acciones (find, get, save, y delete).

Veamos ahora cómo aparece realmente la estructura.


Estructura de datos de UDDI

Para comenzar el proceso de agregar la empresa a un registro UDDI, Francis definió la información a ingresar al registro.

businessEntity

El primer paso es ingresar el propio periódico al registro. Para hacerlo Francis crea un objeto businessEntity Este objeto contiene información acerca de la empresa, tanto para identificarla como para brindar información acerca de la misma. Por ejemplo, el objeto businessEntity incluye uno o más nombres, (lo que le permite, por ejemplo, crear un elemento de nombres para cada lenguaje en el que se representa la empresa), información de contacto (se le dice a Francis que agregue a Pat Mooney como principal contacto), los servicios asociados con la entidad (lo que Gene hará más tarde) y la información para identificar y categorizar la empresa.

A pesar de que la mayoría de la gente nunca va a interactuar con el Registro UDDI de esta manera, el hecho es que UDDI constituye esencialmente una aplicación SOAP; todas las operaciones que ejecute suceden como resultado de los mensajes de SOAP que se intercambian. Lo que significa que es que la businessEntity que está creando Francis se representa en última instancia como un elemento XML. Consulte el Listado 2.

Listado 2. El elemento businessEntity
<businessEntity businessKey="{uuid}"<businessEntity businessKey="{uuid}" operator="(optional)" 
authorizedName="(optional)">
<discoveryURLs>
<discoveryURL></discoveryURL>
<discoveryURL></discoveryURL>
</discoveryURLs>
<name>The Daily Moon</name>

<name lang="fr-ca">La Lune Quotidienne</name>
<description></description>
<contacts>
<contact>
<description></description>
<personName>Pat Mooney</personName>

<phone></phone>
<email>patm@daily-moon.com</email>
<address useType="optional, billing, etc." 
sortCode="optional" 
tModelKey="optional">
<addressLine></addressLine>
<addressLine></addressLine>
<addressLine></addressLine>

</address>
</contact>
<contact>
         ...
</contact>
</contacts>
<businessServices>
<businessService serviceKey="required" 
businessKey="optional">
         ...

</businessService>
</businessServices>
<identifierBag>
      ...
</identifierBag>
<categoryBag>
      ...
</categoryBag>
</businessEntity>

El registro businessEntity No debe ser complicado. De hecho, debe contener únicamente un solo nombre y un identificador único para que actúe como la businessKey requerida. No obstante, a fin de lograr una integralidad, incluimos la estructura completa, excepto algunas secciones que hemos recortado y de las hablaremos en un momento. Los elementos vacíos deberían quitarse en un entorno de producción.

Veamos algo de esta información aquí.

Comenzando por arriba, businessKey, nuevamente, es un identificador único. Los atributos operador y authorizedName los maneja el registro internamente; no debe tocarlos, ya que representan la entidad que ejecuta el registro y la persona o cuenta que agregó el registro.

Se agregan las discoveryURLs al registro cada vez que se graba en el registro una businessEntity. Estas URL constituyen una ubicación al cual puede ir el usuario para buscar más información acerca de la businessEntity.

Observe que Francis había agregado un nombre adicional, representando el nombre del periódico en francés, en donde el mismo está tratando de fomentar el negocio. Cada una de estas entradas trae el atributo lang (idioma) atributo que especifica el código del idioma en cuestión. Puede proporcionar nombres alternativos desde abreviaturas comunes, por ejemplo, IBM versus International Business Machines.

La descripción que sigue es optativa y se trata simplemente de una cadena de texto. De hecho, la mayoría de los elementos más importantes en UDDI poseen una descripción optativa.

Luego, Francis puede agregar más contactos. Para cada contacto puede especificar toda la información que resulte necesaria. Generalmente se proporciona el personName (nombre de la persona), pero se puede agregar más información, tal como el número de teléfono o el correo electrónico, etc., en función de la privacidad asignada a las personas involucradas, dado que toda la información contenida en el Registro UDDI está disponible de manera pública para todos los usuarios. Los contactos pueden también tener un domicilio, con el useType especificando el tipo de domicilio. Por ejemplo, en el caso de un contacto, puede ser el domicilio versus el trabajo, etc. En el caso de una empresa, el useType (tipo de uso) podría ser la oficina principal, el centro de distribución, etc.

El elemento businessServices enumera todos los servicios que han sido asociados con la businessEntity. Dado que Gene no ha agregado ningún servicio aún, este elemento quedará generalmente vacío. Los últimos dos ítems,identifierBag y categoryBag, brindan información adicional acerca de la propia empresa y se utilizan en caso de búsquedas. En un momento analizaremos cada uno de ellos.

publisherAssertion

La publisherAssertion es una declaración en cuanto a la relación de una businessEntity con otra. Por ejemplo, Francis sabe que una de las metas de este proyecto es utilizar un servicio provisto en Daily Star, en el que el Daily Star brinda los resultados deportivos al Daily Moon. Esto hace que el Daily Star se convierta en un proveedor de contenidos para el Daily Moon. Francis puede representar eso, tal como figura en el Listado 3.

Listado 3. La publisherAssertion
<publisherAssertion>
<fromKey>(businessKey for Daily Star)</fromKey>
<toKey>(businessKey for Daily Moon)</toKey>
<keyedReference tModelKey="904BD800-D53A-11DA-B055-850A1DA99D79" 
         keyName="optional" keyValue="CONTENTPROVIDER" />
</publisherAssertion>

Los elementos fromKey y toKey representan las ID únicas para las dos entidades involucradas. En este caso, se trata de Daily Moon, y Daily Star. ElDaily Stares proveedor de contenidos del Daily Moon, entonces las claves se colocan como corresponde. La keyedReference (referencia en clave) aparecerá una y otra vez. En este caso, decimos que la referencia en sí misma es un proveedor de contenidos. El keyValue es el único atributo requerido para una keyedReference pero no es inusual tampoco incluir un keyName por cuestiones de legibilidad, y una tModelKey para identificar un tipo en particular de referencia. En este caso la tModelKey representa el espacio de nombres de asociaciones entre periódicos, en oposición a las representaciones internas. Hablaremos más en detalle acerca de los tModels en un minuto.

businessService

Luego, Francis necesita ingresar información acerca de cualquier servicio real que el Daily Moon vaya a proveer. Un objeto de businessService contiene dos tipos de información principales además de la serviceKey única requerida y el nombre. Son las bindingTemplates y cualquier categoría a la que pertenezca el servicio. Consulte el Listado 4.

Listado 4. El businessService
<businessService serviceKey="required" businessKey="optional">
<name></name>
<description></description>
<bindingTemplates>
<bindingTemplate serviceKey="optional" bindingKey="required">
         ...

</bindingTemplate>
</bindingTemplates>
<categoryBag>
      ...
</categoryBag>
</businessService>

BindingTemplate

Tmodelinstancedetails Indica con qué aplicaciones o especificaciones es compatible. Consulte el Listado 5.

Listado 5. El bindingTemplate (plantilla de enlace)
<bindingTemplate serviceKey="optional"
 bindingKey="required"><accessPoint> OR <hostingRedirector bindingKey="another
 binding to be used instead">
<tModelInstanceDetails>
<tModelInstanceDetail>

<tModelInstanceInfo tModelKey=""uuid key for specification tModel">>
<description></description>
<instanceDetails>
<description></description>
<overviewDoc>
<description></description>
<overviewURL></overviewURL>

</overviewDoc>
<instanceParams>string</intstanceParms>
</instanceDetails>
</tModelInstanceInfo>
<tModelInstanceInfo>
            ...
</tModelInstanceInfo>
  </tModelInstanceDetail>

   <tModelInstanceDetails>
</bindingTemplate>
TModels (including tModel of tModels)
Serve two purposes.  As specification indicators, and as namespace indicators.
<tModel tModelKey="required" operator="optional" 
authorizedName="optional">
<name></name>
<description></description>
<overviewDoc>

<description></description>
<overviewURL></overviewURL>
<overviewDoc>

   <identifierBag>
...
</identifierBag>
<categoryBag>

      ...
</categoryBag>
</tModel>

A bindingTemplate es lo que define tanto la ubicación donde se puede encontrar el servicio y lo que hace, lo cual no suena muy complicado. Sin embargo, ambas funciones adquieren un nuevo significado en el contexto de UDDI. Por ejemplo, para determinar dónde se puede acceder a un servicio se puede proporcionar un accessPoint, que representa una URL simple, o cualquier otro dato adecuado, tal como un número telefónico para una línea de ayuda, o un hostingRedirector.

Taxonomías

Cuando clasificamos información, ayuda poder acordar el modo de denominar tales clasificaciones. Estas clasificaciones acordadas se denominan taxonomías.

Por ejemplo, el Sistema de Clasificación Industrial de Norteamérica (North American Industry Classification System – NAICS) efectúa una distinción entre "Alquiler de artículos deportivos," "Comercios de artículos deportivos," y "Comercios de artículos deportivos, usados" asignándole un código a cada uno de ellos. De este modo, cuando figura el código 532292, usted sabe que está hablando de un lugar para alquilar artículos deportivos, en oposición al lugar donde puede comprarlos.

Los operadores UDDI agregan una serie de taxonomías al sistema como un procedimiento normal, poniéndolos a su disposición para su uso sin que usted tenga que registrar tModels para los mismos. Por ejemplo, la jUDDI para crear un tModel para uddi-org:general_keywords con la clave de tModel de A035A07C-F362-44DD-8F95-E2B134BF43B4, entonces usted puede utilizarla sin definirla usted mismo.

El hostingRedirector se utiliza cuando cambia el enlace de un servicio. Por ejemplo, si el Daily Moon Debiera configurar su servicio de avisos clasificados y permite a cualquiera de los periódicos que presente avisos utilizando la llamada createNewAdd(), necesitaría asegurarse de que el servicio nunca ha cambiado o brindar un modo de informar a los clientes que ha cambiado. En este caso entra en juego el hostingRedirector. En ese caso, Francis (o, en realidad, Gene) crearía una nueva bindingTemplate, representando la información nueva e ingresaría en dicha bindingTemplate la bindingKey en el atributo bindingKey del elemento hostingRedirector.

La definición de lo que realiza el servicio puede resultar aún más difícil por dos motivos. En primer lugar, no estamos hablando necesariamente de un servicio SOAP, no se puede proporcionar simplemente un archivo WSDL. En segundo lugar, dado que ha sido pensado como un proceso automatizado, se debe brindar dicha información de un modo que no resulte ambiguo.

El resultado es que la bindingTemplate incluye un elemento denominado tModelInstanceDetails que contiene uno o más elementos denominados tModelInstanceDetail. Cada uno de ellos incluye uno o más tModelInstanceInfo elementos, que señalan a un tModel en particular. Nuevamente, hablaremos de los tModels en un momento. Lo importante es comprender, sin embargo, es que elemento tModelInstanceInfo puede contener un elemento denominado instanceDetails, que contiene en sí mismo un overviewDoc, que incluye la overviewURL, que se trata de una URL de un documento que en realidad define el servicio. (Sí, allí se especifica el archivo WSDL.)

TModels(que incluyen el tModel de tModels)

Pasemos a hablar ahora de los tModels.

tModels en realidad tienen dos propósitos. El primero, tal como lo hemos visto brevemente en el análisis de las publisherAssertions, el es de ser un "indicador del espacio de nombres". En otras palabras, un tModel puede brindar un modo de efectuar una distinción entre los tipos de información que se pueden confundir fácilmente. Un ejemplo que se brinda a menudo es el de los códigos de identificación tributaria, u otro tipo de números que pueden confundirse con facilidad. Por ejemplo una keyedReference que incluye lo siguiente, no parece brindar toda la información debido a que estas dos ID tributarias pertenecen a distintos países. En ambos países, se denominan ID tributaria, pero de manera programática, debemos tener un modo de distinguirlas, tal como figura en el Listado 6.

Listado 6. Identificaciones tributarias de distintos países
<keyedReference tModelKey="" keyName="taxid" 
keyValue="11111111" />
<keyedReference tModelKey="" keyName="taxid" 
keyValue="22222222" />

Allí ingresa un tModel. Podemos crear un modelo clave para la “clave de identificación tributaria de los EE.UU”, otro para la "clave de identificación tributaria de México", etc. Una vez que los creamos, podemos utilizar sus claves de tModel para calificar estas keyedReferences. Consulte el Listado 7.

Listado 7. tModels y keyedReferences
<tModel tModelKey="902CDE50-D53A-11DA-B055-A74C17FA61A7">
   <name>United States codes</name>
</tModel>
<tModel tModelKey="062377D0-D5F5-11DA-8170-8ACF057FECAD">
   <name>Mexico codes</name>

</tModel>
<keyedReference tModelKey="902CDE50-D53A-11DA-B055-A74C17FA61A7" 
                keyName="taxid" keyValue="11111111" />
<keyedReference tModelKey="062377D0-D5F5-11DA-8170-8ACF057FECAD" 
                keyName="taxid" keyValue="22222222" />

El otro uso del tModel es como un identificador de especificaciones. Por ejemplo, Francis sabe que Gene va a crear entradas para el ClassifiedService Sobre el que los dos trabajaron el mes pasado. Este servicio representa una interfaz específica, y como tal, puede ser identificado utilizando un tModel. El tModel debería ser similar al que figura en el Listado 8.

Listado 8. El tModel
<tModel tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A" 
        operator="optional" authorizedName="optional">

   <name>Classified Service Interface</name>
   <description></description>

   <overviewDoc>
      <description></description>
      <overviewURL>
        http://www.daily-moon.com/ClassifiedService-interface.wsdl
      </overviewURL>
   <overviewDoc>

   <identifierBag>
...
   </identifierBag>

   <categoryBag>
      ...
   </categoryBag>
</tModel>

Tal como sucede con cada objeto al que hemos contemplado, el tModel posee una clave única, que constituye la única información requerida. No obstante, en este caso, desearíamos también especificar la overviewURL, que significará la URL correspondiente al archivo WSDL de la interfaz. (Lo crearemos en la siguiente sección.)

Nuevamente, se pueden identificar los tModels utilizando una identifierBag, se los puede categorizar utilizando una categoryBag. Veamos cómo funciona.

identifierBag

Dado que la intención de la UDDI es ser flexible, no existe una manera específica de identificar una businessEntity. UDDI no impone identificar una empresa mediante su número D-U-N-S, o mediante su número de identificación tributaria, o mediante cualquier otro método de identificación en particular. En cambio, proporciona un contenedor en el cual usted puede colocar tantos identificadores como sea necesario, tal como se puede apreciar en el Listado 9.

Listado 9. La indentifierBag
<identifierBag><keyedReference
 tModelKey="4064C064-6D14-4F35-8953-9652106476A9" 
         keyName="DUNS Number" keyValue="55555555" /><keyedReference tModelKey="" 
         keyName="US Tax ID" keyValue="111111111" />

</identifierBag>

Cada keyedReference que agrega en una identifierBag representa otra oportunidad para que los usuarios encuentren el objeto en cuestión en una búsqueda.

categoryBag

La categoryBag funciona como la identifierBag, en que contiene uno una o más keyedReferences. Consulte el Listado 10.

Listado 10. La categoryBag
<categoryBag>
   <keyedReference tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
           keyName="optional" keyValue="511110" />
</categoryBag>

En este caso, Francis ha creado una categoryBag que muestra que el Daily Moon es una sucursal del periódico. Entonces, veamos cómo se utilizan todos estos objetos.


Mapeo WSDL a UDDI

Antes de que Gene pueda escribir cualquier código para enviar toda esta información al registro UDDI, debe realizar una importante conexión entre sus servicios actuales y la UDDI. Debe adaptarlos a la noción de servicios, interfaces y plantillas de enlace de UDDI.

Servicio versus interfaz

La visión de UDDI de un servicio, tal como lo podrá recordar, contiene tres partes: la interfaz, que se define utilizando los tModels; el businessService; y la bindingTemplate, que sirve para unirlos. Entonces, el primer paso que debe realizar Gene es el de pensar cómo puede encajar en esta estructura el archivo WSDL que define el servicio SOAP.

El primer paso consiste en desglosar el WSDL. Afortunadamente, resulta muy simple. La interfaz contiene todas las piezas del archivo WSDL excepto en el caso de la implementación real en sí misma. Consulte el Listado 11.

Listado 11. Interfaz WSDL
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
      xmlns:tns="http://ws.apache.org/axis2"
      xmlns:axis2="http://ws.apache.org/axis2"
      xmlns:ns1="http://org.apache.axis2/xsd" 
      targetNamespace="http://ws.apache.org/axis2">

   <wsdl:types>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
            targetNamespace="http://org.apache.axis2/xsd" 
            elementFormDefault="unqualified" 
            attributeFormDefault="unqualified">

         <xs:element type="ns1:ClassifiedAd" name="ClassifiedAd"
 />
         <xs:complexType name="ClassifiedAd">

            <xs:sequence>
               <xs:element type="xs:int" name="id" />
               <xs:element type="xs:string" name="content" />
               <xs:element type="xs:string" name="endDate" />
               <xs:element type="xs:string" name="startDate" />
            </xs:sequence>

         </xs:complexType>
         ...
      </xs:schema>
   </wsdl:types>

   <wsdl:message name="createNewAdRequestMessage">
      <wsdl:part name="part1" element="ns1:createNewAdRequest" />

   </wsdl:message>
   <wsdl:message name="createNewAdResponseMessage">
      <wsdl:part name="part1" element="ns1:createNewAdResponse" />
   </wsdl:message>
   ...

   <wsdl:portType name="ClassifiedServicePortType">
      <wsdl:operation name="finalizeIssue">

         <wsdl:input message="tns:finalizeIssueRequestMessage" />
      </wsdl:operation>
      <wsdl:operation name="createNewAd">
         <wsdl:input message="tns:createNewAdRequestMessage" />
         <wsdl:output message="tns:createNewAdResponseMessage" />
      </wsdl:operation>

      ...
   </wsdl:portType>

   <wsdl:binding name="ClassifiedServiceBinding" 
                  type="tns:ClassifiedServicePortType">
      <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
                  style="document" />
      <wsdl:operation name="createNewAd">
         <soap:operation soapAction="createNewAd" style="document"
 />

         <wsdl:input>
            <soap:body use="literal" 
                        namespace="http://ws.apache.org/axis2" />
         </wsdl:input>
         <wsdl:output>
            <soap:body use="literal" 
                        namespace="http://ws.apache.org/axis2" />
         </wsdl:output>

      </wsdl:operation>
      ...
   </wsdl:binding>
</wsdl:definitions>

Incluye las definiciones en cuanto a los tipos (el esquema XML), todos los mensajes, el portType, y aún el binding (enlace), dado que dicho enlace no es específico respecto de una implementación en particular.

La implementación contiene el elemento real del servicio. Consulte el Listado 12.

Listado 12. WSDL de la implementación del servicio
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
      xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
      xmlns:tns=
        "http://www.daily-moon.com/ClassifiedService-interface"
      xmlns:axis2="http://ws.apache.org/axis2"
      xmlns:ns1="http://org.apache.axis2/xsd" 
      targetNamespace=
        "http://www.daily-moon.com/ClassifiedService-interface">

<wsdl:import namespace="http://ws.apache.org/axis2" 
   location=
"http://www.nicholaschase.com/ClassifiedService-interface.wsdl" 
/>

<wsdl:service name="ClassifiedService">
   <wsdl:port name="ClassifiedServicePort" 
               binding="axis2:ClassifiedServiceBinding">
      <soap:address 
         location=
 "http://www.daily-moon.com:8080/axis2/services/ClassifiedService" 
      />
   </wsdl:port>

</wsdl:service>

</wsdl:definitions>

Tome en cuenta que el archivo de la implementación importa el archivo de la interfaz. En otras palabras, este archivo contiene la definición total del servicio.

Ahora veamos como eso se corresponde con nuestros objetos UDDI.

Mapeo de la interfaz a un tModel

Gene en primer lugar debe realizar un mapeo de la interfaz respecto del tModel adecuado. Consulte el Listado 13.

Listado 13. El tModel
<tModel tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">

  
 <name>http://www.daily-moon.com/ClassifiedService-
interface</name>
   <description>Interface for the Daily Moon Classified 
Department web application</description>

   <overviewDoc>

      <description>WSDL interface document</description>
      <overviewURL>
          http://www.daily-moon.com/ClassifiedService-interface.wsdl
      </overviewURL>
   <overviewDoc>

   <categoryBag>

      <keyedReference
 tModelKey="C1ACF26D-9672-4404-9D70-39B756E62AB4"
               keyName="uddi-org:types" keyValue="wsdlSpec" />
      <keyedReference
 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
               keyName="ntis-gov:naics:1997" keyValue="511110" />
   </categoryBag>
</tModel>

Comenzando desde abajo, observe la categoryBag. Gene ha agregado dos keyReferences. La primera especifica que estamos, de hecho, trabajando con un archivo WSDL. Esa tModelKey en particular ha sido predefinida para representar el espacio de nombres uddi-org:types Todos los archivos WSDL deben especificarse de este modo. La segunda referencia se encuentra sujeta al espacio de nombres ntis-gov:naics:1997, entonces, resultaría fácil para los usuarios de Gene encontrar esta definición entre todos los archivos WSDL que representan los servicios relacionados con los periódicos. Más arriba podemos consultar la sección overviewDoc. Además de la descripción optativa, especifica la URL real en el que podemos encontrar el archivo WSDL.

Finalmente, el nombre del tModel debería coincidir el espacio de nombres de destino del archivo WSDL.

Mapeo de la implementación a una plantilla de enlace

Gene luego debe realizar un mapeo de la implementación en sí misma hacia una bindingTemplate. Consulte el Listado 14.

Listado 14. La bindingTemplate
<bindingTemplate serviceKey="" bindingKey="">

   <accessPoint>
      http://www.daily-moon.com:8080/axis2/services/ClassifiedService
   </accessPoint>

   <tModelInstanceDetails>
      <tModelInstanceDetail>

         <tModelInstanceInfo 
                 tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">
            <instanceDetails>
               <description>The canonical implementation of 
                  the Daily Moon's classified
 service.</description>
               <overviewDoc>
                  <overviewURL>

           http://www.daily-moon.com/ClassifiedService-impl.wsdl
                  </overviewURL>
               </overviewDoc>
            </instanceDetails>
         </tModelInstanceInfo>
      </tModelInstanceDetail>
   </tModelInstanceDetails>


</bindingTemplate>

En este caso, vemos que Gene crea una nueva bindingTemplate, que configura el accessPoint como la URL del servicio real. Los modelInstanceDetails clave vinculan el tModel de la interfaz (mediante la tModelKey) al documento de la implementación (especificado en el overviewDoc). Ahora debe hacer referencia al mismo desde el servicio.

Haciendo referencia a la bindingTemplate desde el businessService y la businessEntity

El paso final consiste en unir todo y hacer referencia a la bindingTemplate desde el businessService, y el businessService desde la businessEntity. Consulte el Listado 15.

Listado 15. Toda la businessEntity
<businessEntity businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
   <name>The Daily Moon</name>
   <name lang="fr-ca">La Lune Quotidienne</name>
   <contacts>

      <contact>
         <personName>Pat Mooney</personName>
         <email>patm@daily-moon.com</email>
      </contact>
   </contacts>

   <businessServices>
      <businessService 
            serviceKey="064B4170-D5F5-11DA-8170-A74C17FA61A7">
         <name>ClassifiedService</name>
         <bindingTemplates>
            <bindingTemplate 
                 bindingKey="904BD800-D53A-11DA-B055-850A1DA99D79">

               <accessPoint>
      http://www.daily-moon.com:8080/axis2/services/ClassifiedService
               </accessPoint>

               <tModelInstanceDetails>
                  <tModelInstanceDetail>
                     <tModelInstanceInfo 
                 tModelKey="66999A50-D5F4-11DA-9A50-FA44D6AD622A">

                        <instanceDetails>
                           <description>The canonical
 implementation of the Daily Moon's classified 
service.</description>
                           <overviewDoc>
                              <overviewURL>
           http://www.daily-moon.com/ClassifiedService-impl.wsdl
                              </overviewURL>

                           </overviewDoc>
                        </instanceDetails>
                     </tModelInstanceInfo>
                  </tModelInstanceDetail>
               </tModelInstanceDetails>

            </bindingTemplate>

         </bindingTemplates>

         <categoryBag>
            <keyedReference 
                 tModelKey="C1ACF26D-9672-4404-9D70-39B756E62AB4"
                 keyName="uddi-org:types" keyValue="wsdlSpec" />
            <keyedReference 
                 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
                 keyName="ntis-gov:naics:1997" keyValue="511110" />
         </categoryBag>
      </businessService>

   </businessServices>

   <identifierBag>
      <keyedReference
 tModelKey="4064C064-6D14-4F35-8953-9652106476A9" 
         keyName="DUNS Number" keyValue="55555555" />
      <keyedReference tModelKey="" 
         keyName="US Tax ID" keyValue="111111111" />
   </identifierBag>

   <categoryBag>
      <keyedReference
 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
           keyName="optional" keyValue="511110" />
   </categoryBag>
</businessEntity>

En otras palabras, el servicio se encuentra completo ahora: Gene posee ahora una businessEntity que incluye un servicio.


Encontrar y utilizar información

Ahora que ya está toda la información, al menos teóricamente, Gene debe observar el proceso para encontrarla nuevamente.

Modo en que UDDI busca el trabajo: encontrar una empresa

Buscar en la UDDI implica dos pasos. En el primero, se encuentra la clave del objeto que desea, y luego obtiene información acerca de ese objeto. A tal fin, para que Gene pueda encontrar un negocio necesita crear una solicitud find_business, tal como se muestra en el Listado 16.

Listado 16. Encontrar una empresa por categoría
<find_business generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <categoryBag>
      <keyedReference
 tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
           keyName="optional" keyValue="511110" />
   </categoryBag>
</find_business>

Esta solicitud encontrará todas las empresas que concuerdan con las categorías referenciadas en la categoryBag. Búsquedas en la categoryBag del valor se consideran una búsqueda "AND" (Y). En otras palabras, cualquier ítem que coincida es al menos una de las categorías a coincidir, Usted puede especificar también una búsqueda en la identifierBag de este modo. Gene no está realmente interesado en realizar una búsqueda por categoría, sin embargo. Por el momento, desea solamente ver si la empresa se encuentra en el registro o no, por lo cual preferiría realizar la búsqueda por nombre, tal como en el Listado 17.

Listado 17. Encontrar una empresa por nombre
<find_business generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <name>daily</name>
</find_business>

Observe que se considera a la búsqueda por nombre como si el nombre que está buscando está seguido por un comodín. En otras palabras, la búsqueda en este caso es lo mismo que realizar una búsqueda por "daily*", entonces aparecerá tanto el Daily Moon como el Daily Star, y cualquier otra empresa que comience con la palabra "daily". Estas búsquedas no son sensibles al uso de mayúsculas o minúsculas.

Lo que encuentra una búsqueda

La solicitud find_business para devolver un businessList Consulte el Listado 18.

Listado 18. Empresas que aparecen en una búsqueda
<businessList generic="2.0" operator="uddi.sourceOperator" 
    truncated="true" xmlns="urn:uddi-org:api_v2">

   <businessInfos>

      <businessInfo 
            businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691" >
          <name>The Daily Moon</name>

          <serviceInfos>
             <serviceInfo serviceKey=
                     "064B4170-D5F5-11DA-8170-A74C17FA61A7">
                <name>ClassifiedService</name>
             </serviceInfo>
          </serviceInfos>

      </businessInfo>

      <businessInfo>
         ...
      </businessInfo>

   </businessInfos>

</businessList>

El businessList incluye un elemento businessInfo para cada businessEntity que satisface la búsqueda. Cada uno de esos serviceInfo elementos incluye una businessKey para la businessEntity real incluye una versión abreviada de la información que sería enumerada en la businessEntity, de modo que puede tener una idea de si se trata de la empresa que está buscando.

Una vez que cuenta con la businessKey adecuada, necesita obtener mayor información de la businessEntity.

Una vez que ya posee la clave

Para obtener mayor información acerca de la businessEntity en particular, en función de la businessKey, debe ejecutar una solicitud get_businessDetail. Consulte el Listado 19.

Listado 19. Obtener información comercial
<get_businessDetail generic="2.0" xmlns="urn:uddi-org:api_v2" >
 <businessKey>1A3DB880-D5F4-11DA-B880-F94D3591C691
</businessKey>
</get_businessDetail>

Puede efectuar un listado de tantas businessKeys que figuran en una solicitud get_businessDetail tal como lo desee. Cada una tendrá su propio businessDetail elemento en los resultados. Consulte el Listado 20.

Listado 20. Detalles de la empresa que se pueden visualizar
<businessDetail generic="2.0" operator="uddi.sourceOperator" 
    truncated="false" xmlns="urn:uddi-org:api_v2">

   <businessEntity
 businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
      <name>The Daily Moon</name>
      <name lang="fr-ca">La Lune Quotidienne</name>

      <contacts>
...
         <keyedReference 
              tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
              keyName="optional" keyValue="511110" />
      </categoryBag>
   </businessEntity> 

</businessDetail>

Cada elemento del businessDetail incluye la businessEntity completa de la empresa en cuestión.

Cambio en el modo de búsqueda

Mientras que funciona, hay ocasiones en las que se desea cambiar el comportamiento de búsqueda. Por ejemplo, quizás desea buscar una coincidencia exacta en lugar de una coincidencia mediante comodines, o quizás desea realizar una búsqueda en la que coincidan las mayúsculas y las minúsculas. Puede cambiar el modo de realizar la búsqueda usando findQualifiers Consulte el Listado 21.

Listado 21. Uso de findQualifiers
<find_business generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <findQualifiers>
      <findQualifier>sortByNameAsc</findQualifier>
   <findQualifiers>
   <name>daily</name>

</find_business>

En este caso, la búsqueda procederá del modo usual, pero los resultados se visualizarán ordenados por nombre. Puede agregar tantos elementos findQualifier como desee. Entre los que se encuentran disponibles para los usuarios figuran exactNameMatch, caseSensitiveMatch, sortByNameDesc, sortByDateAsc y sortByDateDesc, o LikeKeys (que le informan al registro cómo tratar las claves de una categoryBag o identifierBag como una condición "OR" (O) si comparten la misma tModelKey), y combineCategoryBags (que consideran a todas las categoryBags de una businessEntity, si pertenecen a la businessEntity, el businessService, o a la bindingTemplate, como si pertenecieran al businessService).

Encontrar un tipo de servicio

Gene desea además asegurarse de que los usuarios puedan encontrar cualquier servicio sobre la base de una interfaz en particular. Por ejemplo, esta consulta ubicará las bindingTemplates que usted usa en la interfaz ClassifiedService Consulte el Listado 22.

Listado 22. Encontrar una bindingTemplate
<find_binding generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <tModelBag>
     
 <tModelKey>66999A50-D5F4-11DA-9A50-FA44D6AD622A</tModelKey>
   </tModelBag>
</find_binding>

Esta consulta permite visualizar un serviceList. Consulte el Listado 23.

Listado 23. Servicios que se pueden visualizar
<serviceList generic="2.0" operator="uddi.sourceOperator"    
                  xmlns="urn:uddi-org:api_v2">
   <serviceInfos>
      <serviceInfo 
            serviceKey="064B4170-D5F5-11DA-8170-A74C17FA61A7" 
            businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
          <name>ClassifiedService</name>
      </serviceInfo>

   </serviceInfos>
</serviceList>

Como en el caso de find_business, en el que usted luego debía volver y solicitar información acerca de la businessEntity, debería solicitar información específicamente acerca de los servidores en función de la serviceKey. Consulte el Listado 24.

Listado 24. Obtener detalles acerca del servicio
<get_serviceDetail generic="2.0" xmlns="urn:uddi-org:api_v2" >
   <serviceKey>064B4170-D5F5-11DA-8170-A74C17FA61A7
</serviceKey>
</get_serviceDetail>

Esta consulta permite visualizar un serviceDetail para cada serviceKey especificado. Consulte el Listado 25.

Listado 25. Detalles acerca del servicio que se pueden visualizar
 <serviceDetail generic="2.0" operator="uddi.sourceOperator" 
    xmlns="urn:uddi-org:api_v2">
   <businessService 
          serviceKey="064B4170-D5F5-11DA-8170-A74C17FA61A7"
          businessKey="1A3DB880-D5F4-11DA-B880-F94D3591C691">
      <name>ClassifiedService</name>
      <bindingTemplates>
         <bindingTemplate 
             bindingKey="904BD800-D53A-11DA-B055-850A1DA99D79">

            <accessPoint>
      http://www.daily-moon.com:8080/axis2/services/ClassifiedService
            </accessPoint>
...
         <keyedReference 
              tModelKey="C0B9FE13-179F-413D-8A5B-5004DB8E5BB2" 
              keyName="ntis-gov:naics:1997" keyValue="511110" />
      </categoryBag>
   </businessService>
   <businessService>

...
   </businessService>
</serviceDetail>

Ahora Gene conoce lo que desea hacer, está listo para comenzar a codificar.


Funcionamiento con UDDI en forma programática

El trabajo definitivo de Gene consiste en establecer un grupo de aplicaciones a prueba de concepto para demostrar el modo en que otros grupos pueden armar aplicaciones basadas en el registro UDDI.

Configuración

El primer paso en el trabajo con un registro UDDI es el software del registro en sí mismo, pero a Gene le causó una grata sorpresa descubrirlo debido a que el papel que utiliza es el de Apache Geronimo como su servidor de aplicaciones Web, ese paso ya se ha dado cautelosamente, Geronimo viene con el Apache jUDDI preinstalado.

Realizado ese paso, Gene debe decidir cómo va a acceder al registro realmente. En este caso tiene dos alternativas. La primera es hacerlo directamente, utilizando APIs basadas en UDDI, tal como la que se incluye en jUDDI o en UDDI4J. La segunda es utilizar una API de Java para la implementación de los Registros XML (JAXR). JAXR ha sido pensado para acceder a cualquier registro, siendo sus principales metas UDDI y el soporte ebXML.

Gene decide ir directo a la fuente y descarga UDDI4J. Este último, a su vez, depende de algunas de las bibliotecas distribuidas con Apache Axis, entonces lo descarga también. (Observe que a pesar de que se han utilizado partes anteriores de este proyecto Axis 2, UDDI4J depende de las bibliotecas distribuidas con Axis 1.)

La configuración es bastante directa, la cual requiere que se asegure de que todos los archivos UDDI4J y Axis *.jar se encuentran en el CLASSPATH. Consulte el Listado 26.

Listado 26. Configuración del conjunto CLASSPATH
CLASSPATH=.;<UDDI4J_HOME>\lib\uddi4j.jar;<AXIS_HOME>\lib\axis.jar;
<AXIS_HOME>\lib\saaj.jar;<AXIS_HOME>\lib\jaxrpc.jar;<AXIS_HOME>\lib\
log4j-1.2.8.jar;<AXIS_HOME>\lib\commons-logging-1.0.4.jar;
<AXIS_HOME>\lib\commons-discovery-0.2.jar;

Finalmente, Gene necesita un nombre de usuario y una contraseña para conectarse al registro. Con respecto a esto, cada registro es diferente, por lo cual no entraremos en detalles. La instalación predeterminada de UDDI en Apache Geronimo utiliza un nombre de usuario y una contraseña de "juddi".

Conéctese al registro

El primer paso en cualquier aplicación es conectarse al registro. Consulte el Listado 27.

Listado 27. Conexión al registro
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;

public class CreateNewBusiness {

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
             "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                token.getAuthInfoString());

      } catch(Exception e ) {
         e.printStackTrace();         
      }
   }
}

Comenzando desde arriba, Gene establece los diversos valores que necesitará a través de la aplicación. Específicamente, Gene establece el nombre de clase para la TransportFactory. UDDI4J puede utilizar cualquier número de clases adecuado, tal como el que viene con Apache Axis, tal como puede apreciarse aquí, el que viene con el paquete Apache SOAP antiguo, o alguno similar.

Finalmente, configura los valores de la inquiryURL y publishURL para el registro —serán generalmente diferentes, en parte, debido a que la publicación se logra en generalmente utilizando SSL— y solicita un token de autorización.

Este token es importante porque se trata del modo en que cada solicitud indica que ha sido autenticada en el servidor. Dado que cada registro maneja las cosas de manera diferente, no resulta práctico (o seguro) continuar enviando el nombre de usuario y clave con cada solicitud.

Cuando Gene ejecuta la aplicación, ve el siguiente resultado:
Security authToken:authToken:505A7DE0-D897-11DA-A5BF-ADFF17B378CF

Crear una entidad comercial

Luego, Gene desea crear la entidad comercial. Consulte el Listado 28.

Listado 28. Creación de la businessEntity
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;

import org.uddi4j.datatype.business.BusinessEntity;
import org.uddi4j.response.BusinessDetail;
import org.uddi4j.datatype.business.Contact;
import org.uddi4j.datatype.business.Contacts;
import org.uddi4j.util.KeyedReference;
import org.uddi4j.util.IdentifierBag;
import org.uddi4j.util.CategoryBag;
import org.uddi4j.datatype.tmodel.TModel;
import java.util.Vector;

public class CreateNewBusiness {

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String businessName = "The Daily Moon";
      String alt_businessName = "Daily Moon";
      String contact_personName = "Pat Moonie";
      String contact_phone = "212-555-1212";
      String identifier_homepage = "http://www.daily-moon.com";
      String category_NAICS = "511110";

      String transportClass = 
               "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                token.getAuthInfoString());

         Vector entities = new Vector();

         BusinessEntity newBusiness = 
                        new BusinessEntity("", businessName);

         Contact newContact = new Contact(contact_personName);
         Vector contactsVector = new Vector();
         contactsVector.addElement(newContact);
         Contacts contacts = new Contacts(); 
         contacts.setContactVector(contactsVector);
         newBusiness.setContacts(contacts);
   
         KeyedReference taxid = 
               new KeyedReference(TModel.HOMEPAGE_TMODEL_KEY,    
                                  identifier_homepage);
         IdentifierBag idBag = new IdentifierBag();
         idBag.add(taxid);
         newBusiness.setIdentifierBag(idBag);

         KeyedReference category = 
               new KeyedReference(TModel.NAICS_TMODEL_KEY, 
                                  category_NAICS);
         CategoryBag catBag = new CategoryBag();
         catBag.add(category);

         entities.addElement(newBusiness);

         BusinessDetail bd = 
                     proxy.save_business(token.getAuthInfoString(), 
                                         entities);

         Vector businessEntities = bd.getBusinessEntityVector();
         BusinessEntity returnedBusinessEntity = 
                       (BusinessEntity)(businessEntities.elementAt(0));

         System.out.println("The new businessKey:" 
                  + returnedBusinessEntity.getBusinessKey());

      } catch(Exception e ) {
         e.printStackTrace();         
      }
   }
}

El proceso de armar una businessEntity contiene, básicamente, de elementos de construcción, tal como están en el XML, con los "plurales" (tales como "contacts", "tModelInfos" Etc.) los cuales se manejan como vectores.

En este caso, Gene arma el vector de contactos, la identifierBag, y la categoryBag, y los agrega al objeto BusinessEntity El objeto en sí mismo se agrega a un Vector, que se dice a este método save_business() junto con el token de autorización.

El resultado es un objeto BusinessDetail Que contiene un objeto o más BusinessEntity tal como existen en la base de datos. En este caso, Gene presentó la BusinessEntity sin un valor para la businessKey, lo cual permite al registro conocer cómo crear un objeto nuevo, y de este modo, una nueva clave. Al recuperar la primera BusinessEntity desde el vector, Gene puede obtener la nueva businessKey.

Cuando ejecuta la aplicación, toma el resultado que se muestra en el Listado 29:

Listado 29. Obtención de una nueva businessKey
Security authToken:authToken:1D05DB90-D899-11DA-A5BF-D3513DE466CA
The new businessKey:1D359E20-D899-11DA-A5BF-F9EAF6D4E3F7

Crear una interfaz de servicio tModel

Con la empresa en su lugar, Gene luego emprendió la tarea de agregar la interfaz de servicio. Consulte el Listado 30.

Listado 30. Creación de un tModel
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.datatype.tmodel.TModel;
import org.uddi4j.response.TModelDetail;
import org.uddi4j.datatype.OverviewURL;
import org.uddi4j.datatype.OverviewDoc;
import org.uddi4j.util.CategoryBag;
import org.uddi4j.util.KeyedReference;

public class CreateNewInterface{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
            "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
            transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                   token.getAuthInfoString());

         Vector tModels = new Vector();
         TModel tModel = new TModel("", 
             "http://www.daily-moon.com/classifieds-interface");

         tModel.setDefaultDescriptionString(
               "Interface for the Daily Moon Classified "+
               "Department web application");

         OverviewDoc overviewDoc = new OverviewDoc();
         overviewDoc.setDefaultDescriptionString(
                                   "WSDL interface document");
         OverviewURL overviewURL = new OverviewURL( 
"http://www.nicholaschase.com/ClassifiedsService-interface.wsdl");
         overviewDoc.setOverviewURL(overviewURL);
         tModel.setOverviewDoc(overviewDoc);

         KeyedReference wsdlNotation = 
            new KeyedReference(TModel.TYPES_TMODEL_KEY, 
                               "wsdlSpec", 
                 "C1ACF26D-9672-4404-9D70-39B756E62AB4");
         KeyedReference typeNotation = 
            new KeyedReference("ntis-gov:naics:1997", 
                               "511110", 
                 "C0B9FE13-179F-413D-8A5B-5004DB8E5BB2");
         CategoryBag catBag = new CategoryBag();
         catBag.add(wsdlNotation);
         catBag.add(typeNotation);
         tModel.setCategoryBag(catBag);

         tModels.add(tModel);

         TModelDetail tModelDetail =              
            proxy.save_tModel(token.getAuthInfoString(), tModels);

         Vector tModelVector = tModelDetail.getTModelVector();
         TModel tModelReturned = (TModel)(tModelVector.elementAt(0));
         System.out.println("TModel Saved: " + 
                                tModelReturned.getNameString());
         System.out.println("TModel Key  : " + 
                                tModelReturned.getTModelKey());

      } catch(Exception e ) {
         e.printStackTrace();         
      }
   }
}

Tal como sucedió anteriormente, Gene emprende la tarea de moldear el elemento XML en código Java. Comienza creando el TModel, nuevamente sin clave, lo cual significa que está creando un objeto nuevo y establece la descripción. Luego crea entonces el OverviewDoc, completo con su descripción y OverviewURL. Luego, crea las KeyedReferences Correspondientes a la CategoryBag. Observe que está siendo referencia a tModels específicos, por lo que brinda la tModelKey para cada uno de ellos; este valor es optativo. Finalmente, guarda el TModel, recuperando otra vez el objeto desde el valor recibido.

Al correr la aplicación Gene obtiene lo siguiente como resultado Listado 31:

Listado 31. Obtaining a new tModel key
Security authToken:authToken:3312DF20-D8A1-11DA-A5BF-D754085751C9
TModel Saved: http://www.daily-moon.com/classifieds-interface
TModel Key  : uuid:332F67D0-D8A1-11DA-A5BF-DF15F533BFA1

Creación de un servicio

Para crear el servicio en sí mismo sigue el mismo procedimiento básico. Consulte el Listado 32.

Listado 32. Creación del servicio
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.datatype.business.BusinessEntity;
import org.uddi4j.datatype.service.BusinessService;
import org.uddi4j.datatype.binding.BindingTemplate;
import org.uddi4j.datatype.binding.BindingTemplates;
import org.uddi4j.util.CategoryBag;
import org.uddi4j.util.KeyedReference;
import org.uddi4j.datatype.binding.AccessPoint;
import org.uddi4j.datatype.binding.TModelInstanceDetails;
import org.uddi4j.datatype.binding.TModelInstanceInfo;
import org.uddi4j.datatype.binding.InstanceDetails;
import org.uddi4j.datatype.OverviewDoc;
import org.uddi4j.datatype.OverviewURL;
import org.uddi4j.datatype.tmodel.TModel;
import org.uddi4j.response.ServiceDetail;

public class CreateNewService{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";
      String businessKey =
 "1D359E20-D899-11DA-A5BF-F9EAF6D4E3F7";

      String transportClass = 
           "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                   token.getAuthInfoString());

         BusinessService businessService = new BusinessService("");
         businessService.setDefaultNameString(
                                   "ClassifiedService",null);
         businessService.setBusinessKey(businessKey);

         BindingTemplate bindingTemplate = new BindingTemplate();

         AccessPoint accessPoint = new AccessPoint(
"http://www.daily-moon.com:8080/axis2/services/ClassifiedService", 
                                                   "http");
         bindingTemplate.setAccessPoint(accessPoint);

         TModelInstanceDetails tModelDetails = 
                                 new TModelInstanceDetails();
         TModelInstanceInfo tModelInstanceInfo = 
                new TModelInstanceInfo(
                       "332F67D0-D8A1-11DA-A5BF-DF15F533BFA1");

         InstanceDetails instanceDetails = new InstanceDetails();
         OverviewDoc overviewDoc = new OverviewDoc();
         OverviewURL overviewURL = new OverviewURL(
"http://www.nicholaschase.com/ClassifiedService-impl.wsdl");
         overviewDoc.setOverviewURL(overviewURL);
         instanceDetails.setOverviewDoc(overviewDoc);

         tModelInstanceInfo.setInstanceDetails(instanceDetails);         

         tModelDetails.add(tModelInstanceInfo);
         bindingTemplate.setTModelInstanceDetails(tModelDetails);

         BindingTemplates bindingTemplates = new BindingTemplates();
         bindingTemplates.add(bindingTemplate);
         businessService.setBindingTemplates(bindingTemplates);

         KeyedReference wsdlNotation = 
            new KeyedReference(TModel.TYPES_TMODEL_KEY, 
                               "wsdlSpec", 
                 "C1ACF26D-9672-4404-9D70-39B756E62AB4");
         KeyedReference typeNotation = 
            new KeyedReference("ntis-gov:naics:1997", 
                               "511110", 
                 "C0B9FE13-179F-413D-8A5B-5004DB8E5BB2");
         CategoryBag catBag = new CategoryBag();
         catBag.add(wsdlNotation);
         catBag.add(typeNotation);
         businessService.setCategoryBag(catBag);

         Vector services = new Vector();
         services.addElement(businessService);
         
         ServiceDetail serviceDetail = proxy.save_service(
                        token.getAuthInfoString(),services);

         Vector businessServices = 
                 serviceDetail.getBusinessServiceVector();
         BusinessService businessServiceReturned = 
                (BusinessService)(businessServices.elementAt(0));

         String serviceKey = businessServiceReturned.getServiceKey();

         System.out.println("The Name: "+          
                businessServiceReturned.getDefaultNameString());
         System.out.println("The ServiceKey: "+ serviceKey);

      } catch(Exception e ) {
         e.printStackTrace();         
      }
   }
}

Hasta ahora a Gene el patrón le resultó familiar; crear los objetos a medida que existen en el documento XML. Crear el BusinessService, agregar la businessKey. Crear la BindingTemplate, asegurarse de hacer referencia a la tModelKey creada cuando creó la interfaz tModel y la URL para el archivo WSDL. Cree la categoryBag, agréguela, y guarde el servicio. Recupere el servicio y su nombre y clave. Al ejecutar la aplicación Gene obtuvo el resultado que se muestra en el Listado 33.

Listado 33. Recuperación de la clave de nombre del servicio
Security authToken:authToken:E4203390-D8A5-11DA-A5BF-8F6C6FEDFEBD
The Name: ClassifiedService
The ServiceKey: E43F2D40-D8A5-11DA-A5BF-880A3C83523B

Encontrar una empresa

Luego Gene se concentra en poner en juego dichas búsquedas. Comienza con una búsqueda de empresa y trata de asegurarse de que se haya ingresado el periódico al registro y que no haya sido duplicado. Consulte el Listado 34.

Listado 34. Encontrar una empresa
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.datatype.Name;
import org.uddi4j.response.BusinessInfo;
import org.uddi4j.response.BusinessList;
import org.uddi4j.util.FindQualifier;
import org.uddi4j.util.FindQualifiers;

public class FindBusiness{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
             "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                    token.getAuthInfoString());

         String businessToFind = "The Daily Moon";
         Vector names = new Vector();
         names.add(new Name(businessToFind));

         FindQualifiers findQualifiers = new FindQualifiers();
         Vector qualifier = new Vector();
         qualifier.add(new FindQualifier("exactNameMatch"));
         findQualifiers.setFindQualifierVector(qualifier);
         BusinessList businessList = 
                        proxy.find_business(names, null, null, 
                                   null,null,findQualifiers,5);

         Vector businessInfoVector  = 
             businessList.getBusinessInfos().getBusinessInfoVector();
         for( int i = 0; i < businessInfoVector.size(); i++ ){
            BusinessInfo businessInfo = 
                      (BusinessInfo)businessInfoVector.elementAt(i);
            System.out.println(businessInfo.getDefaultNameString() +
                               ": " +
 businessInfo.getBusinessKey());
         }

      } catch(Exception e ) {
         e.printStackTrace();         
      }
   }
}

Gene está buscando un valor de nombre en particular, por lo cual arma ese tipo de búsqueda. Crea un Vector De objetos de Nombres con un único ítem y crea un FindQualifier Para especificar que está buscando únicamente una coincidencia exacta. Finalmente, alimenta la solicitud en el método find_business() que toma como parámetros los nombres, cualquier discoveryURLs, una IdentifierBag, una CategoryBag, una TModelBag, cualquier FindQualifiers, y la cantidad máxima de resultados a devolver.

Da como resultado un BusinessList, a través del cual Gene lo repite para ver si todos sus valores en caso de que se haya duplicado la información. Imprime para cada uno el nombre y la businessKey tal como se puede observar en el Listado 35.

Listado 35. Nombre de la empresa y businessKey
Security authToken:authToken:DBEAE280-D8A8-11DA-A5BF-A6D55D3D237D
The Daily Moon: 1D359E20-D899-11DA-A5BF-F9EAF6D4E3F7
The Daily Moon: 1A3DB880-D5F4-11DA-B880-F94D3591C691

En este caso, puede ver que se ha duplicado la información, por lo cual puede alimentar la businessKey extra al UDDIProxy del objeto delete_business() del método.

Encontrar un servicio

Luego, Gene desea asegurarse de que se puede encontrar el ClassifiedService En función de su categoría. Consulte el Listado 36.

Listado 36. Encontrar un tipo de servicio
import org.uddi4j.client.UDDIProxy;
import org.uddi4j.response.AuthToken;
import org.uddi4j.transport.TransportFactory;
import java.util.Vector;

import org.uddi4j.util.CategoryBag;
import org.uddi4j.util.KeyedReference;
import org.uddi4j.datatype.tmodel.TModel;
import org.uddi4j.datatype.binding.BindingTemplate;
import org.uddi4j.datatype.binding.TModelInstanceInfo;
import org.uddi4j.datatype.binding.TModelInstanceDetails;
import org.uddi4j.datatype.binding.AccessPoint;
import org.uddi4j.datatype.binding.InstanceDetails;
import org.uddi4j.datatype.service.BusinessService;
import org.uddi4j.response.ServiceDetail;
import org.uddi4j.response.ServiceInfo;
import org.uddi4j.response.ServiceList;

public class FindTypeOfService{

   public static void main (String args[]){
      String inquiryURL = "http://localhost:8080/juddi/inquiry";
      String publishURL = "http://localhost:8080/juddi/publish";
      String userId = "juddi";
      String credential = "juddi";

      String transportClass = 
                "org.uddi4j.transport.ApacheAxisTransport";
      System.setProperty(TransportFactory.PROPERTY_NAME, 
                         transportClass);

      UDDIProxy proxy = new UDDIProxy();

      try {

         proxy.setInquiryURL(inquiryURL);
         proxy.setPublishURL(publishURL);

         AuthToken token = proxy.get_authToken(userId, credential);
         System.out.println("Security authToken:" + 
                                 token.getAuthInfoString());
         KeyedReference wsdlNotation = 
            new KeyedReference(TModel.TYPES_TMODEL_KEY, 
                               "wsdlSpec", 
                 "C1ACF26D-9672-4404-9D70-39B756E62AB4");
         KeyedReference typeNotation = 
            new KeyedReference("ntis-gov:naics:1997", 
                               "511110", 
                 "C0B9FE13-179F-413D-8A5B-5004DB8E5BB2");
         CategoryBag catBag = new CategoryBag();
         catBag.add(wsdlNotation);
         catBag.add(typeNotation);

         ServiceList serviceList = proxy.find_service(null, null, 
                                             catBag,null,null,5);

         Vector serviceInfoVector = 
               serviceList.getServiceInfos().getServiceInfoVector();
         for( int i = 0; i < serviceInfoVector.size(); i++ ){
            ServiceInfo serviceInfo = 
                   (ServiceInfo)serviceInfoVector.elementAt(i);

            System.out.println("Service name: " + 
                          serviceInfo.getDefaultNameString());
            System.out.println("Service key: " + 
                          serviceInfo.getServiceKey());

            ServiceDetail serviceDetail = 
                proxy.get_serviceDetail(serviceInfo.getServiceKey());

            BusinessService thisService =             
                    (BusinessService)serviceDetail
                           .getBusinessServiceVector().elementAt(0);
            if (thisService.getBindingTemplates().size() > 0){
               BindingTemplate thisBinding =                
                      (BindingTemplate)thisService
                                 .getBindingTemplates().get(0);

               TModelInstanceDetails tModelDetails = 
                              thisBinding.getTModelInstanceDetails();
               TModelInstanceInfo tModelInfo = tModelDetails.get(0);
               InstanceDetails instanceDetails = 
                              tModelInfo.getInstanceDetails();
               String wsdlDocument = 
                              instanceDetails.getOverviewDoc()
                                             .getOverviewURLString();
               System.out.println("Document located at " + 
                                             wsdlDocument);
            }
         }

      } catch(Exception e ) {
         e.printStackTrace();         
      }
   }
}

El primer paso para Gene es crear una CategoryBag que le permita buscar todos los servicios especificados que se relacionan con los periódicos. Como resultado de esa búsqueda obtiene un ServiceList, a través del cual efectúa una repetición para obtener más información. Un objeto ServiceInfo representa a cada servicio en el resultado, y lo repite en cada uno de ellos, visualizando su nombre y serviceKey.

Sin embargo, si Gene desease obtener más detalles, tales como la URL del archivo WSDL, debe utilizar la serviceKey para solicitar el ServiceDetail correspondiente al servicio. El ServiceDetail No posee o posee más BindingTemplates Asociados con el mismo y si encuentra uno, sigue hacia abajo a través del objeto TModelInstanceDetails Hasta el objeto InstanceDetails Que incluye el OverviewDoc, y así la OverviewURL. El resultado muestra no solamente el nombre y la serviceKey del servicio resultante, sino también la URL en la que el usuario puede encontrar mayor información. Consulte el Listado 37.

Listado 37. Resultados finales
Security authToken:authToken:59FE37C0-D8AF-11DA-A5BF-A79333DB92F9
Service name: ClassifiedService
Service key: E43F2D40-D8A5-11DA-A5BF-880A3C83523B
Document located at 
         http://www.nicholaschase.com/ClassifiedService-impl.wsdl

Resumen

Un entorno distribuido requiere un repositorio centralizado, de modo tal de que los usuarios y desarrolladores puedan saber lo que se encuentra disponible y dónde encontrarlo y los servicios web no constituyen la excepción. Este tutorial explicó el uso de la Interfaz de Descripción, Localización e Integración Universal (UDDI), la cual brinda un registro de la información disponible acerca de empresas y servicios.

En este tutorial usted aprendió:

  • De qué se trata UDDI y su importancia
  • Cómo estructurar los datos de UDDI
  • Cómo efectuar una distinción entre las interfaces SOAP y sus implementaciones
  • Cómo encontrar datos en un registro UDDI
  • Cómo interactuar con un registro UDDI utilizando Java

Las próximas partes de esta serie tratarán acerca de las crecientes necesidades de seguridad y analizarán WS-Security y WS-Policy.


Descargar

DescripciónNombretamaño
Source codeuddicode.zip6KB

Recursos

Aprender

Obtener los productos y tecnologías

  • Descargue Apache Geronimo.
  • Para crear su propio registro UDDI, descargue Apache jUDDI.
  • Descargue UDDI4J.
  • Descargue Apache Axis 1.3.
  • Descargue Java 1.4.2. Geronimo no se ejecutará correctamente con Java 1.5.
  • UDDI4Py Es un paquete de Python que permite el envío de solicitudes y el procesamiento de respuestas desde las API de la Versión 2 de UDDI.

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=SOA y servicios web
ArticleID=660820
ArticleTitle=Comprender las especificaciones de servicios web, Parte 3: Interfaz de Descripción, Localización e Integración Universal (UDDI)
publish-date=08082011