J2EE 1.4 facilita el desarrollo de servicios web

Al concluir su presentación de servicios web J2EE (Java 2 Platform, Enterprise Edition) en JavaOne del año pasado, el arquitecto de IBM Jim Knutson comentó que "todo servicio web necesita un lugar para ser un servicio". Luego sugirió que el lugar más ideal para ser un servicio web era dentro de la infraestructura J2EE. Un poco más de un año después, el lanzamiento final de J2EE 1.4 es inminente y su promesa más importante es cumplir con la visión de los servicios web de J2EE.

Las características del servicio web en J2EE 1.4 se dirigen tanto al lado del servidor como del cliente de los servicios web. Las características amplían J2EE para permitir que los componentes Java empresariales del lado del servidor existentes se conviertan en servicios web y especifiquen cómo un contenedor de cliente J2EE puede invocar servicios web. Las tecnologías para ambos objetivos existen desde hace un tiempo, y las nuevas especificaciones J2EE se basan en las API existentes para el soporte de servicios web. Las nuevas especificaciones agregan a las tecnologías existentes un conjunto de requisitos de interoperabilidad y un modelo de programación e implementación para la integración de servicios web.

Hay dos especificaciones que describen explícitamente esas características añadidas: Java Specification Request 151, el JSR general para J2EE 1.4, y JSR 109, Web Services para J2EE. En el momento de escribir este artículo, JSR 109 ha llegado a su etapa final en el JCP (Java Community Process), mientras que JSR 151 se encuentra en la última fase de votación. Además, el JCP modificó la versión final de JSR 101, API de Java para llamadas a procedimiento remoto basadas en XML (JAX-RPC), para admitir los requisitos de interoperación de J2EE 1.4.

Los servidores de aplicaciones de nivel J2EE 1.3 también pueden implementar muchas de las características prescritas por estos JSR. De hecho, muchos proveedores de servidores de aplicaciones han admitido varias funciones de implementación y desarrollo de servicios web en sus productos existentes desde hace algún tiempo. Los JSR 109 y 151 codifican algunas prácticas existentes y describen nuevos mecanismos con la esperanza de crear un modelo universal de integración de servicios J2EE-Web. Los servidores de aplicaciones de próxima generación probablemente seguirán ese modelo unificado y estandarizado.

Tras un breve estudio de las nuevas funciones de J2EE relacionadas con los servicios web, este artículo revisa los nuevos modelos de programación de clientes y servidores, incluidos los nuevos roles de gestión de servicios y despliegue de J2EE asociados con el soporte de servicios web.

Extensiones J2EE relacionadas con el servicio web

Quizás las adiciones más importantes y de mayor importancia a J2EE son los nuevos requisitos de interoperación. Los requisitos prescriben el soporte para SOAP (Protocolo simple de acceso a objetos) 1.1 en la capa de presentación J2EE para facilitar el intercambio de mensajes XML. Los contenedores compatibles con J2EE 1.4 también deben admitir el perfil básico WS-I (Web Services Interoperability Consortium). Dado que el intercambio de mensajes XML en J2EE depende de JAX-RPC, las especificaciones de JAX-RPC ahora también exigen compatibilidad con WS-I Basic Profile.

El resultado es que una aplicación basada en J2EE 1.4 puede invocarse como un servicio web, incluso desde aplicaciones que no están escritas en el lenguaje de programación Java. Si bien ese es un paso evolutivo para J2EE, dado que la plataforma ha adoptado durante mucho tiempo sistemas que no están basados ​​en Java, es posiblemente la forma más directa de facilitar la interacción con tecnologías basadas en Windows que dependen de .Net.

El cliente de un servicio basado en J2EE no tiene que saber cómo se implementa un servicio. Más bien, ese cliente puede usar el servicio confiando completamente en la definición WSDL (Lenguaje de descripción de servicios web) del servicio. (Las columnas anteriores de JavaWorld Web Services explican cómo descubrir servicios en función de sus definiciones WSDL y cómo crear y usar definiciones WSDL. Consulte Recursos para obtener enlaces). Si bien las especificaciones de J2EE no explican la mecánica exacta de dicha interacción, J2EE 1.4 ' La adopción del perfil básico WS-I, que Microsoft también afirma seguir, probablemente hará que la interacción J2EE-.Net sea común.

Para facilitar el acceso a las definiciones WSDL, J2EE 1.4 agrega soporte para el estándar JAXR (API Java para registros XML). Las bibliotecas JAXR son ahora una parte necesaria del cliente de aplicación J2EE, EJB (Enterprise JavaBeans) y contenedores web (aunque no el contenedor de subprogramas). Dado que WS-I Basic Profile exige soporte para UDDI (Universal Description, Discovery e Integration) 2.0, los clientes J2EE, así como los componentes y servlets EJB, pueden interactuar con los registros de servicios web públicos. ("Web Services Take Float with JAXR" ( JavaWorld, mayo de 2002) ofrece un tutorial sobre JAXR.) La Figura 1 ilustra las bibliotecas adicionales relacionadas con los servicios Web compatibles con J2EE 1.4.

