Construcción de SOA con servicios web usando WebSphere Studio, Parte 4: Detectar código en UDDI

Los autores cubren lo último en servicio de agregación en alquileres de DVD por detección de códigos mediante el servicio UDDI publicado en el tutorial anterior (ver todas las partes de esta serie de tutoriales). Este tutorial se centra fundamentalmente en la interacción entre el cliente, el agregador y los dos proveedores de alquiler al realizar el seguimiento de una transacción de un extremo al otro.

Warner Onstine, Senior Mentor, ArcMind

Warner Onstine, Senior Mentor de ArcMind, Inc., es un desarrollador con más de 8 años de experiencia en la industria, la mayor parte de los cuales dedicó al desarrollo de aplicaciones Web. Warner es coautor del libro Professional Java Tools for Extreme Programming, que contiene capítulos sobre Maven, pruebas unitarias en Swing y cobertura de código con jcoverage.



Rick Hightower, Chief Mentor, ArcMind

Rick Hightower, Chief Mentor de ArcMind, Inc., es un desarrollador que ha cosechado múltiples logros, premios de la industria y certificaciones. Es coautor de los libros Professional Jakarta Struts y Java Tools to Extreme Programming, y escribió 1/5 del libro Mastering Tomcat. Rick es autor de numerosos tutoriales bien recibidos sobre EJB 2.0 CMP CMR, XDoclet, Apache Axis, ETTK, WSDK, Struts Tiles, etc. para IBM developerWorks.



05-08-2011

Acerca de este tutorial

El propósito de este tutorial

Los autores cubren lo último en servicio de agregación en alquileres de DVD por detección de código mediante el servicio UDDI publicado en el tutorial anterior. Este tutorial se centra fundamentalmente en la interacción entre el cliente, el agregador y los dos proveedores de alquiler al realizar el seguimiento de una transacción de un extremo al otro.

Qué se necesita saber para este tutorial

En este tutorial, se presupone que se ha completado con éxito el tutorial anterior, Construcción de SOA con servicios web usando WebSphere Studio, Parte 3: WSDL y edición de UDDI usando WebSphere (ver Recursos). Las generalidades presentadas reflejan el resultado de ejecutar consultas luego de la publicación de los modelos técnicos, de negocios y servicios abarcados en el tutorial anterior.

También se presupone la existencia de un conocimiento de trabajo de los servicios web y la capacidad de realizar operaciones básicas con IBM WebSphere®Studio Application Developer Integration Edition V5.1, tales como iniciar y detener el servidor e implantar un servicio web. También asume la existencia de un conocimiento de trabajo de tecnología Java y XML. El conocimiento de tecnología J2EE y de Ant es útil pero no necesario.

Todas las aplicaciones de ejemplos están implementadas en el IBM WebSphere Application Server incrustado que viene con Application Developer. Se provee un generador de scripts Ant para que generar e implantar las aplicaciones de ejemplos sea más fácil y más confiable. Se proveen referencias al material introductorio sobre Ant, tecnología Java, XML, productos IBM WebSphere y tecnología J2EE en la sección de Recursos al final de este tutorial.

Acerca de este tutorial

Este tutorial abarca consultas a un Registro UDDI. Se incluyen los temas, herramientas y técnicas siguientes:

Temas

  • Revisión de UDDI
  • Generalidades sobre el proceso de detección de servicios web
  • Exploración de UDDI4J
  • Uso de API UDDI4J para consultar el registro Application Developer UUDI
  • Ubicación de modelos técnicos
  • Ubicación de un servicio de negocios
  • Ubicación de una entidad de negocios

Herramientas

  • WebSphere Web Service Navigator
  • UDDI4J
  • WSDL4J

Técnicas

  • Consultar el registro Application Developer UDDI interno mediante WebSphere Web Service Navigator
  • Uso de API UDDI4J para consultar el Registro UDDI Application Developer
  • Uso de WSDL4J para enlazar un servicio devuelto por una consulta

Acerca de los laboratorios en esta serie

Todos estos tutoriales se centran en motores de búsqueda de DVD Rental que agrega resultados de búsqueda de una o más tiendas de alquiler de DVD que exhiben sus catálogos online. El caso de uso al que nos referimos, Recomendaciones de alquiler, consiste en permitir que los usuarios introduzcan qué categoría de película desean alquilar y luego, basándose en el historial de alquileres del usuario, el servicio web sugiere otras películas. En el segundo tutorial ("Creación de un servicio web desde una clase Java," ver Recursos), se creó un simple servicio web y se lo ejecutó. En el tercer tutorial se vio cómo conectar dos servicios usando clientes generados por WSDL ("Discover code on UDDI in WebSphere Studio Application Developer Integration Edition V5.1", ver Recursos). En este cuarto tutorial, se amplía la exploración de trabajar con servicios web con dos laboratorios:

  • Laboratorio 1: Publicación de servicios web a un Registro UDDI -- En este laboratorio se orienta sobre cómo publicar dos servicios a un Registro UDDI.
  • Laboratorio 2: Detección de servicios web desde un registro UDDI -- En este laboratorio se orienta sobre la detección de los servicios que se acaban de publicar.

Herramientas necesarias para este tutorial

Como mínimo se necesita Java SDK 1.3.1 o superior, a fin de ejecutar Application Developer (ver Recurso para una versión de prueba).


Cómo encajan las piezas

En el tutorial anterior se creó el servicio de DVD de Dave, en el cual entonces se creó un cliente para el uso del asistente de servicios web de Application Developer. Este cliente realizó una consulta al servicio de DVD de Dave por un título específico de DVD. Si Dave lo tenía, entonces se devolvía como un objeto SOAP complejo, el cual luego se serializaba a un objeto Java que se pudiera manipular.

Se conectó entonces ese cliente al servicio AggregateSearch. Se puede interactuar también con ese servicio a través de SOAP, por lo tanto se ilustró cómo pedir al servicio Aggregate un DVD, lo cual se obtuvo del servicio de DBD de Dave a través del cliente generado. A continuación se presenta un diagrama del recorrido de ida y vuelta.

Seguidamente se lo eleva al siguiente nivel al tomar dos servicios similares al DVD de Dave y publicarlos en el Registro UDDI. El servicio AggregateSearch hará entonces una consulta al registro en busca de servicios que respondan a la búsqueda y luego les enviará una consulta por un DVD específico. A continuación se muestra cómo se vería el nuevo recorrido de ida y vuelta:

Lo que se hace aquí es requerir información de servicios del Registro UDDI, que devuelve los servicios registrados que coincidan con esa descripción específica. Luego se efectúan pedidos directos a los servicios a través de la información obtenida del registro UDDI.


Revisión UDDI

Generalidades sobre UDDI

En el tutorial anterior se aprendió cómo un registro UDDI almacena información sobre los negocios, los servicios ofrecidos por estos negocios, e información técnica sobre dichos servicios. Un tema que es necesario tratar es la gran cantidad de información que se puede almacenar en un registro UDDI. A fin de ubicar un determinado servicio requerido, la especificación UDDI define un enorme conjunto de mensajes SOAP para ejecutar consultas de búsqueda en un registro. Al usar estos mensajes SOAP, se puede encontrar toda la información sobre negocios, servicios y modelos técnicos almacenada.

Ubicar información en un registro frecuentemente se realiza, mediante la provisión de datos de categorización. Se lo puede comparar a usar un motor de búsqueda en la Web para ubicar todos los sitios que contengan información sobre determinados temas de interés. Por ejemplo, se puede consultar el registro UDDI para todas las compras electrónicas y empresas de venta por correo.

La búsqueda de registros frecuentemente se realiza a través de portales GUI (Interfaz de Usuario Gráfica) que sean capaces de crear y ejecutar consultas a un registro. WebSphere Web Service Navigator es un ejemplo de dicho portal. Sin embargo, en otras ocasiones, será deseable buscar un registro de forma programática.

Buscar un registro para servicio con GUI y luego usar los resultados de la búsqueda en cliente es una forma de usar UDDI. En ese caso, el programa cliente puede no necesitar, en absoluto, la interacción con el registro. Se busca el registro de forma manual para un servicio en particular en tiempo de diseño y luego se codifican los resultados al cliente.

En otras ocasiones, será deseable buscar el registro de forma programática. En ese caso, cliente necesitará interactuar con el registro de forma directa en tiempo de ejecución, mediante el uso del registro API. Este código suele ser bastante largo, pero da gran capacidad para la creación de clientes que puedan buscar registros de manera inteligente.

Para interactuar con un registro de manera programática se necesita un API client. En Application Developer, la API cliente es IBM UDDI4J.

Este tutorial usa IBM UDDI4J como API programático. UDDI4J es una implementación de código abierto basado en Java, del protocolo UDDI, que contiene un conjunto de clases completo para publicar, buscar y enlazar un servicio web. La Versión 2 de UDDI4J provee apoyo total para las especificaciones de UDDI V2, viene con una capacidad de registro completa, e incluye capacidades de configuración mejoradas en comparación con versiones anteriores. Todos los ejemplos mostrados en este tutorial se escriben con UDDI4J V2.

El tutorial se centra en el uso de UDDI4J Inquiry API para la localización de negocios, servicios y modelos técnicos. Una vez ubicado el registro apropiado con UDDI4J, se introduce WSDL4J API para crear un enlace con el servicio.

Revisión de estructura de datos UDDI

En el tutorial anterior se explicó el modelo de datos UDDI y se publicó un Negocio (DVDOnline), un Servicio (OrderDVD) y un Modelo Técnico (Online DVD Order).

He aquí una breve revisión de las estructuras de datos usadas en UDDI:

<businessEntity>
La estructura businessEntity contiene toda la información descriptiva sobre la empresa y los servicios que ofrece.

<businessService>
Cada estructura businessEntity contiene una o más estructuras businessService. Una estructura businessService describe un conjunto de servicios categorizado ofrecido por una empresa.

<bindingTemplate>
La estructura bindingTemplate contiene una descripción técnica de un servicio. Cada bindingTemplate pertenece a un sólo elemento businessService.

<tModel>
Un tModel describe las especificaciones, el comportamiento, el concepto y hasta el diseño compartido al cual un servicio da cumplimiento.


WebSphere Web Service Navigator

Uso de WebSphere Web Service Navigator

Si ha completado el tutorial anterior, habrá visto WebSphere Web Service Navigator que viene como parte de Application Developer; pero, por las dudas, se le dará otro vistazo. Navigator provee funcionalidad para ubicar servicios y negocios en el registro y para la publicación y mantenimiento de estos negocios y servicios. Se usa Navigator (también llamado consola de usuario o simplemente consola) en otras partes de este tutorial para publicar algunos de los negocios y servicios. También se usa la consola para inspeccionar la información de negocios y servicios que se publica en el registro.

Para iniciar la consola, haga clic en el ícono Web Services explorer de la barra de herramientas de Application Developer.

Una vez iniciada la consola, haga clic en UDDI Main (UDDI principal) en el panel izquierdo del explorador. Para abrir una conexión a un registro, seleccione IBM UDDI Test Registry (Registro de prueba IBM UDDI) desde la lista desplegable Favorite Registry (Registro favorito) y haga clic en Go (Ir).

Deténgase un momento para observar detenidamente console.

Nota:
Este tutorial presupone la conexión a un repositorio remoto. Todos los ejemplos de este tutorial se crearon con una nueva cuenta de usuario en la cual se publican las entidades del tutorial anterior. Por lo tanto, las generalidades de la consola pueden diferir si se realizaron otros cambios en el registro.

