Introducción a los Servicios Web en Java (I): SOA

Con este artículo da comienzo el tutorial de introducción a los Servicios Web en Java. Los primeros artículos, que serán casi netamente teóricos, nos van a proporcionar la base de conocimiento necesaria para poder afrontar la cantidad brutal de especificaciones y herramientas que forman parte de, o están relacionadas con, los Servicios Web en Java. Serán estas especificaciones y herramientas las que darán forma a los artículos más técnicos, y en los que encontrarás multitud de ejemplos en código.

Muchos de los artículos técnicos serán (siempre que sea posible) autocontenidos, de manera que la tecnología que se trate en él pueda ser aplicada directamente sin tener una base previa y/o adicional. Sin embargo, todos en conjunto te darán una visión más amplia de los Servicios Web en Java, y te ayudarán a comprenderlos mejor (además de mostrarte otras posibilidades para resolver un mismo problema). El orden de publicación será (siempre que sea posible, again) el adecuado para que la curva de aprendizaje sea asequible.

En este primer artículo vamos a hacer una aproximación a la Arquitectura Orientada a Servicios y a su ingrediente esencial: el servicio.

1.1 Definiendo un servicio

Un servicio es un componente de software que, dependiendo de su tipo, puede tener una función mayor o menor. Sin embargo existen ciertas cualidades que suele cumplir todo servicio:

  • Está definido por una interface
  • Está disponible a través de una red
  • Opera sobre objetos de negocio
  • Puede ser decorado con funcionalidad adicional
  • Es reusable

Veamos una por una las cualidades anteriores.

Un servicio está definido por una interface, que actúa como un contrato para el uso de la misma (esto no es distinto de una interface estándar en Java). La interface puede ser dependiente de una plataforma (por ejemplo en un servicio EJB, donde sólo un cliente EJB podrá hacer uso del contrato) o por contra ser independiente de una plataforma (por ejemplo REST, que actúa sobre XML y HTML y por tanto puede ser accedida desde multitud de sistemas, por muy distintos que sean éstos).

Un servicio está disponible a través de una red, o lo que es lo mismo: puede ser accedido remotamente. Esto incluye a otras aplicaciones, otras máquinas, etc.

Un servicio opera sobre objetos de negocio, los cuales representan una parte tangible del problema de negocio que intentamos resolver. En un servicio que realice conversión de divisas entre dólares americanos (USD) y francos suizos (CHF) la divisa es el objeto de negocio y la conversión de divisas es el problema de negocio.

Un servicio puede ser decorado con funcionalidad adicional, de manera que le puedan ser aplicados requerimientos tanto funcionales como no funcionales. En un servicio SOAP hay disponibles multitud de especificaciones, como WS-ReliableMessaging y WS-SecureConversation, que proporcionan capas adicionales de seguridad a un servicio SOAP estandar.

Por último, un servicio debe ser reusable, con una funcionalidad atómica y bien definida. Ya seas arquitecto o programador, el concepto de reusabilidad debe ser tu mantra.

1.2 Definiendo SOA

La Arquitectura Orientada a Servicios (Service-Oriented Architecture, a partir de ahora SOA) es un tipo de arquitectura que utiliza servicios para facilitar la integración entre sistemas. El termino arquitectura en SOA debe ser tratado de forma distinta a como es tratado el termino objetos en Programación Orientada a Objetos: en éste último caso los objetos suelen ser tratados como una unidad de medida, como el resultado final y tangible de un problema de negocio. Por el contrario, cuando nos enfrentamos a SOA debemos pensar en términos más abstractos, en un cómo en lugar de un qué. En otras palabras, es un paradigma de diseño.

1.3 Identificando candidatos a servicio

Existen ciertas cuestiones que, cuando nos las planteamos, nos pueden resultar tremendamente útiles para determinar si un proyecto de software es un candidato a servicio:

  • ¿Va el servicio a ser consumido por distintas plataformas/sistemas?
  • ¿Pueden ser usados protocolos como HTTP?
  • ¿Van a ser salvadas barreras de integración implementando una funcionalidad como servicio (por ejemplo reemplazando o envolviendo una interface propietaria punto-a-punto)?
  • ¿Va a representar una carga demasiado pesada el proceso de tratamiento de datos desde y hacia XML?
  • ¿Va a permitir en el futuro que sea reusable, ya sea por otros proyectos o servicios de negocio?

Debes aprender a identificar que problemas de negocio deben ser solventados por SOA, y cuales no. Convertirlo todo en un servicio no es una buena idea, ya que al final acabarás manteniendo cientos o miles de servicios, muchos de ellos inútiles. Esto es conocido como tool trap (trampa de la herramienta), que dice que cuando tienes un martillo, todo parece un clavo.