De hecho, J2EE considera que un servicio web es una implementación de una o más interfaces definidas por un documento WSDL. Las operaciones descritas en WSDL se mapean primero a los métodos Java siguiendo las reglas de mapeo WSDL a Java de la especificación JAX-RPC. Una vez que se define una interfaz Java correspondiente a un archivo WSDL, puede implementar los métodos de esa interfaz de una de estas dos formas: como un bean de sesión sin estado que se ejecuta en el contenedor EJB o como una clase Java que se ejecuta en el contenedor de servlets J2EE. Finalmente, usted hace arreglos para que el contenedor respectivo escuche las solicitudes SOAP entrantes y mapee esas solicitudes a la implementación respectiva (EJB o servlet). Para procesar las invocaciones SOAP entrantes, J2EE 1.4 exige el tiempo de ejecución JAX-RPC como un servicio de contenedor J2EE adicional.

De acuerdo con la arquitectura J2EE, el contenedor de una implementación de servicio media el acceso a un servicio web: si expone un componente EJB o un servlet como un servicio web J2EE, los clientes de su servicio pueden invocar ese servicio solo indirectamente, a través del contenedor. Eso permite que la implementación de un servicio se beneficie de la seguridad del contenedor, la gestión de subprocesos e incluso las garantías de calidad del servicio. Además, los contenedores le permiten tomar decisiones importantes sobre servicios web, como restricciones de seguridad, en el momento de la implementación. Por último, el modelo basado en contenedores de J2EE hace que la implementación de servicios web sea portátil: puede desarrollar un servicio web basado en Java utilizando cualquier herramienta J2EE y esperar que ese servicio se ejecute en cualquier otra implementación de contenedor compatible.

Un cliente de servicio web, por otro lado, desconoce la presencia de un contenedor de servicios web. En cambio, el cliente ve un puerto que representa una instancia de punto final de red de un servicio web. Ese punto final sigue el modelo de interfaz de punto final de servicio (SEI) JAX-RPC y proporciona una implementación de la interfaz del servicio. Un cliente ve cada servicio web J2EE como una combinación de puerto y SEI. Un solo contenedor J2EE puede albergar muchas de estas combinaciones, como ilustra la Figura 2. Cada combinación de SEI / puerto es una instancia de un servicio web.

Tenga en cuenta que el cliente en esta arquitectura puede ser un cliente J2EE, que se ejecuta dentro del contenedor del cliente J2EE, o un cliente que no es J2EE. Cualquier cliente compatible con WS-I Basic Profile puede utilizar un servicio web J2EE, pero cada cliente puede seguir diferentes modelos de programación. La especificación de servicios web J2EE describe un modelo de programación para clientes que se ejecutan dentro del contenedor de cliente de aplicaciones J2EE y otro modelo, el modelo de programación del servidor, para las implementaciones de servicios web que se ejecutan en los contenedores EJB o servlet.

El modelo de programación del cliente del servicio web J2EE

La esencia del modelo de programación de cliente de servicio web es optimizar el uso de las API definidas en JSR 67 (API Java para mensajería XML, JAXM), 93 (JAXR) y 101 (JAX-RPC), y proporcionar un marco integral para utilizando esas API juntas en el contenedor del cliente J2EE.

De acuerdo con el modelo de programación del cliente J2EE, un cliente de servicio web es remota y proporciona transparencia local / remota. El proveedor del puerto del servicio web y el contenedor en el que se ejecuta el puerto definen cómo ve un cliente un servicio web. El cliente siempre accede al puerto y nunca se le pasa una referencia directa a la implementación de un servicio web. Un cliente de servicio web J2EE no es consciente de cómo funciona un puerto y debe preocuparse solo por los métodos que define un puerto. Estos métodos constituyen la interfaz pública de un servicio web. Además, un cliente debe considerar el acceso a un puerto de servicio web como sin estado en todas las invocaciones de servicio. En lo que respecta al cliente, un puerto carece de una identidad única: un cliente no tiene forma de determinar si se comunica con puertos idénticos a través de las invocaciones de servicio.

El cliente obtiene acceso a un puerto basado en la interfaz de servicio del puerto. Los servicios web J2EE se basan en JAX-RPC para definir la relación entre un puerto y su interfaz de servicio. JAX-RPC crea esa relación basándose en las reglas de procesamiento de WSDL. Por tanto, la definición WSDL del servicio web rige en última instancia el comportamiento del puerto. Según la definición de JAX-RPC, la interfaz de servicio puede ser una interfaz genérica que implementa directamente la javax.xml.rpc.Serviceinterfaz o un "servicio generado", que es un subtipo de esa interfaz. El último tipo de interfaz es específico del tipo de servicio web.