Búsqueda de una entrada

Para buscar una entrada en el registro UDDI, haga clic en Find (Encontrar) en el panel derecho de Web Service Navigator debajo de Other Actions (Otras acciones).

Cuando se conoce el nombre o parte del nombre de la entrada que se busca, la forma más rápida de encontrar la entrada es mediante la selección de la opción Businesses (Negocios) de la lista desplegable Search for (Buscar) y de la selección Simple como el Type of search (Tipo de búsqueda)

Cuando no se conoce el nombre completo de la entrada que se busca, se puede usar la tecla % (porcentaje) como comodín. Con sólo ingresar % devuelve todas las entradas registradas.

  1. Seleccione Businesses en la lista desplegable Search for.
  2. Seleccione Simple como Type of search.
  3. Ingrese DVDOnline como nombre para esta entrada.
  4. Haga clic en Go.

Se observarán dos entradas para el negocio DVDOnline en el panel derecho de la consola. Estas entradas son negocios publicados en el tutorial anterior. Si se hubieran publicado negocios distintos, se deberían poder observar aquí.

Tal como se puede ver, se encontraron varios negocios diferentes que coinciden con esta descripción. Esto se debe a que seguramente habrá otras personas que, en su intento por hacer este tutorial, habrán creado los mismos negocios que se acaban de crear.

Una vez encontrado una empresa, puede obtener información descriptiva sobre la misma si hace clic en el Name (Nombre) de la empresa. Se pueden encontrar los servicios que provee esta empresa si se hace clic en Get services (Obtener servicios) en la sección Other Actions.

Además de ubicar empresas, también se pueden ubicar servicios y modelos técnicos mediante el ingreso del nombre del servicio o del modelo técnico y luego seleccionar la opción apropiada en el panel Find.

A menudo se desconoce el nombre exacto de la entrada. La consola provee capacidades de búsqueda avanzadas para ubicar negocios, servicios y modelos técnicos basados en nombres parciales, información del localizador (categorías a las cuales se asignó una entrada) u otra información descriptiva.


Introducción a UDDI4J

Generalidades sobre UDDI4J

Tal como se mencionara anteriormente en este tutorial, la interfaz programática a un registro se efectúa a través de un conjunto de mensajes SOAP definidos en las especificaciones UDDI. Para crear programas que interactúen con un registro UDDI, el programador necesita crear los mensajes SOAP que registro UDDI comprenda.

Existen muchas formas de escribir un programa para crear estos mensajes SOAP. La forma más fácil y la más común es la de usar algún API de alto nivel en el nivel superior inmediato encima de SOAP. IBM UDDI4J es exactamente esa API. Es una implementación Java, de código abierto, del protocolo UDDI.

Anteriormente en este tutorial, se vieron las estructuras de datos en un registro UDDI y se interactuó con un registro de distintas maneras. A continuación se mostrará cómo interactuar con un registro mediante el uso de UDDI4J.

Conceptos básicos sobre UDDI4J

Se estructura UDDI4J en una serie de paquetes bajo org.uddi4j:

  • org.uddi4j.client -- contiene la clase de clientes importantes UDDIProxy
  • org.uddi4j.datatype -- representa objetos de datos UDDI
  • org.uddi4j.request -- contiene mensajes enviados al servidor
  • org.uddi4j.response -- representa mensajes de respuesta desde un servidor UDDI
  • org.uddi4j.transport -- soporte para transportes conectables
  • org.uddi4j.util -- clases de utilidad para distintas tareas

Una de las clases principales que se usa es la clase org.uddi4j.client.UDDProxy. Es un proxy para el servidor UDDI al que se accede desde el código de cliente. Sus métodos mapean a los mensajes en las especificaciones API del Programador UDDI.

El enfoque en esta sección es el de estudiar un ejemplo, paso a paso, que detalle los pasos importantes en el uso de UDDI4J. Se saltearán algunos de los detalles, tales como importaciones paquete y declaraciones de variables en las secciones detalladas, pero están todas disponibles en el listado de códigos completo al final del tutorial.

Para obtener información adicional extensa, vea el sitio Web UDDI4J. Vale la pena descargar la versión binaria desde ese sitio y navegar Javadocs para la biblioteca.

Acceder al registro -- UDDIProxy

La clase más importante en el paquete UDDI4J es la clase org.uddi4j.client.UDDIProxy. Es el principal objeto cuando se accede a un registro UDDI. Contiene todos los métodos necesarios para conectar a un registro, efectuar consultas al mismo y procesar el resultado. Tiene un constructor que toma URL para efectuar consultas a un registro UDDI.

La URL para ubicar y obtener información del registro instalado en el equipo local es http://localhost:6080/uddisoap/inquiryapi.

Efectuar consultas y obtener información de un registro no requiere de una conexión segura al registro. Tal como se vio en el tutorial anterior, publicar la información requiere una conexión HTTPS.

Listado 1: Creación de UDDIProxy

  private static String inquiryURL = 
      "http://uddi.ibm.com/testregistry/inquiryapi";

// ...

  private void setupProxy(){
    //set up proxy
    proxy = new UDDIProxy();
    try {
      proxy.setInquiryURL(inquiryURL);
    } catch (MalformedURLException e) {
      // Can't create proxy - exit ...
    }
  }

Ubicación de información mediante el uso de UDDI4J

Cuando se desarrolla una aplicación, es muy probable que se busquen servicios web que sigan un determinado modelo. Por ejemplo, se podrían buscar servicios que provean una dirección de correo electrónico para solicitar información. Alternativamente, como en el ejemplo siguiente, se buscará servicios web a través de los cuales se pueden solicitar DVDs. Más específicamente aún, se podrían buscar servicios que sigan el modelo publicado en el tutorial anterior --Modelo de pedido de DVD online.

Para lograr esta tarea, se buscará en el registro el modelo publicado en el tutorial anterior. Una vez hallado, se consulta el registro para obtener servicios que sigan este modelo en particular. Una vez ubicados los servicios, se ubicarán las empresas que provean dicho servicio.

Anteriormente, se comparó el registro UDDI con un motor de búsqueda para buscar páginas en la World Wide Web (www). Cuando se usa un motor de búsqueda, el resultado de la búsqueda es un listado de direcciones de páginas Web y algunas generalidades sobre el contenido de la página Web. Una vez seleccionado uno de los ítems del listado, se lo redireccionará al actual sitio para obtener más información.

UDDI4J usa una forma similar de ubicar entradas de registros. La clase UDDIProxy define métodos para buscar entradas en el registro. Cada uno de esos métodos devuelve un listado de objetos que contiene sólo información básica de cada entrada seleccionada. Esta información incluye por lo menos el nombre y UUID (Identificador Único Universal) de la entrada seleccionada.

Una vez hallada la entrada adecuada, se puede usar UUID para obtener información detallada sobre la entrada del registro.

Acerca de los listados de códigos

En el tutorial anterior, los ejemplos mostraron los pasos necesarios para crear una aplicación que publique BusinessEntity y BusinessService.

Este tutorial tiene un enfoque ligeramente distinto. Usar UDDI4J Inquiry API permite a los desarrolladores buscar el registro de varias maneras diferentes. Los ejemplos mostrados en esta sección buscan y recuperan las distintas entradas. NO SON fragmentos de código de una aplicación completa para ubicar, recuperar y usar un servicio web. Al final de este tutorial se presenta un ejemplo de codificación completo.


Ubicación de un modelo técnico

El método find_tModel

Se puede ubicar un tModel a través de UDDI4J mediante el uso del método find_tModel() de la clase UDDIProxy.

La firma del método find_tModel es:

public TModelList find_tModel(String name, CategoryBag c,
IdentifierBag I, FindQualifiers f, int maxRows)

Se puede usar el método find_tModel() para buscar tModels por nombre, categorías, identificadores o cualquier combinación de los mismos. Se pueden ingresar valores nulos para las entradas que no se van usar en la consulta. Por ejemplo, cuando se buscan modelos por su nombre, la llamada del método es:

proxy.find_tModel(name, null, null, null, 0);

El último parámetro, (int maxRows), indica el número de filas máximo que se pueden devolver al cliente. Cero indica que se pueden devolver cualquier cantidad de filas.

Nota:
FindQualifiers se explica en Ubicar negocios por ubicación geográfica.

El TModelList que find_tModel() devuelve

El valor de devolución de find_tModel() es un objeto org.uddi4j.response.TModelList. Este objeto contiene un objeto org.uddi4j.response.TModelsInfos que incluye un objeto java.util.Vector que contiene objetos org.uddi4j.response.TModelInfo.

La muestra siguiente presenta el resultado de serializar TModelList a su XML equivalente. Se muestra la estructura claramente.

<tModelList generic="2.0" operator="www.mycompany.com/uddi" 
          truncated="false" xmlns="urn:uddi-org:api_v2">
      <tModelInfos>
	<tModelInfo 
                   tModelKey="UUID:1B830749-20BB-4F97-BADF-24353B5424E8">
		<name>Online DVD Order</name>
	</tModelInfo>

     </tModelInfos>
</tModelList>

Realizar consultas en base a nombres

El método que se muestra consulta al registro sobre modelos técnicos basándose en el nombre del modelo. Una vez hallados los modelos del nombre dado, se devuelve un java.util.Vector que contiene objetos org.uddi4j.response.TModelInfo. Cada objeto TModelInfo contiene información sobre un tModel.

Listado 2: Ubicación de modelos técnicos por nombre

public Vector findTModel(String name){
  Vector tModelInfoVector = null;
  try{
    tModelList = 
        proxy.find_tModel(name, null, null, null, 0);
    tModelInfoVector  = 
        tModelList.getTModelInfos().getTModelInfoVector();
  } catch (org.uddi4j.transport.TransportException te){
     // ...
  }catch (org.uddi4j.UDDIException ue){
    // ...
  }
  return tModelInfoVector;
}

Un objeto TModelInfo sólo contiene el nombre y la clave de tModel. Se puede obtener esta información mediante la ejecución de los métodos getName() y getTModelKey() sobre el objeto.

Listado 3: TModelInfo

for (int i = 0; i < tModelInfoVector.size(); i++) {
  TModelInfo tModelInfo = (TModelInfo) tModelInfoVector.get(i);
  Name tName = tModelInfo.getName();
  String tModelName = tName.getText();
  String tModelNameLanguage = tName.getLang();
  String tModelKey = tModelInfo.getTModelKey();
  // ...
}

La información en el objeto TModelInfo es sólo información clave sobre el modelo técnico. Dado que TModelKey se incluye en el objeto TModelInfo, se puede usar esta clave para obtener el verdadero tModel, del registro.

Nota: La recuperación de un modelo técnico verdadero se trata en la sección" Generalidades."

Dificultades – refinar la consulta

El siguiente código es un pobre intento por ubicar un modelo técnico, en base a información de categorización. Si bien el error podría no ser muy claro al principio, cuando se ejecute la búsqueda contra un registro largo, no es muy probable que se encuentre lo que se busca.

Detenerse un momento para observar el código y tratar de detectar el problema.

Listado 4: ¿Qué es lo que funciona mal?

KeyedReference ref = new KeyedReference();
ref.setKeyName("Specification for a Web Service described in WSDL");
ref.setKeyValue("wsdlSpec");
ref.setTModelKey(TModel.TYPES_TMODEL_KEY);
CategoryBag categoryBag = new CategoryBag();
categoryBag.add(ref);
String tModelKey = null;