1.4 Tipos de servicio

Podemos catalogar un servicio dado dentro de uno de los siguientes tres tipos:

  • De entidad
  • Funcional
  • De proceso

Veamos brevemente cada uno de ellos.

Un servicio de entidad representa aquel que actúa sobre entidades de negocio (objetos) los cuales tienen un determinado estado, comportamiento e identidad. Ejemplos de entidades de negocio son un cliente, una factura, un empleado, etc. Los servicios de entidad suelen realizar operaciones CRUD (Create-Read-Update-Delete, Crear-Leer-Actualizar-Eliminar) sobre las entidades de negocio.

Un servicio funcional, a diferencia de un servicio de entidad, actúa sobre una tecnología. Su propósito es proveer funcionalidad reusable y centralizada en la que otros servicios puedan confiar, y debe ser lo más autónomo posible. Un ejemplo es un servicio de envío de email.

Por último, un servicio de proceso es aquel que representa un conjunto de tareas relacionadas, y es visto como un conjunto de clientes de otros servicios o procesos (que a su vez pueden ser también clientes de otros servicios o procesos). Un ejemplo sería un servicio para procesar la contratación de un nuevo empleado, el cual haría uso de varios servicios para dar de alta al empleado, solicitar una nueva estación de trabajo al departamento de IT, enviar un correo electrónico informativo al departamento al que fuera a ser asignado el empleado, etc. Estas tareas deben estar íntimamente ligadas (ser parte del mismo proceso) para que, a pesar de ser un conjunto de servicios, podamos seguir viéndolo como atómico (cualidad que dijimos que debería tener todo servicio).

1.5 Modelando servicios

Una vez tenemos un candidato a servicio, debemos realizar el proceso de modelado. Para esta tarea, existen tres técnicas que son de utilidad: generalización, decomposición y agregación. Veamos brevemente cada una de ellas:

Mediante generalización analizamos un servicio para determinar qué representa conceptualmente. Es una técnica similar a la que utilizamos en Programación Orientada a Objetos para determinar relaciones de tipo es un. Por ejemplo, un cliente es una persona, y un empleado también es una persona, y a la hora de modelar nuestro servicio tenemos que encontrar el nivel adecuado de generalización.

Mediante decomposición analizamos un servicio para determinar si este está compuesto de múltiples elementos, y si estos estarían mejor definidos como servicios en si mismos. Cuanto más granulado sea un servicio, más posibilidades tendrá de ser reusado.

Mediante agregación analizamos un servicio para determinar otros servicios que puedan ser parte del primero. Es una técnica similar a la que utilizamos en Programación Orientada a Objetos para determinar relaciones de tipo tiene un. Esta técnica es útil para descubrir servicios componibles.

1.6 Servicios componibles

Decimos que un servicio es componible cuando se ha definido de manera que pueda ser reusado incluyéndolo en la implementación de otro servicio. La mejor forma de conseguir esto es asegurarnos que el servicio realiza una acción específica a un único caso de negocio. Un ejemplo es el de un sistema de pago con tarjeta de cŕedito que será invocado desde un punto de venta. Este sistema realizará varias acciones:

  • Invocará un servicio de pago con tarjeta de crédito, y cargará el importe de pago
  • Invocará un servicio que comprobará si esa tarjeta de crédito está asociada a una tarjeta de fidelización, y cargará en ésta un montante de puntos dependiendo del importe de pago

En el ejemplo anterior ambos servicios son componibles porque son usados de forma independiente y pueden ser reusados (mediante otra combinación o de forma independiente): una franquicia puede que no esté asociada al programa de puntos de fidelización, y en su lugar llame a un servicio que realiza un descuento directo en forma de abono; o tal vez podríamos aportar puntos de fidelización a un cliente por rellenar una encuesta cuando visite una página web. Si hubiéramos definido ambos servicios como uno solo diríamos que está altamente acoplado, ya que hay varios sistemas que dependen el uno del otro. Esto impide la reutilización de servicios, además de ser un mal diseño.

Un servicio no es siempre componible, pero durante su diseño debes recordar esta cualidad como una meta a tener siempre presente.

Resumen

En este primer artículo del tutorial de Servicios Web en Java hemos definido SOA y el concepto de servicio. Además, hemos visto algunas técnicas para identificar y modelar servicios, técnicas que pueden ser de mucha utilidad en el futuro. En el próximo artículo veremos en profundidad el lenguaje XML, una de las piedras angulares de los Servicios Web, así como algunas APIs de Java para trabajar con él.