Proyecto de Integración
 

Integración con Servicios Web

Introducción

En esta sesión de integración vamos a ofrecer como servicio web algunas de las operaciones implementadas mediante EJBs en sesiones anteriores. También utilizaremos un servicio web externo para obtener información extendida sobre los libros de nuestra biblioteca. Por último, crearemos un cliente Java para nuestro servicio.

Nota
Para realizar el trabajo de esta sesión partiremos del resultado de la sesión de integración con JMS (aunque realmente no vamos a utilizar JMS, por lo que se podría partir del resultado de la integración con EJBs).

Creación de servicios web

Vamos a exponer como un servicio web SOAP la funcionalidad que obtiene información de los libros de nuestra biblioteca, implementada actualmente por un EJB. Dicho servicio, por lo tanto, podrá ser utilizado por otras aplicaciones (de nuestra empresa o fuera de ella).

CREAMOS EL PROYECTO

Comenzaremos creando un nuevo proyecto web Maven con los siguientes datos:

  • nombre: jbib-enterprise-ws
  • groupID: org.especialistajee.proyint
  • version: 1.0-SNAPSHOT
  • package: org.especialistajee.jbib.ws
  • server: Server jbib

MODIFICAMOS LAS DEPENDENCIAS DE LOS PROYECTOS

Nuestro proyecto necesita acceder al proyecto (va a depender de) jbib-enterprise-ejb por lo que añadiremos las dependencias correspondientes en nuestro pom. Pondremos el scope a provided. Con esto estamos indicando que el jar correspondiente se necesitará para compilar el proyecto jbib-web-services pero no se incluirá en el empaquetado final del mismo. Para añadir la dependencia tenemos dos opciones: (1) Modificamos directamente el fichero pom.xml e incluimos la nueva dependencia con la etiqueta <dependency>; (2) En el nodo Dependencies de nuestro proyecto, pinchamos con botón derecho y seleccionamos: Add Dependency...

Podemos visualizar gráficamente las dependencias de nuestro proyecto, situándonos sobre él y pinchando con botón derecho sobre Show Dependency Graph. En la figura mostrada, podemos pinchar sobre jbib-enterprise-ws y veremos lo siguiente:

Dependencias del proyecto jbib-enterprise-ws

También tenemos que añadir, en el proyecto jbib-enterprise-ear la dependencia con nuestro proyecto jbib-enterprise-ws, de la misma forma que hemos comentado (con la diferencia de que el scope debe ser el de por defecto, es decir, compile). Después de hacer las modificaciones, las dependencias de la aplicación enterprise serán:

Dependencias del proyecto jbib-enterprise-ear

Además, nuestro proyecto tiene que incluirse como un módulo de la aplicación proyint-jbib-enterprise. Añadimos la dependencia en el proyecto proyint-jbib-enterprise. De nuevo podemos optar por editar directamente el pom.xml. podemos añadir el módulo desde el nodo Modules del proyecto proyint-jbib-enterprise, seleccionando con botón derecho la opción Add Module...

Visualización de las dependencias de los proyectos Maven
Podéis ver las depenencias de cualquier proyecto Maven, pinchando con botón derecho sobre el proyecto y seleccionando Show dependency graph. Nos aparecerá un grafo con las dependencias de dicho proyecto, que podremos mostrar en varios niveles.

CREAMOS EL SERVICIO WEB

El proyecto jbib-enterprise-ws contendrá el servicio web que va a ofrecer dos operaciones, utilizando la funcionalidad de la implementación del ejb que hemos creado en sesiones anteriores. Los datos con los que crearemos nuestro servicio web serán:

  • Name: LibroWS
  • package: org.especialistajee.jbib.ws
  • Marcaremos Create WS from Existing Session Bean
  • Elegiremos el elemento LibroBO

Concretamente, las operaciones que deberá ofrecer este servicio serán (únicamente):

  • recuperaLibro
  • listaLibros

La operación recuperaLibro nos devuelve los datos del libro solicitado a partir de su isbn. La seguna operación permitirá a un cliente externo obtener los datos de todos los libros de nuestra biblioteca.

Tendremos que editar el código generado, comentado el resto de métodos, ya que por defecto, Netbeans ha expuesto como operaciones del servicio, todos los métodos del ejb que hemos seleccionado. Además, vamos a modificar el tipo del elemento que retornan las operaciones de nuestro servicio, para que devuelvan objetos de tipo LibroTO, y list<LibroTO>, respectivamente.

  • public LibroTO recuperaLibro(String isbn) throws LibroException
  • List<LibroTO> listaLibros() throws LibroException