//  Code for Demonstration puposes only.

try{
  TModelList tModelList = 
    proxy.find_tModel(null, categoryBag, null, null, 0);
  Vector tModelInfoVector  
    tModelList.getTModelInfos().getTModelInfoVector();
  if(tModelInfoVector.size() > 0){
    tModelKey = 
     ((TModelInfo)tModelInfoVector.get(0)).getTModelKey();
  }
}catch (org.uddi4j.transport.TransportException te){
  // ...
}catch (org.uddi4j.UDDIException ue){
  // ...
}

En el ejemplo anterior, se busca un modelo técnico sólo en base a información de categorización. La categoría elegida es la categoría Especificación para un servicio web descrito en WSDL. Una cantidad extremadamente importante de modelos técnicos caen en esta categoría. El resultado de ejecutar este código contra el registro instalado localmente, podría devolver sólo algunos modelos técnicos. Sin embargo, cuando se ejecutó esta consulta contra el registro de prueba público de IBM, el número de modelos técnicos devuelto fue el número máximo del servidor, 100 modelos.

Cuando se busca información en un registro, se debe proveer la mayor cantidad de información posible sobre la entrada que se busca, a fin de limitar el número de devolución de entradas.


Ubicar un BusinessService

El método find_service()

Se puede ubicar BusinessService con UDDI4J mediante el uso del método find_service() de la clase UDDIProxy. La firma de este método es:

public ServiceList find_service(String businessKey, Vector names, 
       CategoryBag c, TModelBag t, FindQualifiers f , int maxRows)

Se puede usar el método find_service() de la clase UDDIProxy para buscar servicios en el registro en base a lo siguiente:

  • El UUID de una BusinessEntity
  • El nombre del servicio
  • La información sobre la categoría de un servicio
  • La información tModel de dicho servicio
  • Cualquier combinación de estos parámetros.

Se pueden ingresar valores nulos para aquellos parámetros que no se van a usar en la consulta.

Nota:
FindQualifiers se explica en Ubicar negocios por ubicación geográfica.

El ServiceList devuelto por find_service()

El método find_service() devuelve un objeto org.uddi4j.response.ServiceList que contiene un objeto org.uddi4j.response.ServiceInfos. El objeto ServiceInfos contiene a java.util.Vector que contiene cero o más objetos org.uddi4j.response.ServiceInfo.

Esta muestra presenta un objeto ServiceList representado como su XML equivalente:

<serviceList generic="2.0" operator="www.mycompany.com/uddi" truncated=
"false" xmlns="urn:uddi-org:api_v2">
  <serviceInfos>
    <serviceInfo businessKey="24851C0A-0E73-469A-9805-0635125C00B3" 
    serviceKey="302813FA-0ECB-49A9-A4D8-3D3F18F03627">
      <name xml:lang="en">OrderDVD</name>
    </serviceInfo>

    <serviceInfo businessKey="23290FC9-3D1B-44E6-BFD7-1DB73279188E" 
    serviceKey="1CAD11A5-3E75-4172-92B7-1B862B3B06F8">
      <name xml:lang="en-US">OrderDVD</name>
    </serviceInfo>
  </serviceInfos>
</serviceList>

Especificación de claves con TModelBag

A fin de buscar el registro basándose en información tModel, el método find_service() requiere un objeto org.uddi4j.util.TModelBag. Un objeto TModelBag contiene cualquier cantidad de objetos org.uddi4j.util.TModelKey. Cada objeto TModelKey contiene el UUID para un modelo técnico.

En el tutorial anterior, se publicó un modelo técnico para pedir DVDs online. El UUID para ese modelo técnico se usa en el siguiente ejemplo con el fin de ubicar servicios en el registro.

Listado 5: Especificación de claves y ejecución de búsqueda

TTModelBag tModelBag = new TModelBag();
tModelBag.add(new TModelKey(tModelKey));
Vector serviceInfoVector = null;
try{
  ServiceList myServiceList = 
    proxy.find_service(null, null, null, tModelBag, null, 0);
  serviceInfoVector = 
    myServiceList.getServiceInfos().getServiceInfoVector();
}catch (org.uddi4j.transport.TransportException te){
  // ...
}catch (org.uddi4j.UDDIException ue){
  // ...
}

Una vez ubicados uno o más servicios, puede obtener información importante sobre el servicio desde el objeto ServiceInfo.

Listado 6: ServiceInfo

ServiceInfo serviceInfo = (ServiceInfo) serviceInfoVector.get(i);
Name name = serviceInfo.getName();
String serviceName = name.getText();
String serviceNameLanguage = name.getLang();

También puede obtener la clave del servicio. La clave del servicio define a un servicio en el registro, de manera única. Se puede usar la clave del servicio para recuperar el servicio del registro.

Nota:
La recuperación de un servicio de detalla en la sección "Generalidades" de este tutorial.

Listado 7: Obtención de la clave del servicio

String serviceKey = serviceInfo.getServiceKey();

La clave del negocio de la businessEntity a la cual se asignó el servicio (en otras palabras, una referencia a la empresa que provee este servicio), también se incluye en el objeto ServiceInfo.

Listado 8: Obtención de la clave de la empresa

String businessKey = serviceInfo.getBusinessKey();

Ubicación de BusinessEntity

El método find_business()

Se puede ubicar BusinessEntity a través de UDDI4J mediante el uso de find_business() de la clase UDDIProxy. La firma de este método es:

public BusinessList find_business(Vector names, 
DiscoveryURLs d, IdentifierBag i, CategoryBag c, TModelBag t, 
FindQualifiers f, int maxRows)

Se pueden buscar empresas por nombre, discoveryURL, identificador, categoría, tModel o cualquier combinación de estos parámetros. Se pueden ingresar valores nulos para aquellos parámetros que no participan de la búsqueda.

La BusinessList (Listado de negocios) que find_business() devuelve

El método find_Business() devuelve un objeto org.uddi.response.BusinessList. Los objetos BusinessList contienen un objeto org.uddi.response.BusinessInfos que contiene un java.util.Vector que contiene cero o más objetos org.uddi.response.BusinessInfo.

La siguiente muestra presenta un objeto BusinessList serializado a un árbol DOM (Modelo de Objetos para la representación de Documentos):

<businessList generic="2.0" operator="www.mycompany.com/uddi" truncated=
"false" xmlns="urn:uddi-org:api_v2">
  <businessInfos>
    <businessInfo businessKey="23290FC9-3D1B-44E6-BFD7-1DB73279188E">
      <name xml:lang="en">DVDOnline</name>
      <description xml:lang="en">Online DVD store</description>

      <serviceInfos>
        <serviceInfo businessKey="23290FC9-3D1B-44E6-BFD7-1DB73279188E" 
serviceKey="1CAD11A5-3E75-4172-92B7-1B862B3B06F8">
          <name xml:lang="en-US">OrderDVD</name>
	 </serviceInfo>
      </serviceInfos>

    </businessInfo>
  </businessInfos>
</businessList>

Ubicar empresas por ubicación geográfica

En el ejemplo de programación siguiente, las empresas se localizan en base a la ubicación geográfica y a las primeras tres letras del nombre de la empresa. Se crea un objeto org.uddi4j.util.KeyedReference para definir la categoría de EEUU. El modelo tModelKey para esta referencia se activa mediante el uso de setTModelKey() y de la provisión de UUID para esta taxonomía.

Se definieron varios UUID como variables estáticas en la clase TModel. El UUID para tModel que describe la ubicación geográfica, se define como ISO_CH_TMODEL_KEY.

También se pueden definir múltiples referencias para usar en la búsqueda. Todas las referencias se agregan a un objeto org.uddi4j.util.CaregoryBag y luego se pasan al método find_business().

Listado 9: Búsqueda por ubicación geográfica

KeyedReference reference = new KeyedReference();	
reference.setKeyName("United States");
reference.setKeyValue("US");
reference.setTModelKey(TModel.ISO_CH_TMODEL_KEY);
CategoryBag categoryBag = new CategoryBag();
categoryBag.add(reference)

Uso de calificadores de búsqueda

El argumento findQualifiers es una Collection de calificadores. Estos calificadores se definen en la interfaz FindQualifier. Los valores posibles incluyen: exactNameMatch,caseSensitiveMatch,sort_byNameAsc,sortByDateDesc, y muchos otros.

También se puede usar FindQualifiers para cambiar el comportamiento predeterminado de las relaciones entre los distintos parámetros de búsqueda. Por ejemplo, cuando se ingresan categorías múltiples como parámetros de búsqueda de manera predeterminada, la búsqueda devuelve todos los negocios que correspondan a todas las categorías provistas (AND [Datos de Navegación Automática] lógicas). Se puede usar FindQualifiers para cambiar esto a un OR lógico, de ser necesario, mediante la incorporación del calificador orAllKeys.

Listado 10: Uso de calificadores de búsqueda

FindQualifier findQualifier = new FindQualifier();
findQualifier.setText(FindQualifier.sortByDateDesc);
FindQualifiers findQualifiers = new FindQualifiers();
findQualifiers.add(findQualifier);

Ubicación de empresas por nombre

En el siguiente ejemplo de programación, se ubican empresas en base a las primeras tres letras del nombre de la empresa.

Para ubicar una empresa en base al nombre, se crea un objeto org.uddi4j.datatype.Name. Esta búsqueda particular busca todas las empresas cuyo nombre en español comience con DVD. Con esta finalidad, se especifica el idioma en el objeto Name como es (español). Dado que se pueden definir múltiples nombres sobre los cuales efectuar la búsqueda, se agregan objetos Name múltiples a un objeto java.uitl.Vector y luego se lo pasa al método find_business().

Listado 11: Búsqueda por nombre

Name name = new Name();
name.setText("DVD%");
name.setLang("es");
Vector names = new Vector();
names.add(name);
Vector businessInfoVector = null;
try{
  BusinessList businessList = 
    proxy.find_business(names, null, null, categoryBag, null, 
                        findQualifiers, 0);
  businessInfoVector  = 
    businessList.getBusinessInfos().getBusinessInfoVector();
}catch (org.uddi4j.transport.TransportException te){
  // ...
}catch (org.uddi4j.UDDIException ue){
  // ...
}

Obtención de información de empresas

La información contenida en el objeto BusinessInfo contiene el nombre predeterminado de BusinessEntity.Se debe observar que este nombre no es siempre el mismo idioma que el idioma a través del cual se efectuó la búsqueda de la empresa.

Listado 12: El objeto BusinessInfo

BusinessInfo businessInfo = (BusinessInfo) businessInfoVector.get(i);
Name name = businessInfo.getName();
String businessName = name.getText();
String businessNameLanguage = name.getLang();

La clave de negocios para esta BusinessEntity en particular también se incluye en el objeto BusinessInfo. Esta clave define esta entrada en el registro de manera no equitativa y se puede usar para recuperar BusinessEntity del registro.

Listado 13: La clave del negocio

String businessKey = businessInfo.getBusinessKey();

La descripción de este modelo también está disponible en el objeto BusinessInfo.

Listado 14: Descripción de negocios

Vector descriptionVector = businessInfo.getDescriptionVector();
for (int j = 0; j < descriptionVector.size(); j++) {
  Description description = (Description) descriptionVector.get(j);
  String descriptionText = description.getText();
  String descriptionLanguage = description.getLang();
  // ...
}