En el modelo de programación J2EE, el cliente obtiene una referencia al objeto de un servicio web a Servicetravés de una operación de búsqueda JNDI (Java Naming and Directory Interface). La búsqueda JNDI se realiza mediante un nombre lógico o una referencia de servicio para el servicio web. Al igual que con todos los recursos basados ​​en directorios, un cliente debe declarar qué recursos necesita en su descriptor de implementación (más sobre esto más adelante).

La especificación de servicios web Java (JSR 109) recomienda que todos los servicios web se incluyan en el servicesubcontexto JNDI . El contenedor del cliente vincula la interfaz de servicio descrita por esa referencia en el java:comp/envcontexto de denominación del entorno del cliente. Al declarar una referencia de servicio en el descriptor de implementación del cliente, el contenedor del cliente garantiza que el servicio al que se hace referencia esté disponible en los recursos compatibles con JNDI. El siguiente fragmento de código muestra cómo obtener una referencia a un servicio web basado en J2EE a través de una búsqueda JNDI:

InitialContext ctx = new InitialContext (); Servicio myService = (Servicio) ctx.lookup ("java: comp / env / services / MyWebService");

El código anterior obtiene un objeto de servicio genérico: un objeto sin un tipo específico. Se accede a un servicio generado por JAX-RPC de la misma manera, esta vez lanzando el servicio al tipo de interfaz del servicio web específico:

InitialContext ctx = new InitialContext (); MyWebService myService = (MyWebService) ctx.lookup ("java: / comp / env / services / MyWebService");

Tenga en cuenta que este código asume que la MyWebServicereferencia se une a un objeto que implementa la MyWebServiceinterfaz. Dado que la vinculación de servicios se facilita en el momento de la implementación de un servicio web, se espera que las herramientas J2EE garanticen esa coherencia. Todos los servidores de aplicaciones compatibles con J2EE 1.4 deben admitir la búsqueda de servicios basada en JNDI.

Una vez que un cliente obtiene el Serviceobjeto de un servicio web , puede usar ese objeto para recuperar una javax.xml.rpc.Callinstancia que realiza la invocación del servicio real. El cliente tiene tres opciones para obtener una Call: a través de un stub, un proxy de servicio dinámico o una DII (Interfaz de invocación dinámica). No discutiré en este artículo las diferencias entre esos métodos, ya que, independientemente de cómo Callse cree, se Callrefiere directamente al puerto del servicio, el único objeto que el cliente debe tener en cuenta al invocar el servicio web. Todos los contenedores compatibles con J2EE 1.4 deben admitir los Servicemétodos de interfaz y, por lo tanto, permitir que un cliente obtenga una referencia a un Callobjeto para un servicio web y al puerto de ese servicio a través de Call.

Tenga en cuenta que, a diferencia de utilizar JAX-RPC fuera de J2EE, un cliente no debería utilizar la ServiceFactoryclase JAX-RPC para obtener un nuevo servicio. En su lugar, el cliente debe obtener acceso al Servicedesde una fuente basada en JNDI, ya que la referencia a un servicio recuperado de JNDI tendrá todos los valores y configuraciones necesarias para invocar la instancia de servicio en particular. Desde el punto de vista de un cliente, esa diferencia es algo análoga a cómo un cliente J2EE recupera un JDBC a DataSourcetravés de la interfaz JNDI para acceder a una base de datos, en lugar de configurar manualmente una Connectioninstancia JDBC .

Con ese Callobjeto en su lugar, el cliente sigue la semántica JAX-RPC de la llamada a procedimiento remoto. Por ejemplo, el cliente puede usar el invoke()método Callpara interactuar con el servicio web. (Para obtener un ejemplo de invocación de servicios al estilo JAX-RPC, consulte "Me gusta su tipo: describir e invocar servicios web según el tipo de servicio" ( JavaWorld, septiembre de 2002)).

El modelo de programación del servidor de servicios web

Un servicio web basado en J2EE puede seguir una de dos posibles implementaciones: Si el servicio se implementa como una clase Java normal, debe cumplir con los requisitos del contenedor de servlets JAX-RPC. O, si el servicio está definido para ejecutarse en el contenedor EJB, entonces debe seguir el modelo de programación requerido de beans de sesión EJB sin estado. Independientemente del método de implementación, cada contenedor proporciona la implementación del servicio web con soporte para el ciclo de vida, administración de simultaneidad y una infraestructura de seguridad.

La responsabilidad principal del contenedor del servidor J2EE es mapear y enviar solicitudes SOAP, en el caso de EJB, a beans de sesión sin estado y, en el caso del contenedor de servlets, a métodos en clases de punto final de servicio JAX-RPC. Mientras que la especificación JAX-RPC define un modelo de programación para la última opción, el JSR de servicios web J2EE (JSR 109) describe un modelo análogo para beans de sesión EJB sin estado.