El objeto LibroTO es un TransferObject (una clase java plana con atributos y sus correspondientes getters y setters. Esto nos permitirá tener control sobre las estructuras de datos que se serializan durante la llamada a los servicios y así evitar enviar información no necesaria o con un formato que no resulte adecuado para la conversión a XML. Utilizando entidades (como por ejemplo LibroDomain) tendremos problemas con los campos que relacionan dichas entidades con otras (relaciones uno a muchos). Por ejemplo, si devolvemos un LibroDomain, el servicio web generado intentará devolver también las operaciones activas y prerreservas, lo cual causará un problema al intentar recuperar esta información de forma lazy.

La clase LibroTO, en la que volcaremos los datos de nuestros objetos LibroDomain, se ubicará en el paquete org.especialistajee.jbib.ws del proyecto jbib-enterprise-ejb, y tendrá la siguiente información:

public class LibroTO implements Serializable {
    
    private String isbn;
    private String titulo;
    private String autor;
    private Integer numPaginas;
    
    //constructor vacío, necesario para que desde el 
    //servidor de aplicaciones se pueda crear una instancia
    //de LibroTO para devolver la respuesta    
    public LibroTO() {
    }

    public LibroTO(LibroDomain libro) {
    ...
    }
    
    //getters y setters

Podemos ver el wsdl generado por Glassfish al desplegar nuestro servicio accediendo a:

 http://localhost:9080/jbib-enterprise-ws/LibroWS?wsdl
 

Podemos probar el servicio creado con el cliente de pruebas que nos genera Glassfish al desplegar el servicio accediendo a:

 http://localhost:9080/jbib-enterprise-ws/LibroWS?tester
 

Acceso a servicios web externos

Vamos a añadir a la aplicación de la biblioteca la funcionalidad de obtener los detalles de un libro (portada, precio, editorial y fecha de publicación). Para hacer esto recurriremos a un servicio web (InfoLibroSWService) que hemos creado en el servidor de jtech para el curso de especialista, y al que denominaremos servicio web de Jtech.

Opcional
Si queréis probar el servicio web de Jtech lo podéis hacer accediendo a: http://server.jtech.ua.es:3700/servcweb-infoLibro-jtech/InfoLibroSWService?tester

Primero vamos a añadir un nuevo Transfer Object LibroInfoTO, en el paquete org.especialistajee.jbib.ws del proyecto jbib-enterprise-ejb:

public class LibroInfoTO implements Serializable{
    
    private String isbn;
    private float precio;
    private String imagen;
    private int imagenAncho;
    private int imagenAlto;
    private String editorial;
    private String anyoEdicion;
    
    //getters y setters

Creamos dentro del módulo EJB (jbib-enterprise-ejb) un cliente para acceder al servicio web de Jtech, cuyo documento WSDL se puede encontrar en la siguiente dirección:

http://server.jtech.ua.es:3700/servcweb-infoLibro-jtech/InfoLibroSWService?wsdl

Indicaremos que el paquete en el que deben generar las clases al ejecutar wsimport será: org.especialistajee.jbib.ws

Después de crear el cliente (y por lo tanto generar los stubs necesarios para acceder al servicio), tenemos que modificar el pom del proyecto jbib-enterprise-ejb, y añadir un nuevo directorio de recursos:

<build>
   <resources>
      ...
      <resource>
          <directory>src/main/resources</directory>
      </resource>
   </resources>
   ...
</build>   

Imporante. Modificaciones en el pom.xml
Por defecto, todos los ficheros incluidos en el directorio src/main/resources se copian en el directorio raíz del jar/war generado. Así, por ejemplo, podemos ver que en dicho directorio (podemos ir a la pestaña "Files", o bien desde la pestaña "Projects", pinchamos sobre el nodo "Other Sources") tenemos el fichero "META-INF/persistence.xml", que se copiará en el jar generado (ver el contenido del fichero "jbib-enterprise-ejb-1.0-SNAPSHOT.jar" en el directorio tarjet). Ahora bien, cuando creamos el cliente del servicio Web, lo que hace NetBeans de forma automática es modificar el pom añadiendo el plugin wsimport y ejecutar dicho pom, generando así los stubs. Además de incluir el plugin, de forma automática se modifica el directorio de recursos por defecto, de forma que en lugar de ser /src/main/resources, los nuevos recursos a copiar en el jar serán: el directorio src/wsdl, más el fichero src/jax-ws-catalog.xml. Por lo tanto, si no añadimos el directorio src/main/resources, el fichero persistence.xml (que antes de añadir el cliente del servicio Web, se copiaba por defecto en el jar) NO se añadirá en el jar generado, y como consecuencia fallará la ejecución del ejb.

Añadiremos una nueva operación recuperaInfoLibro en la interfaz local del ejb (ILibroBO):

org.especialistajee.jbib.ws.LibroInfoTO recuperaLibroInfo (String isbn) throws LibroException;

Y a continuación implementaremos dicho método en LibroBO.java. Aquí es donde incluiremos el código para llamar al servicio web de Jtech, concretamente tendremos que utilizar la operación buscaLibro, del servicio InfoLibroWSService. Dicha operación devuelve información detallada de un libro a partir de su isbn.

Importante. Bug de Glassfish
Debido a un bug de Glassfish, la inyección de la referencia al servicio web (anotación @WebServiceReference) no funciona correctamente, de forma que, al ejecutar el servicio web, el servidor no encuentra el wsdl asociado a dicha referencia. En consecuencia, las llamadas al objeto Service provocará una excepción. Para solucionar este problema tendremos que quitar la anotación @WebServiceReference, y en su lugar, crearemos "a mano" nosotros dicha instancia en lugar de dejar que Glassfish lo haga. Por lo tanto añadiremos la línea service = new InfoLibroSWService(); antes de realizar la llamada service.getInfoLibroSWPort().

Probamos el acceso al servicio Web externo

Para probar la llamada al servicio Web de Jtech, lo haremos desde un nuevo servlet, al que llamaremos InfoLibrosJtech, que crearemos en la aplicación web jbib-enterprise-web. Para crear el nuevo servlet utilizaremos los siguientes parámetros:

  • Name: InfoLibrosJtech
  • package: org.especialistajee.jbib.servlet
  • servletName: InfoLibrosJtech
  • servletName: InfoLibrosJtech
  • URL: /InfoLibrosJtech

El código del servlet hará una llamada a una instancia de LibroBO, accediendo al método recuperaLibroInfo utilizando, por ejemplo, el valor de isbn "0321180860". Se mostrarán por pantalla los datos: isb, editorial, año de edición, precio, dirección de descarga de la portada del libro. A continuación mostramos un ejemplo:

Resultado de la ejecución del servlet InfoLibrosJtech

Para mostrar la imagen con la portada, podéis utilizar un código similar a éste:

out.println("<img src= \""+imagen+"\" alt=\"Portada\">")

Siendo imagen la variable (de tipo String) que contiene la dirección url del fichero de imagen

Cliente para el servcio Web

Crear un cliente Java con Netbeans para el servicio web de la biblioteca (LibroWS), en un nuevo proyecto Maven Java al que llamaremos jbib-enterprise-ws-client.

El programa deberá invocar la operación listaLibros y mostrar en la consola el listado de libros.

De cada libro se mostrará su ISBN, su título, y su autor.

Resumen

Proyecto jbib-enterprise-ws

Proyecto jbib-enterprise-ejb

Proyecto jbib-enterprise-web

Proyecto jbib-enterprise-ws-client

Se deberá añadir un nuevo proyecto Maven Web jbib-enterprise-ws con el siguiente servicio web:

  • LibroWS: Servicio web que ofrecerá las operaciones recuperaLibro, listaLibros.

Se deberán añadir los siguientes componente al módulo jbib-enterprise-ejb:

  • LibroTO: Transfer Object con los datos detallados de un libro proporcionados por Jtech.
  • LibroInfoTO: Transfer Object con los datos detallados de un libro proporcionados por Jtech.
  • Cliente del servicio de Jtech: Stub para acceder a los servicios de Jtech.
  • operación recuperaInfoLibro, en LibroBO, que obtiene los datos detallados de un libro mediante el servicio de JTech

Se deberá añadir al proyecto Maven Web jbib-enterprise-web:

  • Servlet InfoLibrosJtech: para probar el cliente del servicio Web de Jtech desde el ejb.

Se deberá añadir un nuevo proyecto Maven Java jbib-enterprise-client-ws, que contendrá:

  • un cliente Java que acceda a nuestro servicio. Obtendrá la lista de todos los libros, y la mostrará por la consola
A entregar...
Deberéis entregar los proyectos jbib-enterprise-ejb, jbib-enterprise-ws, jbib-enterprise-web, jbib-enterprise-ws-client

Para la entrega se deberá etiquetar el estado del proyecto con el tag entrega-proyint-servc-web. Recordamos que la dirección del proyecto padre proyint-jbib en el servidor SVN debe ser:

svn+ssh://server.jtech.ua.es/home/svn/<login>/proyint/trunk/proyint-jbib