Finalmente, se puede obtener un objeto ServiceInfos del objeto BusinessInfo. Tal como se describiera anteriormente, cuando se buscan servicios, un objeto ServiceInfos contiene cero o más objetos ServiceInfo que proveen información de servicios básica. El objeto ServiceInfos, obtenido del objeto BusinessInfo, contiene información sobre los servicios que este negocio provee.

Listado 15: Los objetos ServiceInfo

ServiceInfos serviceInfos = businessInfo.getServiceInfos();
for (int j = 0; j < serviceInfos.size(); j++) {
  ServiceInfo serviceInfo = serviceInfos.get(j);
  // ...
}

Obtención de información detallada mediante el uso de UDDI4J

Generalidades

En las secciones anteriores de este tutorial, se ubicaron negocios, servicios y modelos técnicos. La información devuelta por estas búsquedas, sólo contenían información muy básica con respecto a las entradas de registros. En ambos casos, se devolvió el UUID de la entrada.

Al usar este UUID, se puede recuperar el objeto BusinessEntity,BusinessService, o el tModel propiamente dicho, del registro. Recuperar información detallada de estos objetos es bastante sencillo.

Esta sección provee generalidades sobre la información en un objeto BusinessEntity,ServiceEntity y en un TModel, y sobre cómo obtenerla.

BusinessDetail

Se usan dos métodos get_businessDetail() de la clase UDDIProxy para recuperar entidades de negocios del registro. Un método requiere sólo un objeto String que representa una clave de negocios. El otro método requiere un objeto java.util.Vector que contenga uno o más valores String, en el que cada uno representa una clave de negocios.

Ambos métodos devuelven un objeto org.uddi4j.response.BusinessDetail. El objeto BusinessDetail contiene cero o más objetos BusinessEntity. (El Vector contiene cero objetos cuando no se encuentra ningún negocio para la(s) clave(s) provista(s).

Listado 16: Obtención de detalles de empresas

BusinessDetail businessDetail = null;
try{
  businessDetail = proxy.get_businessDetail(businessKey);
}catch(  ... ){
  //...
}
Vector businessEntityVector = 
  businessDetail.getBusinessEntityVector();
if(businessEntityVector.size() > 0){
  BusinessEntity businessEntity = 
   (BusinessEntity) businessEntityVector.get(0);

Además del nombre de la empresa, de la clave de la empresa y de la información descriptiva, el objeto BusinessEntity contiene información de contacto para cualquier persona que se pueda conectar por esta empresa.

Listado 17: Obtener información de contactos de negocios

Contacts contacts = businessEntity.getContacts();
for (int i = 0; i $lt; contacts.size(); i++) {
  Contact contact = (Contact) contacts.get(i);
  // ...
}

Los DiscoveryURLs para este BusinessEntity también están disponibles en el objeto BusinessEntity.

Listado 18: Obtención de discovery URLs

DiscoveryURLs discoveryURLs = businessEntity.getDiscoveryURLs();
for (int i = 0; i < discoveryURLs.size(); i++) {
  DiscoveryURL discoveryURL = (DiscoveryURL) discoveryURLs.get(i);
  // ...
}

ServiceDetail

Se puede recuperar un BusinessService del registro de casi la misma forma en que se recupera BusinessEntity. Se usa una o más claves de servicio como parámetros para el método get_serviceDetail().

El método devuelve un objeto org.uddi4j.response.ServiceDetail que contenga un objeto java.util.Vector. El Vector contiene cero o más objetos org.uddi4j.datatype.service.BusinessService. (El vector contiene cero objetos cuando no se encuentran servicios, con clave(s) de servicio dada(s), en el registro).

Listado 19: Obtención de detalles de servicio

ServiceDetail serviceDetail = null;
try{
  serviceDetail = proxy.get_serviceDetail(serviceKey);
}catch(  ...  ){
  // ...
}
Vector businessServiceVector = 
  serviceDetail.getBusinessServiceVector();

Una vez que se obtiene un objeto BusinessService, se puede acceder a la información detallada sobre este servicio mediante la invocación de métodos de obtención en este objeto.

Listado 20: Obtención de información detallada

BusinessService businessService = 
   (BusinessService) businessServiceVector.get(0);
  BindingTemplates bindingTemplate = 
   businessService.getBindingTemplates();

Estructura de datos businessService

En vez de repasar todos los métodos individuales del objeto BusinessService, la muestra siguiente presenta la estructura del objeto BusinessService. Se puede acceder a cada elemento y atributo individual a través de UDDI4J API. También muestra la relación entre la información desde la cual se pueden comprender los distintos objetos que se pueden obtener del objeto BusinessService, y las relaciones entre ellos.

<businessService businessKey="24851C0A-0E73-469A-9805-0635125C00B3" 
serviceKey="302813FA-0ECB-49A9-A4D8-3D3F18F03627">
    <name xml:lang="en">OrderDVD</name>
    <bindingTemplates>
      <bindingTemplate bindingKey="2294343A-03D6-4980-B92A-3E0D0EFB15B9" 
serviceKey="302813FA-0ECB-49A9-A4D8-3D3F18F03627">
	 <accessPoint URLType="http">
          http://localhost:6080/DVDOnline/services/OrderDVD
        </accessPoint>
	 <tModelInstanceDetails>
          <tModelInstanceInfo tModelKey=
          "UUID:1B830749-20BB-4F97-BADF-24353B5424E8"/>
        </tModelInstanceDetails>
      </bindingTemplate>

    </bindingTemplates>
    <categoryBag>
      <keyedReference keyName="United States" keyValue="US" tModelKey=
      "UUID:4E49A8D6-D5A2-4FC2-93A0-0411D8D19E88"/>
    </categoryBag>
</businessService>

<businessService businessKey="24851C0A-0E73-469A-9805-0635125C00B3" 
serviceKey="302813FA-0ECB-49A9-A4D8-3D3F18F03627">
	<name xml:lang="en">OrderDVD</name>
	<bindingTemplates>
		<bindingTemplate bindingKey="2294343A-03D6-4980-B92A-3E0D0EFB15B9" 
serviceKey="302813FA-0ECB-49A9-A4D8-3D3F18F03627">
			<accessPoint URLType="http">
				http://localhost:9080/DVDOnline/services/OrderDVD
			</accessPoint>
			<tModelInstanceDetails>
				<tModelInstanceInfo tModelKey=
				"UUID:1B830749-20BB-4F97-BADF-24353B5424E8"/>
			</tModelInstanceDetails>
		</bindingTemplate>
	</bindingTemplates>

	<categoryBag>
		<keyedReference keyName="United States" keyValue="US" tModelKey=
"UUID:4E49A8D6-D5A2-4FC2-93A0-0411D8D19E88"/>
	</categoryBag>
</businessService>

TModelDetail

Luego de recuperar BusinessEntity y BusinessService,recuperar TModel no debería ser un problema.

El método get_tModelDetail() de la clase UDDIProxy requiere una o más claves tModel. Se puede proveer una sola clave como un objeto String, o proveer un objeto java.util.Vector que contenga una o más claves.

El método devuelve un objeto org.uddi4j.response.TModelDetail que contenga un objeto java.util.Vector. El Vector contiene cero o más objetos TModel, cada uno de los cuales representa un solo modelo técnico. (El Vector contiene cero objetos cuando no se encuentran modelos para la(s) clave(s) tModel provista(s).

Listado 21: Obtención de TModelDetail

TModelDetail tModelDetail = null;
try{
  tModelDetail = proxy.get_tModelDetail(tModelKey);
}catch(Exception e){
  // ...
}   
Vector tModelVector = tModelDetail.getTModelVector();

Una vez obtenido el objeto TModel, se puede acceder a información detallada sobre este servicio, mediante la invocación de métodos de obtención en este objeto.

Listado 22: Obtención de detalles

TModel tModel = (TModel) tModelVector.get(0);
Name name = tModel.getName();
// ...

Estructura de datos tModel

En vez de repasar todos los métodos individuales del objeto TModel, la muestra siguiente presenta su estructura. Se puede acceder a cada elemento y atributo individual a través de UDDI4J API. También muestra las relaciones entre la información desde la cual se puede comprender los distintos objetos que se pueden obtener del objeto TModel.

<tModel authorizedName="admin" operator="www.mycompany.com/uddi" 
tModelKey="UUID:1B830749-20BB-4F97-BADF-24353B5424E8">
    <name>Online DVD Order</name>
    <description xml:lang="en">Service for ordering DVDs online</description>
    <overviewDoc>
      <description xml:lang="en">
        WSDL document for Order DVD Service
      </description>
      <overviewURL> 
        http://localhost:6080/DVDOnline/services/OrderDVDService.wsdl
      </overviewURL>
    </overviewDoc>
    <categoryBag>
      <keyedReference keyName=
      "Specification for a Web Service described in WSDL" keyValue=
      "wsdlSpec" tModelKey="UUID:C1ACF26D-9672-4404-9D70-
      39B756E62AB4"/>
    </categoryBag>
</tModel>

<tModel authorizedName="admin" operator="www.mycompany.com/uddi" 
tModelKey="UUID:1B830749-20BB-4F97-BADF-24353B5424E8">
<name>Online DVD Order</name>
<description xml:lang="en">Service for ordering DVDs online</description>
<overviewDoc>
<description xml:lang="en">
WSDL document for Order DVD Service
</description>
<overviewURL>
http://localhost:6080/DVDOnline/services/OrderDVDService.wsdl
</overviewURL>
</overviewDoc>
<categoryBag>
<keyedReference keyName=
"Specification for a Web Service described in WSDL" keyValue=
"wsdlSpec" tModelKey="UUID:C1ACF26D-9672-4404-9D70-
39B756E62AB4"/>
</categoryBag>
</tModel>

Laboratorio 1: Publicación de servicios web a un registro UDDI

Creación de servicios

Para lograr los objetivos deseados habrá dos servicios que representen servicios ligeramente distintos a los descritos anteriormente. En este ejemplo se muestran dos tiendas de DVD, DVD Online America y DVD Online Australia. Estos servicios devuelven precios por un DVD específico, aceptan pedidos por un DVD específico e indican si la compra se aprobó o no. Ambos servicios cumplen con el descriptor estándar llamado OrderDVDService.wsdl, que se puede encontrar en el proyecto OrderDVD. Este descriptor ofrece la siguiente funcionalidad a la cual se deben ajustar los dos servicios.

Esta funcionalidad se divide en tres partes:

  • getDVDId -- Dado un título de un DVD, éste devuelve un identificador único de ese DVD específico para ese servicio.
  • getDVDPrice -- Dado un identificador de un DVD, éste devuelve un precio específico de ese servicio para ese DVD.
  • orderDVD -- Dado un identificador de un DVD, éste coloca un pedido de un DVD específico mediante el uso de ese servicio.

Estos son los proyectos que es necesario configurar para publicar y recuperar los servicios, así como también sus relaciones:

  • OrderDVD -- es la base para el código de detección del cliente, describe el aspecto del servicio.
  • OrderDVDAU -- es la implementación australiana del servicio.
  • OrderDVDUS -- es la implementación de EEUU del servicio.
  • PublishUDDI -- se usa para publicar las descripciones, servicios y TModel de negocios.
  • DiscoverUDDI -- se usa para detectar los servicios y usarlos. Cuenta con el proyecto OrderDVD.

Los dos servicios se describen principalmente en las siguientes clases:

  • com.ibm.wsad.tutorial4.ex1.webservice.OrderDVDServiceUS
  • com.ibm.wsad.tutorial4.ex1.webservice.OrderDVDServiceAU

Estas dos clases son muy sencillas y tienen los siguientes métodos (que corresponden a la descripción del servicio visto anteriormente en el descriptor WSDL):

  • public int getDVDId(String dvdName) -- obtener DVD ID dada una cadena
  • public double getDVDPrice(int dvdID) -- obtener el precio de un DVD
  • public String orderDVD(int dvdID) -- pedir un DVD

Una vez implantado servicios web, es necesario agregar negocios, servicios y modelos técnicos al registro. En particular, es necesario agregar dos servicios al registro que describan OrderDVDUS y OrderDVDAU Web services y todas las entradas de soporte para estos servicios, tales como modelos técnicos. Naturalmente se proveerá un programa que se ocupará de hacer todo eso.

El programa que se ofrece efectúa las siguientes entradas en el registro:

  • Un modelo técnico llamado DVDOnlineModel que describe las especificaciones del pedido de DVD Online
  • Un BusinessEntity llamado: DVDOnline America
  • Un servicio OrderDVDUS, ofrecido por la empresa DVDOnline America
  • Un BusinessEntity llamado: DVDOnline Australia
  • Un servicio OrderDVDAU, ofrecido por la empresa DVDOnline Australia
  • Un modelo técnico ficticio llamado DummyModel
  • Un negocio ficticio llamado Dummy Business
  • Un servicio ficticio llamado Dummy Service

Los modelos, negocios y servicios Dummy se crean sólo para propósitos de prueba. Si el registro estuviera vacío, a excepción de la información ingresada, sería demasiado fácil efectuar una consulta para captar la información de vuelta. Las entradas ficticias no se deben devolver, por lo tanto eso obliga a efectuar una consulta verdadera.

Para ahorrar algo de tiempo, se provee además WSDL para el servicio Online DVD Order (Pedido de DVD online). De no tener WSDL, use un portal UDDI para ubicar el modelo técnico deseado y descargar o copiar el documento WSDL de la URL definida en el modelo técnico.

Activar todo

Primero, descargar y descomprimir el código fuente (ver Recursos) para este laboratorio. Contiene todos los archivos necesarios para ejecutar este laboratorio. Es necesario importar algunos de estos archivos hacia nuevos proyectos que se crearán en Application Developer. Es necesario importar todos los proyectos al espacio de trabajo, comenzando con OrderDVD. Elegir File > Import y luego seleccione El proyecto existente. Una vez que aparece el cuadro de diálogo, se podrá navegar hacia donde se descomprimió el código fuente, elegir entonces el proyecto OrderDVD e importarlo. Se debería encargar de retener todas las configuraciones.

El paso siguiente es el de avanzar y generar las clases de cliente desde el archivo WSDL. Para esto, buscar el archivo WSDL bajo Web Content/WEB-INF/OrderDVDService.wsdl y haga clic con el botón derecho sobre el archivo. De esta lista de opciones elegir Web Services > Generate Client. Este preguntará qué archivo EAR (Archivo Enterprise) se desea colocar en el mismo. Si no se ve OrderDVDEAR, avanzar y crear uno nuevo con ese nombre y permitir que Application Developer lo cree. Una vez completado, se deberá ver un nuevo árbol de origen bajo JavaSource llamado com.ibm.wsad.tutorial4.ex1.service que contiene todo el código del cliente. Esto incluye lo siguiente:

  • OrderDVDService -- Es la interfaz que se usa para las llamadas remotas de Java.
  • OrderDVDServiceService -- La interfaz JAX-RPC remota para el servicio.
  • OrderDVDServiceSoapBindingStub -- La implementación del servicio mediante el uso de llamadas del método SOAP.
  • OrderDVDServiceServiceLocator -- El localizador de clases que se usa para buscar el servicio que implementa la interfaz OrderDVDServiceService.
  • OrderDVDServiceProxy -- La clase Proxy que se usa para buscar en el servicio y devolver la información apropiada.

El resto de los proyectos no requieren la generación de ningún código fuente, por lo tanto se puede avanzar e importarlos de a uno por vez. Pero se lo deberá hacer de manera secuencial. Seguidamente será deseable importar el proyecto PublishUDDI, luego los dos servicios, los proyectos EAR asociados (OrderDVDUS_EAR y OrderDVDAU_EAR) y finalmente el proyecto DiscoverUDDI. Cuando se importe el proyecto DiscoverUDDI, se debe asegurar que cuenta con el proyecto OrderDVD mediante la selección del nombre del proyecto, luego haga clic con el botón derecho y elegir propiedades. Una vez que se abra la ventana de propiedades para ese proyecto ir a la opción Java Build Path y seleccionar la pestaña Projects (Proyectos). Aparecerá una marca de verificación al lado de OrderDVD. De no aparecer, ponga una y luego haga clic en OK para que el proyecto reconstruya con la nueva dependencia.

Configuración del registro y publicación de los servicios

Ahora es necesario registrar con IBM UDDI Test Registry de manera de poder usarlo para publicar y luego recuperar los servicios registrados. Primero, se necesita un ID de Usuario IBM y una contraseña (se puede usar la misma que se usó cuando se registró para este tutorial). Una vez obtenido User ID, vaya a la página IBM UDDI Test Registry e ingresar. Esto asegurará tener un User ID correcto y que se puede usar el servicio. De surgir algún problema al ingresar, contactar a IBM para pedir ayuda.

Una vez que se haya ingresado al registro de prueba y verificado su funcionamiento, es necesario poblar el registro. Para ello se usa el proyecto PublishUDDI, específicamente com.ibm.wsad.tutorial4.ex1.publish.Publisher.

public class Publisher{
  public static void main(String[] args) {
    PublishDVDOnlineTModel pdot = new PublishDVDOnlineTModel();
    String modelKey = pdot.publishTModel();
	
    PublishDVDOnlineUS pdou = new PublishDVDOnlineUS();
    String businessKey = pdou.publishBusinessEntity();
    pdou.publishBusinessService(businessKey, modelKey);

    PublishDVDOnlineAU pdoa = new PublishDVDOnlineAU();
    businessKey = pdoa.publishBusinessEntity();
    pdoa.publishBusinessService(businessKey, modelKey);

    PublishDummyModel dummyModel = new PublishDummyModel();
    String dummyModelKey = dummyModel.publishTModel();
    PublishDummy dummy = new PublishDummy();
    businessKey = dummy.publishBusinessEntity();
    dummy.publishBusinessService(businessKey, dummyModelKey);

  }
}

Esto intenta publicar TModel, Servicios y Negocios así como también modelos ficticios, servicios y negocios tal como se observara anteriormente. Esto es lo que hace el resto de las clases.

  • PublishDVDOnline -- Configura la conexión al registro UDDI para su publicación
  • PublishDVDOnlineUS -- Publica la empresa y al servicio asociado DVDOnline America; extiende PublishDVDOnline
  • PublishDVDOnlineAU -- Publica la empresa y el servicio asociado DVDOnline Australia; extiende PublishDVDOnline
  • PublishDVDOnlineTModel -- Publica el modelo técnico para DVD Order online

Veamos de cerca a PublishDVDOnline.

public class PublishDVDOnline {
    //UDDI proxy object representing the UDDI registry.
    protected static UDDIProxy proxy;

    //Paths to inquiry and publish api.
    private static String publishURLsecure = 
    "https://uddi.ibm.com/testregistry/publishapi";

    //UDDI User ID and password.
    protected static String uddiUserID = "test@com.com";
    protected static String uddiPassword = "password";

    // trustStoreDirPath depends on the location of the application server
    // which is obtained by reading the System property "wsdk.app.server.home".
    private String trustStoreDirPath  = null;
    private static final String trustStoreFilename = "DummyClientTrustFile.jks";
    private static final String trustStorePassword = "WebAS";

    private BusinessDetail businessDetail = null;

  public PublishDVDOnline() {
    setEnvironment();
    setupProxy();
  }
  
  protected void setEnvironment(){
    //Set appserver username and password
    System.setProperty("http.basicAuthUserName", uddiUserID);
    System.setProperty("http.basicAuthPassword", uddiPassword);

    //Add SSL as a supported protocol.
    System.setProperty("java.protocol.handler.pkgs", 
    "com.ibm.net.ssl.internal.www.protocol");
    Security.addProvider(new IBMJSSEProvider());

  }

  protected void setupProxy(){
    //set up proxy
    proxy = new UDDIProxy();
       try{
         proxy.setPublishURL(publishURLsecure);
       } catch (MalformedURLException e) {
            System.out.println(
            "MalformedURLException was thrown when attempting to 
            set the UDDI proxy's URL");
            System.out.println(e.getMessage());
            System.exit(1);
        }
  }

    protected String getAuthorization(String usr,String pwd){
        //Get authorization token
        String authInfo=null;
        try{
            AuthToken authToken = proxy.get_authToken(usr,pwd);
            authInfo = authToken.getAuthInfoString();
        }catch (Exception e){
            System.out.println(
            "An exception was thrown when getting the authorization token:\n"+e);
            e.printStackTrace();
            System.exit(1);
        }
        return authInfo;
    }
}

Como se puede ver, existen dos variables que almacenan el ID de Usuario y la contraseña; antes de ejecutar Publisher, cámbielas al ID y a la contraseña que usaba para ingresar al registro de prueba. Una vez hecho esto se estará listo para ejecutar el programa. Dado que se configuró todo, es más fácil ejecutarlo directamente desde el interior de Application Developer. Pero antes de hacer eso, es necesario cambiar el JRE (Entorno Java de tiempo de ejecución) bajo el cual se ejecuta; no va a afectar a nada más, sólo logrará que el Publisher se ejecute correctamente. Para cambiar JRE, haga clic en Window > Preferences y luego elija Java > Installed JREs. El elegido será WebSphere 5.1 JRE (tal vez sea necesario abrir esa descripción un poco para ver cuál elegir).

Ya se está todo listo para ejecutar Publisher. Haga clic en Run > Run As > Java Application.

Esto inicia Publisher con todas las dependencias JAR adecuadas y luego conecta al IBM Test Registry.

Una vez conectado, el programa indica si hubo algún problema al publicar al registro. Si no surgieron problemas, se estaría en condiciones de ingresar al registro una vez más y ver los nuevos servicios. Si se quiere, se puede navegar por las entradas, pero toda la información que se ingresó fue a través de las clases Java que se usaron en PublishUDDI.


Laboratorio 2: Detectar servicios web desde un registro UDDI

Ejecución de servicios web

Una vez publicados los servicios web, se necesita alguna forma de buscarlos. Se puede configurar un simple client para que lo realice, pero primero es necesario estar seguro que los servicios estén activos y en ejecución.

La forma más sencilla de hacer esto es la de implantarlos en Application Developer, tal como se hiciera anteriormente. Se describirá cómo hacer esto primero con OrderDVDUS, pero las instrucciones son idénticas a las usadas para OrderDVDAU. Haga clic con el botón derecho sobre el nombre del proyecto y elegir Run on Server (Ejecutar sobre el servidor). Surgirá entonces un cuadro de diálogo similar al que se ve a continuación

Desde aquí elegir OrderDVDUS_EAR si estuviera disponible como opción de implante; de no ser así, hay que estar seguro de crear un nuevo proyecto EAR para cada servicio (OrderDVDUS_EAR y OrderDVDAU_EAR respectivamente), luego continuar e implantar esto al servidor de prueba WebSphere. Una vez implantado se estará en condiciones de navegar hacia el mismo mediante el uso del Web Services Explorer que se usó en los tutoriales anteriores para asegurar que el servicio esté activo y en ejecución. Simplemente repetir esta acción también para el servicio australiano.

El client

Se ha llegado al objetivo principal de este ejercicio. El programa cliente que es, de hecho, el que efectúa las consultas y usa los servicios. Nuevamente, se proveerá un código y se lo repasará clase por clase, se lo construirá y ejecutará contra el ejemplo de DVD configurado. Las clases que componen el programa son:

  • Locator -- configura la conexión al registro UDDI para consultas.
  • ModelLocator -- ubica al modelo técnico basándose en el nombre del modelo.
  • ServiceLocator -- ubica todos los servicios mediante la implementación de un modelo dado y encuentra las URL de los servicios actuales.
  • BusinessLocator -- recupera y visualiza información sobre un negocio.
  • BuyDVD -- encuentra un servicio web que ofrezca DVD al precio más bajo y pide el DVD a través del Servicio.
  • BuyDVDClient -- clase principal del programa que inicia todo.

Conexión al registro – la clase Locator

La conexión al registro en este punto, es relativamente sencilla. Tal como se hiciera anteriormente, se usa la clase UDDIProxy para crear la conexión. En el programa esto se implementa mediante la clase Locator de la cual todas las otras clases Locator forman subclases.

Listado 23: Clase Locator

package com.ibm.wsad.tutorial4.ex1.inquiry;

import java.net.MalformedURLException;
import java.security.Security;

import org.uddi4j.client.UDDIProxy;

import com.ibm.jsse.IBMJSSEProvider;

public class Locator {
    //UDDI proxy object representing the UDDI registry.
    protected static UDDIProxy proxy;

    //Paths to inquiry and publish api.
    private static String inquiryURL = 
    "http://uddi.ibm.com/testregistry/inquiryapi";
	
  public Locator(){
    setupProxy();
  }
  
  /**
   * Setup UDDIProxy for Inquiry operations
   */
  public void setupProxy(){
    proxy = new UDDIProxy();
       try{
         proxy.setInquiryURL(inquiryURL);
       } catch (MalformedURLException e) {
            System.out.println(
            "MalformedURLException was thrown when attempting to 
            set the UDDI proxy's URLs");
            System.out.println(e.getMessage());
            System.exit(1);
        }
  }
}

Ubicación del modelo técnico – clase ModelLocator

ClassName: ModelLocator

Methods: 
  public public String findTModel(String tModelName);

Esta clase va al registro y recupera una clave para un modelo técnico, en este caso DVDOnlineModel, en base al nombre del modelo. Esto se efectúa mediante el uso del método find_tModel() de un objeto UDDIProxy. El código hace lo siguiente:

  • A fin de asegurar que se use la última versión implantada del modelo técnico, se crea un FindQualifier, el cual ordena el resultado por fecha (en orden descendiente).
  • Se llama find_tModel() a un objeto UDDIProxy para obtener un vector de objetos TModelInfo para el nombre dado.
  • El primer objeto del vector se selecciona y se extrae la clave.

Una vez ubicado el modelo, se obtiene y devuelve la clave de este tModel. Estas claves se usarán para buscar BusinessServices que cumplan con este modelo técnico.

Listado 24:Clase ModelLocator

package com.ibm.wsad.tutorial4.ex1.inquiry;

import java.util.Vector;

import org.uddi4j.UDDIException;
import org.uddi4j.response.TModelInfo;
import org.uddi4j.response.TModelList;
import org.uddi4j.transport.TransportException;
import org.uddi4j.util.FindQualifier;
import org.uddi4j.util.FindQualifiers;

public class ModelLocator extends Locator {

  public ModelLocator() {
    super();
  }

  /**
   * Locate a technical Model on the model name
   * @param tModelName the Name of the Model to search for
   * @return The tModelKey of the object located
   */
    public String findTModel(String tModelName){
      Vector tModelInfoVector = null;

      //Define findQualifier, to make sure the most recent model is 
      //on top of the list
      FindQualifier findQualifier = new FindQualifier();
      findQualifier.setText(FindQualifier.sortByDateDesc);
      FindQualifiers findQualifiers = new FindQualifiers();
      findQualifiers.add(findQualifier);

      String tModelKey = null;
      try{
          //find model based on Name and findQualifiers
          TModelList tModelList = 
          proxy.find_tModel(tModelName, null, null, findQualifiers, 0);
          tModelInfoVector  = tModelList.getTModelInfos().getTModelInfoVector();
        }catch(TransportException t){
          System.out.println("TransportException while Locating Model:\n"+ t);
          System.exit(1);
        }catch(UDDIException ue){
          System.out.println("UDDIException while Locating Model:\n"+ ue);
          System.exit(1);
        }

      if(tModelInfoVector.size() > 0){
        TModelInfo tModelInfo = (TModelInfo) tModelInfoVector.get(0);
        tModelKey = tModelInfo.getTModelKey();
      }else{
        System.out.println("No Technical Models found for Name: " + tModelName);
        System.exit(1);
      }

      return tModelKey;
    }
}

Ubicación de servicios – la clase ServiceLocator

ClassName: ServiceLocator

Methods: 
  public Map findServices(String tModelName)
  public Map getServiceURL(Set serviceKeySet)

Se pueden hallar servicios que sigan el modelo técnico elegido cuando se consulte al registro por servicios que implementen ese modelo. Se pueden hallar múltiples servicios cuando se busquen servicios por modelo técnico. (En el entorno de demostración, se deberían hallar dos servicios). Para cada uno de los servicios hallados, las servicekey y businesskey, de la empresa que provee esos servicios, se recuperan y almacenan en un HashMap. Mantener la clave de la empresa a mano para poder recuperar BusinessDetail directamente sin tener que consultar nuevamente el registro.

Los servicios se buscan con el método findServices() que hace lo siguiente:

  1. Encuentra el modelo mediante el uso de un objeto ModelLocator.
  2. Consulta al registro por servicios mediante el uso del método UDDIProxy.find_service() y del modelo técnico que encontró anteriormente.
  3. Extrae el servicio y claves del negocio del vector de objetos ServiceInfo devueltos por find_service().

Listado 25: Clase ServiceLocator

package com.ibm.wsdk.tutorial7.ex1.inquiry;

import com.ibm.wsdk.tutorial7.ex1.util.*;

import java.util.*;
import org.uddi4j.*;
import org.uddi4j.transport.*;
import org.uddi4j.response.*;
import org.uddi4j.util.*;
import org.uddi4j.datatype.*;
import org.uddi4j.datatype.service.*;
import org.uddi4j.datatype.binding.*;

public class ServiceLocator extends Locator {

  public ServiceLocator() {
    super();
  }

  /**
   * Find all services implementing the specified technical Model
   * The method returns a HashMap. Each entry is a serviceKey and the 
   * businessKey of the
   * BusinessEntity providing this service
   * @param tModelName
   * @return HasMap, containing serviceKey - businessKey pairs.
   */
  public Map findServices(String tModelName){
    ModelLocator modelLocator = new ModelLocator();
    String tModelKey = modelLocator.findTModel(tModelName);
    TModelBag tModelBag = new TModelBag();
    tModelBag.add(new TModelKey(tModelKey));
    Vector serviceInfoVector = null;
    try{
      ServiceList myServiceList = 
       proxy.find_service(null, null, null, tModelBag, null, 0);
      serviceInfoVector  = 
       myServiceList.getServiceInfos().getServiceInfoVector();
    }catch(TransportException t){
        // ...
    }catch(UDDIException ue){
        // ...
    }
    if(serviceInfoVector.size() == 0){
      System.out.println("No Services found that comply to Model: " + 
                          tModelName);
        // ...
    }
    Map serviceKeys = new HashMap();
    for (int i = 0; i < serviceInfoVector.size(); i++) {
       ServiceInfo serviceInfo = 
        (ServiceInfo) serviceInfoVector.get(i);
       String serviceKey = serviceInfo.getServiceKey();
       String businessKey = serviceInfo.getBusinessKey();
       serviceKeys.put(serviceKey, businessKey);
    }
    return serviceKeys;
  } // end findServices

  // class definition continued in next panel ...

package com.ibm.wsad.tutorial4.ex1.inquiry;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.uddi4j.UDDIException;
import org.uddi4j.datatype.Name;
import org.uddi4j.datatype.binding.AccessPoint;
import org.uddi4j.datatype.binding.BindingTemplate;
import org.uddi4j.datatype.service.BusinessService;
import org.uddi4j.response.ServiceDetail;
import org.uddi4j.response.ServiceInfo;
import org.uddi4j.response.ServiceList;
import org.uddi4j.transport.TransportException;
import org.uddi4j.util.TModelBag;
import org.uddi4j.util.TModelKey;

public class ServiceLocator extends Locator {

  public ServiceLocator() {
    super();
  }

  /**
   * Find all services implementing the specified technical Model
   * The method returns a HashMap. Each entry is a serviceKey 
   * and the businessKey of the
   * BusinessEntity providing this service
   * @param tModelName
   * @return HasMap, containing serviceKey - businessKey pairs.
   */
  public Map findServices(String tModelName){
        ModelLocator modelLocator = new ModelLocator();
        String tModelKey = modelLocator.findTModel(tModelName);

        TModelBag tModelBag = new TModelBag();
        tModelBag.add(new TModelKey(tModelKey));

        Vector serviceInfoVector = null;
        try{
            ServiceList myServiceList = 
            proxy.find_service(null, null, null, tModelBag, null, 0);
            serviceInfoVector  = 
            myServiceList.getServiceInfos().getServiceInfoVector();
        }catch(TransportException t){
          System.out.println("TransportException while Locating Service:\n"+ t);
          System.exit(1);
        }catch(UDDIException ue){
          System.out.println("UDDIException while Locating Service:\n"+ ue);
          System.exit(1);
        }

        if(serviceInfoVector.size() == 0){
          System.out.println("No Services found that comply to Model: " + tModelName);
          System.exit(1);
        }
        Map serviceKeys = new HashMap();
        for (int i = 0; i < serviceInfoVector.size(); i++) {
          ServiceInfo serviceInfo = (ServiceInfo) serviceInfoVector.get(i);

          Name name = serviceInfo.getName();

          String serviceKey = serviceInfo.getServiceKey();
          String businessKey = serviceInfo.getBusinessKey();

          serviceKeys.put(serviceKey, businessKey);
        }

        return serviceKeys;
    }

    /**
     * Get the URL of the actual service, given the UUID of a BusinessService
     * @param Set ServiceKeys of the BusinessService(s)
     * @return Map with URL-serviceKey pairs
     */
    public Map getServiceURL(Set serviceKeySet){
      Vector serviceKeys = new Vector(serviceKeySet);
      return getServiceURL(serviceKeys);
    }
    /**
     * Get the URL of the actual service, given the UUID of a BusinessService
     * @param Vector ServiceKeys of the BusinessService(s)
     * @return Map with URL-serviceKey pairs
     */
    public Map getServiceURL(Vector serviceKeys){
      Vector businessServices = null;
      Map urlMap = new HashMap();

      try{
        ServiceDetail serviceDetail = proxy.get_serviceDetail(serviceKeys);
        businessServices = serviceDetail.getBusinessServiceVector();
      }catch(TransportException t){
        System.out.println("TransportException while getting ServiceDetail:\n"+ t);
        System.exit(1);
      }catch(UDDIException ue){
        System.out.println("UDDIException while getting ServiceDetail:\n"+ ue);
        System.exit(1);
      }
        if(businessServices.size() == 0){
            System.out.println("Failed to find business services");
            System.exit(1);
        }

        for (int j = 0; j < businessServices.size(); j++) {
          BusinessService businessService = (BusinessService) businessServices.get(j);
          String serviceKey = businessService.getServiceKey();

          Vector bindingTemplateVector=
          businessService.getBindingTemplates().getBindingTemplateVector();
          BindingTemplate bindingTemplate = null;
          for(int i=0; i<bindingTemplateVector.size(); i++) {
              // find the binding template with an http access point
              bindingTemplate = (BindingTemplate)bindingTemplateVector.elementAt(i);
              AccessPoint accessPoint = bindingTemplate.getAccessPoint();
              if(accessPoint.getURLType().equals("http")) {
                urlMap.put(accessPoint.getText(),serviceKey);
              }
          }
        }
        return urlMap;
    }
}

Obtención de la URL del servicio – la clase ServiceLocator

ClassName: ServiceLocator

Methods: 
  public Map findServices(String tModelName)
  public Map getServiceURL(Set serviceKeySet)

Para poder acceder al servicio web, se requiere la URL del servicio. La URL del servicio URL se encuentra dentro de un objeto BusinessService. Una vez ubicados todos los servicios apropiados, la URL de acceso a cada servicio se obtiene del objeto BusinessDetail para cada uno de estos servicios.

Al vector que contenga todos los servicios encontrados se lo pasa al método UDDIProxy.get_serviceDetail(). Al usar un vector de nombres, todos los objetos ServiceDetail para estos servicios se recuperan en una sola llamada al registro.

Para cada objeto ServiceDetail recuperado, el punto de acceso URL se obtiene y almacena en otro HashMap junto con la clave del servicio perteneciente a esta URL. La URL funciona como la clave de cada objeto en HashMap. Mediante el almacenamiento de esta información, se puede hallar fácilmente el serviceKey perteneciente a la URL, más adelante en la aplicación.

La aplicación también controla el tipo de URL de cada punto de acceso, y de ese modo asegura que sólo se almacenen puntos de acceso de tipo http en HashMap.

Listado 26: Clase ServiceLocator

/**
   * Get the URL of the actual service, given the UUID of a BusinessService
   * @param Set ServiceKeys of the BusinessService(s)
   * @return Map with URL-serviceKey pairs
   */
  public Map getServiceURL(Set serviceKeySet){
    Vector serviceKeys = new Vector(serviceKeySet);
    return getServiceURL(serviceKeys);
  }
   /**
   * Get the URL of the actual service, given the UUID of a BusinessService
   * @param Vector ServiceKeys of the BusinessService(s)
   * @return Map with URL-serviceKey pairs
   */
  public Map getServiceURL(Vector serviceKeys){
    Vector businessServices = null;
    Map urlMap = new HashMap();
     try{
      ServiceDetail serviceDetail = proxy.get_serviceDetail(serviceKeys);
      businessServices = serviceDetail.getBusinessServiceVector();
    }catch(TransportException t){
     }catch(UDDIException ue){
      // ...
    }
    if(businessServices.size() == 0){
      System.out.println("Failed to find business services");
      // ...
    }
    for (int j = 0; j < businessServices.size(); j++) {
      BusinessService businessService = (BusinessService) businessServices.get(j);
      String serviceKey = businessService.getServiceKey();
      Vector bindingTemplateVector=
      businessService.getBindingTemplates().getBindingTemplateVector();
      BindingTemplate bindingTemplate = null;
      for(int i=0; i<bindingTemplateVector.size(); i++) {
        // find the binding template with an http access point
        bindingTemplate = 
        (BindingTemplate)bindingTemplateVector.elementAt(i);
        AccessPoint accessPoint = bindingTemplate.getAccessPoint();
        if(accessPoint.getURLType().equals("http")) {
          urlMap.put(accessPoint.getText(),serviceKey);
        }
      } // end for
    } // end for
      return urlMap;
  } // end getServiceURL

} // end ServiceLocator

Obtención de información de negocios – la clase BusinessLocator

ClassName: BusinessLocator

Methods: 
  public void showBusinessDetail(String businessKey)

Cuando una aplicación hace un pedido, es necesario visualizar información sobre la empresa que provee este servicio. Se obtiene esta información mediante la recuperación del objeto BusinessDetail de la empresa, al usar businessKey como clave.

Al tener las claves de la empresa guardadas del objeto ServiceDetail, no es necesario buscar a la empresa ya que la businessEntity apropiada puede recuperarse del registro en forma directa.

El código es sencillo, sólo que un poco largo. Se recupera BusinessDetail a través de proxy mediante el uso de la clave de la empresa. El objeto de detalles se usa entonces para recuperar distintos detalles sobre la empresa que se visualizarán entonces.

Listado 27: Clase BusinessLocator

package com.ibm.wsdk.tutorial7.ex1.inquiry;

import java.util.*;
import org.uddi4j.*;
import org.uddi4j.transport.*;
import org.uddi4j.response.*;
import org.uddi4j.util.*;
import org.uddi4j.datatype.*;
import org.uddi4j.datatype.business.*;

public class BusinessLocator extends Locator {

  public BusinessLocator(){
    super();
  }
  /**
   * Display business information of a BusinessEntity
   * @param businessKey the businessKey of the BusinessEntity
   */
  public void showBusinessDetail(String businessKey){

    BusinessDetail businessDetail = null;

    try{
      // Get the business detail from the registry based on the key
      businessDetail = proxy.get_businessDetail(businessKey);
    }catch(TransportException t){
      // ... 
    }catch(UDDIException ue){
      // ...
    }

    // Get the first business entity returned
    Vector businessEntityVector = 
    businessDetail.getBusinessEntityVector();
    if(businessEntityVector.size() == 0){
      System.out.println("Could not locate business for businessKey: " + businessKey);
      // ...
    }
    BusinessEntity businessEntity = 
    (BusinessEntity) businessEntityVector.get(0);

    // Display business name
    Vector businessNames = businessEntity.getNameVector();
    for (int i = 0; i < businessNames.size(); i++) {
      Name businessName = (Name) businessNames.get(i);
      System.out.println("Business Name : " + businessName.getText() + 
                         "(Languag: " + businessName.getLang() +")");
    }

    // Display descriptions
    Vector descriptions = businessEntity.getDescriptionVector();
    for (int i = 0; i < descriptions.size(); i++) {
      Description description = (Description) descriptions.get(i);
      System.out.println("Description:\n" + description.getText());
    }

    // Display contacts
    System.out.println("Contacts for this Business");
    Contacts contacts = businessEntity.getContacts();
    for (int i = 0; i < contacts.size(); i++) {
      Contact contact = (Contact) contacts.get(i);
      System.out.println("Name: " + contact.getPersonName().getText()
             + " Role: " + contact.getUseType());
      Vector emailVector = contact.getEmailVector();
      for (int j = 0; j < emailVector.size(); j++) {
        Email email = (Email) emailVector.get(j);
        System.out.println("Email: " + email.getText() + "
           (" + email.getUseType() + ")");
      }
    } // end for

  } // end showBusinessDetail

} // end BusinessLocator

Uso de servicios web -- la clase BuyDVD

ClassName: BuyDVD

Methods: 
  private Map getServiceAccessPoints()  
  private OrderDVDService getOrderDVDService(String urlString)
  public void orderDVD(String dvdTitle)

Toda la programación realizada hasta este momento consiste sólo en ubicar y recuperar información del registro. Finalmente se está cerca de utilizar los servicios web que se hayan recuperado. La clase BuyDVD hace eso. Usa la clase ServiceLocator para recuperar un HashMap que contenga URLs y las serviceKeys de los servicios apropiados, tal como se muestra a continuación.

Listado 28: Clase BuyDVD

package com.ibm.wsad.tutorial4.ex1.inquiry;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.ibm.wsad.tutorial4.ex1.OrderDVDService;
import com.ibm.wsad.tutorial4.ex1.OrderDVDServiceServiceLocator;

public class BuyDVD{
  private static final String tModelName = "DVDOnlineModel";
  private Map serviceMap = null; //Map of ServiceKey-BusinessKey pairs

  /**
   * Get the ServiceURLs for all available services
   * @return HashMap containing URL-serviceKey pairs
   */
  private Map getServiceAccessPoints(){
      Map urls = new HashMap();

      //Locate services for the Technical Model specified
      ServiceLocator serviceLocator = new ServiceLocator();
      serviceMap = serviceLocator.findServices(tModelName);

      //Get a set of service keys
      Set serviceSet = serviceMap.keySet();
      urls = serviceLocator.getServiceURL(serviceSet);
      System.out.println("Number of services found: " + serviceMap.size());
      return urls;
  }

Creación de objetos OrderDVDService – la clase BuyDVD

ClassName: BuyDVD

Methods: 
  private Map getServiceAccessPoints()
  private OrderDVDService getOrderDVDService(String urlString)
  public void orderDVD(String dvdTitle)

Una vez que las URL estén disponibles, se crean los objetos DVDOnlineService. Se debe recordar que el código para la clase DVDOnlineService se generó mediante el asistente de servicios web según el documento WSDL del modelo técnico. Finalmente, con el objeto de servicios creado aquí se puede, de hecho, invocar al servicio.

Listado 29: Clase BuyDVD

/**
   * Create a OrderDVDService object, to communicate with the Web service, defined 
   * by the URL
   * @param urlString The URL of the webservice
   * @return An OrderDVDService object.
   */
  private OrderDVDService getOrderDVDService(String urlString){
     OrderDVDServiceServiceLocator serviceLocator = new OrderDVDServiceServiceLocator();
     
     OrderDVDService orderDVDService = null;
     try{
       URL url = new URL(urlString);
       orderDVDService = serviceLocator.getOrderDVDService(url);
    } catch (MalformedURLException e) {
      System.out.println(
      "MalformedURLException was thrown when attempting to 
      locate web service");
      System.out.println(e.getMessage());
      System.exit(1);
    } catch(javax.xml.rpc.ServiceException se){
      System.out.println(
      "ServiceException was thrown when attempting obtain web service");
      System.out.println(se.getMessage());
      System.exit(1);
    }

    return orderDVDService;
  }}

Uso del servicio – la clase BuyDVD

ClassName: BuyDVD

Methods: 
  private Map getServiceAccessPoints()
  private OrderDVDService getOrderDVDService(String urlString)
  public void orderDVD(String dvdTitle)

Una vez creados los objetos OrderDVDService, implementar la parte restante del cliente es codificación Java directa. Se obtiene un conjunto de objetos OrderDVDService y se invoca el método getDVDId() sobre cada uno para obtener el ID para este DVD.

Una vez que el ID esté disponible, se llama al método getDVDPrice(int dvdID) para conseguir el precio de un DVD. Se verifica el conjunto completo de servicios recuperados y se recuerda el servicio que ofrece el precio más bajo, junto con el precio y el serviceKey. Finalmente, se invoca el método orderDVD(int dvdID) sobre el OrderDVDService guardado.

Dado que se guardó el serviceKey del servicio con el precio más bajo, se puede usar HashMap que contenga pares serviceKey - businessKey guardados anteriormente para obtener el BusinessDetail de la empresa mediante la provisión de este servicio, el cual deberá desplegar en ese momento,.

Todo listo. Se consultó con éxito un registro para un servicio en particular. Se recuperaron servicios que proveen la funcionalidad deseada y se pidió un DVD mediante el uso del servicio.

Listado 30: Clase BuyDVD

/**
   * Find the web services that offers the DVD for the lowest price 
   * and order the DVD
   * through this service
   * @param dvdTitle Title of DVD to be ordered
   */
  public void orderDVD(String dvdTitle){

    //Obtain all access points for services providing this service
    Map accessPoints = getServiceAccessPoints();

    //Create a set of accespoints
    Set accessSet = accessPoints.keySet();
    Iterator it = accessSet.iterator();

    double lowestPrice = Double.MAX_VALUE;
    OrderDVDService cheapestService = null;
    String keyCheapestService = null;
    int dvdID = -1;

    // Go through all the services, and find the one with the lowest price.
    while(it.hasNext()) {
      //For each access point, create an OrderDVDService object
      String accessPoint = (String) it.next();
      OrderDVDService service = getOrderDVDService(accessPoint);

      try{
        //Ask for price of DVD
        dvdID = service.getDVDId(dvdTitle);
        double price = service.getDVDPrice(dvdID);

        //When price lower then prices found sofar, save price and information 
        //   about service
        if(price < lowestPrice){
          lowestPrice = price;
          //Reference to OrderDVDService object
          cheapestService = service;
          //Obtain serviceKey from BusinessService (registry key)
          //Later used to locate business, which provides this service
          keyCheapestService = (String) accessPoints.get(accessPoint);
        }
      }catch(java.rmi.RemoteException rme){
        System.out.println(
        "RemoteException was thrown when invoking service");
        System.out.println(rme.getMessage());
        System.exit(1);
      }
    } // end while

    if(cheapestService == null){
      System.out.println("The cheapest service could not be located.....");
      // ...
    }

    //Order DVD through cheapest web service
    String orderResult = null;
    try{
      orderResult = cheapestService.orderDVD(dvdID);
    }catch(java.rmi.RemoteException rme){
      System.out.println(
      "RemoteException was thrown when invoking service");
      System.out.println(rme.getMessage());
      System.exit(1);
    }

    // Print out our info !
    System.out.println("-------------------------------------------");
    System.out.println("The Lowest price found is: " + lowestPrice);
    System.out.println("-------------------------------------------");
    System.out.println("Order status for " + dvdTitle + " DVD: " + orderResult);
    System.out.println("-------------------------------------------");
    System.out.println("Business through which DVD was ordered");
    System.out.println("-------------------------------------------");
    //Obtain the businessKey of the BusinessEntity, providing the service
    //(This information was saved, when obtaining accesspoints
    String businessKey = (String) serviceMap.get(keyCheapestService);

    //Locate the BusinessEntity
    BusinessLocator businessLocator = new BusinessLocator();
    //Display information about this business
    businessLocator.showBusinessDetail(businessKey);

  } // end orderDVD

} // end class BuyDVD

  /**
   * Find the web services that offers the DVD for the lowest price and 
   * order the DVD through this service
   * @param dvdTitle Title of DVD to be ordered
   */
  public void orderDVD(String dvdTitle){
    //Obtain all access points for services providing this service
    Map accessPoints = getServiceAccessPoints();

    //Create a set of accespoints
    Set accessSet = accessPoints.keySet();
    Iterator it = accessSet.iterator();

    double lowestPrice = Double.MAX_VALUE;
    OrderDVDService cheapestService = null;
    String keyCheapestService = null;
    int dvdID = -1;

    while(it.hasNext()) {
      //For each access point, create an OrderDVDService object
      String accessPoint = (String) it.next();
      System.out.println("Access Point :: " + accessPoint);
	  OrderDVDService service = getOrderDVDService(accessPoint);
      

      try{
        //Ask for price of DVD
        dvdID = service.getDVDId(dvdTitle);
        double price = service.getDVDPrice(dvdID);
        //When price lower then prices found sofar, save price and 
        //information about service
        if(price < lowestPrice){
          lowestPrice = price;
          //Reference to OrderDVDService object
          cheapestService = service;
          //Obtain serviceKey from BusinessService (registry key)
          //Later used to locate business, which provides this service
          keyCheapestService = (String) accessPoints.get(accessPoint);
        }
      }catch(java.rmi.RemoteException rme){
        System.out.println(
        "RemoteException was thrown when invoking service");
        System.out.println(rme.getMessage());
        System.exit(1);
      }
    }

    if(cheapestService == null){
      System.out.println("The cheapest service could not be located.....");
      System.exit(1);
    }

    //Order DVD through cheapest web service
    String orderResult = null;
    try{
      orderResult = cheapestService.orderDVD(dvdID);
    }catch(java.rmi.RemoteException rme){
        System.out.println(
        "RemoteException was thrown when invoking service");
        System.out.println(rme.getMessage());
        System.exit(1);
      }

    System.out.println("-------------------------------------------");
    System.out.println("The Lowest price found is: " + lowestPrice);
    System.out.println("-------------------------------------------");
    System.out.println("Order status for " + dvdTitle + " DVD: " + orderResult);
    System.out.println("-------------------------------------------");
    System.out.println("Business through which DVD was ordered");
    System.out.println("-------------------------------------------");
    //Obtain the businessKey of the BusinessEntity, providing the service
    //(This information was saved, when obtaining accesspoints
    String businessKey = (String) serviceMap.get(keyCheapestService);

    //Locate the BusinessEntity
    BusinessLocator businessLocator = new BusinessLocator();
    //Display information about this business
    businessLocator.showBusinessDetail(businessKey);

  }
}

El programa cliente – la clase BuyDVDClient

ClassName: BuyDVDClient

Methods: 
  public static void main(String[] args)

BuyDVDClient es una clase pequeña que inicia el proceso. Toma como argumento el título del DVD que se busca, luego crea una instancia de BuyDVD e inicia toda la cadena de eventos observados hasta aquí.

En realidad, el título no tiene en verdad ningún efecto, ya que la clase de implementación del servicio es trivial. Pero ese no es el punto – el objetivo es buscar e invocar al servicio. La clase BuyDVDClient.

Listado 31: Clase BuyDVDClient

package com.ibm.wsdk.tutorial7.ex1.inquiry;

import java.util.*;

public class BuyDVDClient{
  public static void main(String[] args) {
    if(args.length < 1){
      System.out.println("Usage\n   BuyDVDClient <dvdTitle>");
    }

    BuyDVD buyDVD = new BuyDVD();
    buyDVD.orderDVD(args[0]);

  }
}

package com.ibm.wsad.tutorial4.ex1.inquiry;


public class BuyDVDClient{
  public static void main(String[] args) {
    if(args.length < 1){
      System.out.println("Usage\n   BuyDVDClient <dvdTitle>");
    }

    BuyDVD buyDVD = new BuyDVD();
    buyDVD.orderDVD(args[0]);
	

  }
}

Ejecución de cliente

Tal como se ejecutó el cliente de Publisher, también se puede ejecutar el código BuyDVDClient directamente desde dentro de Application Developer. Para ejecutar el programa:

  • Asegurarse que se haya iniciado el servidor.
  • Desde el menú Run arriba de todo, elija Run.
  • Elija Java Application a la izquierda y luego seleccione la pestaña Arguments.
  • Escriba el título de la película que se desea adquirir (en este punto puede ser cualquiera, por lo tanto escribir Meatballs).

Se debería ver algo así como lo siguiente (con el programa invocado como MeatBalls):

Number of services found: 2
-------------------------------------------
The Lowest price found is: 19.95
-------------------------------------------
Order status for MeatBalls DVD: Order has been accepted
-------------------------------------------
Business through which DVD was ordered
-------------------------------------------
Business Name : DVDOnline America(Language: en)
Description:
Online DVD store based in the United States of America
Contacts for this Business
Name: Jack Smith Role: Director
Email: J.Smith@DVDOnlineUS.lpc(Business)

El programa pidió el DVD requerido desde la empresa DVDOnline America por 19.95 dólares estadounidenses!

¿De qué sirve esto?

Este ejemplo ilustra la utilidad de los servicios web. Se buscó a través del registro y se encontró, el precio más bajo de un DVD en particular, pedido anteriormente. ¿O no es así? Se acaba de pagar 19.95 dólares estadounidenses por el DVD, mientras que el precio del mismo DVD de la empresa australiana es de 24.95 dólares australianos.

Si el programa cliente hubiera ubicado y usado un convertidor de divisas de servicio web, capaz de convertir el valor de dólares australianos a dólares estadounidenses, el programa habría detectado que, de haber hecho el pedido a través de la empresa australiana, el DVD costaría sólo cerca de 14 dólares estadounidenses. Como tarea extra se podría hacer un repaso del programa de la siguiente manera: buscar un servicio que pueda efectuar esa conversión de divisas. Ahora bien, ¿no sería útil un servicio web capaz de ofrecer información sobre gastos de envío?


Resumen

Repaso

En este tutorial usted:

  • realizó una breve revisión de UDDI .
  • navegó por los registros internos de la edición integradora de WebSphere Studio Application Developer con UDDI GUI.
  • recibió una introducción a UDDI4J.
  • aprendió sobre partes importantes de UDDI4J API.
  • creó un programa que consulta registros mediante el uso de UDDI4J.
  • invocó servicios web recuperados en la consulta anterior.

UDDI es una especificación de temas complejos y UDDI4J es una API muy extensa. Aún con dos tutoriales sólo se alcanza a tratar sus capacidades de manera muy superficial. De todas maneras es un buen comienzo para empezar a entender UDDI, tanto desde una perspectiva de publicación, como de consultas. Trabajarlo y profundizar más aún en la documentación, permitirá continuar la exploración de sus capacidades.

En cierto nivel, se puede usar UDDI como cualquier otro servicio de nombres. Si bien esto es útil, hay mucho más en UDDI que lo que brevemente se mostró aquí. ¿Es esta capacidad realmente tan útil? Después de todo, es mucho trabajo para ahorrar sólo unos pocos pesos en un DVD.

Esto es definitivamente cierto, pero si se multiplica por miles de millones de transacciones, o si se considera cómo puede afectar al mercado B2B (Business to Business - transmisión de información referente a transacciones comerciales de manera electrónica), se verá que ésta es una tecnología que puede causar un gran impacto. El estado actual de UDDI no es todavía muy avanzado. Si bien la tecnología comienza a estar disponible, la infraestructura de negocios para su uso correcto, es virtualmente inexistente.

No hace mucho, comprar online estaba en esa misma situación. Para los primeros proveedores y consumidores de compras online, el esfuerzo seguramente superaba cualquier ventaja o ganancia que se obtuviera. Sin embargo ahora, se ha convertido en un aspecto clave en los hábitos de compra de los consumidores y en una ventaja (o desventaja) competitiva para muchas empresas.

UDDI tiene potencial para elevar el comercio electrónico a otro nivel. Ya existen sitios Web que salen a buscar artículos que se desean comprar basándose en distintos criterios. UDDI formaliza esto y provee la tecnología para hacerlo en un nivel mucho más sofisticado. Quizás algún día, en un futuro no muy lejano, solo se considerará comprar a empresas que provean servicios web registrados en registros UDDI y que ofrezcan un poder de compra más inteligente que nunca. La sensación es que no habrá que esperar demasiado.


Descargar

DescripciónNombretamaño
Source code for this tutorialws-soa-4code.zip24MB

Recursos

Aprender

Obtener los productos y tecnologías

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=681888
ArticleTitle=Construcción de SOA con servicios web usando WebSphere Studio, Parte 4: Detectar código en UDDI
publish-date=08052011