Taller de Sistemas de Información 2 Web Services Web Service • Es un mecanismo para que aplicaciones cliente y servidor se comuniquen a través de los protocolos de la web (HTTP/HTTPS) • Permite que diversas aplicaciones en múltiples tipos de plataformas y frameworks puedan interoperar Tipos de web services • “Big” Web Services • Utilizan mensajes XML que siguen el protocolo SOAP (Simple Object Access Protocol) • SOAP define la estructura y formato de los mensajes intercambiados • Generalmente proveen un documento que permite describir las funciones provistas por el web service (WSDL) • Pueden soportar diversos aspectos no funcionales, como ser transaccionalidad, seguridad, confianza, coordinación, etc. • Pueden soportar invocaciones y procesamiento asincrono Tipos de web services • “RESTful” Web Services • • • • • • REST es el estilo arquitectónico sobre el que esta basado la web Es apto para mecanismo “ad-hoc” de integración No requieren el uso de WSDL, SOAP o XML Están muy integrados con el protocolo HTTP Soportan el uso de cache, provisto por las tecnologías de la web Ambas partes deben acordar el contexto y contenido del material intercambiado Tipos de web services • JAX-WS • Implementación de web services basados en SOAP • Permiten cumplir con requisitos de QoS, que generalmente solemos encontrar en ambientes empresariales • Permite soportar mas fácilmente que JAX-RS el uso de WS-* • JAX-WS • Implementación de web services basados en REST • Facilitan la integración de soluciones en escenarios simples • No caen en el overhead impuesto por los servicios SOAP JAX-WS • En JAX-WS una invocación de una operación esta representada en base a un protocolo basado en XML (SOAP) • SOAP define la estructura y las convenciones usadas para intercambiar mensajes entre las partes • Las llamadas y respuestas son transmitidos como mensajes SOAP, codificados en formato XML • Si bien SOAP es complejo, la complejidad de este es abstraída por el uso del API provista en JAX-WS JAX-WS – Esquema de comunicación Requisitos • Debemos tener una clase Java anotada con @javax.jws.WebService • Esto define que la clase es el endpoint de un servicio web • SEI • Service Endpoint Interface • Service Endpoint Implementation • Declara los métodos que un cliente puede invocar en un servicio • El uso de una interfaz Java no es requerido (pero si recomendable) para definición del endpoint • Podemos declarar explícitamente una interfaz usando el atributo “endpointInterface” de la anotación @WebService Pasos para crear el web service • Servidor • Implementamos la clase del servicio • Compilamos y empaquetamos en un WAR/JAR según el tipo de implementación • Deployeamos el modulo en el servidor web para brindar la funcionalidad • Cliente • Implementamos la clase del cliente • Usamos alguna herramienta para generar los proxies automáticamente (por ejemplo, wsimport de Java) • Anexamos las clases generadas al classpath y ejecutamos el codigo Requisitos para el endpoint • La clase debe estar anotada con @javax.jws.WebService o @javax.jws.WebServiceProvider • La clase puede referenciar explícitamente una SEI a través del atributo “endpointInterface” de la anotación anterior. • Si no se utiliza “endpointInterface”, se genera una SEI automáticamente a partir de la clase de implementación • Los métodos de negocio que se expondrán, deben ser públicos, y no pueden ser static o final • Los métodos expuestos al cliente, pueden estar anotados con @javax.jws.WebMethod Requisitos para el endpoint • Los métodos de negocio que son expuestos al cliente, deben tener tipos JAXB compatibles • La clase no puede ser declarada final o abstract • La clase debe tener un constructor por defecto • La clase no puede implementar el método finalize • La clase puede definir los métodos del ciclo de vida @PostConstruct (javax.annotation.PostConstruct) y @PreDestroy (javax.annotation.PreDestroy) JAXB: Java API for XML Binding JAXB JAXB • Si bien el intercambio de información entre el consumidor y proveedor se hace en base a XML, el código Java no tiene porque interactuar con esto directamente • JAXB provee un estándar para trabajar con representaciones Java de documentos XML y viceversa • Permite que el código Java se abstraiga de la complejidad de validar y manipular documentos XML, junto con su correspondiente representación Java Documento XML Schema XML Ejemplo… • Clase de implementación para un servicio de saludos…. • Cumple con los requisitos antes planteados @WebService • Esta anotación también puede ser aplicada sobre la propia interfaz, para hacer que la misma sea la endpointInterface del servicio @WebMethod • Por defecto, todos los métodos públicos del web service (o de su interfaz) son incluidos dentro de lo que se expone al exterior • Para customizar la forma en como se hace esto (por ejemplo para cambiar el nombre del método), usamos la anotación @WebMethod, aplicada sobre el método a modificar • Por ejemplo... @WebResult • Opera en conjunto con la anotación anterior • Permite customizar el nombre del mensaje devuelto como resultado de la operación @WebParam • Permite customizar los parámetros que son enviados al servicio • Podemos cambiar el nombre y el tipo de parámetro @OneWay • Es una anotación que permite indicar que un método, no retorna valores • Por ejemplo, los métodos que retornan void • Esto permite que el container realice optimizaciones con los métodos de este tipo, por ejemplo, usando Asynchronous (solo en EJB) Errores • SOAP informa los errores a los consumidores a través de SOAP Faults • Son una forma estándar de manejar errores (similares a las excepciones) • En el caso de que se produzca una excepción en el servidor, se genera una Fault utilizando el nombre completo de la excepción como mensaje Excepciones • También se indica que el error se produce por causa del servidor @WebFault @WebFault Fault obtenida SOAPFactory Ciclo de vida • El ciclo de vida de los web services es similar al de los stateless session beans • No mantienen ningún estado, simplemente existen o no existen • Como en el caso de los stateless, podemos usar las anotaciones @PreDestroy y @PostConstruct • En el caso de un web service implementado como EJB, se pueden utilizar interceptors Ciclo de vida Web Service Context • Como en el caso de los EJBs, el web service tiene un contexto que permite obtener información útil del ambiente de ejecución del servicio • Se inyecta como en el caso de los EJB, usando @Resource Web Service Context • GetMessageContext • Permite acceder al mensaje SOAP, por ejemplo para obtener los headers • GetUserPrincipal • Identifica a traves del Principal al emisor del mensaje • IsUserInRole • Determina si un usuario autenticado esta presente en un rol determinado Invocando un web service JAX-WS Invocación programática • Si estamos fuera del container, podemos invocar programáticamente Invocación programática • Requiere que se hayan generado los artefactos Java a partir del WSDL del servicio web • Podemos usar la herramienta wsimport provista por Java estándar • wsimport <URL al WSDL del servicio> • Los artefactos Java generados (clases) deben ser incluidas en el classpath del proyecto Invocación con inyección RESTful Services • Son servicios desacoplados, livianos, aptos para crear APIs simples para acceder a las funcionalidades de una aplicación • REST es un estilo arquitectónico basado en la idea de la transferencia de representaciones de recursos entre un cliente y un servidor, a través de request/response HTTP • REST se basa en una serie de principios generales • • • • Identificación de recursos con URIs Interfaz uniforme Mensajes autodescriptivos Interacciones stateful con links Recursos y URIs • Los recursos tienen un rol central en REST • Un recurso es cualquier cosa con la cual un cliente quiera interactuar, y que sea identificable a través de un hipervínculo • Un libro, un perfil, un resultado de una busqueda, etc. • Puede almacenarse en cualquier lado • Archivo, base de datos, etc. Recursos y URIs • Un recurso se identifica por una URI (Uniform Resource Identifier) • Una URI es un identificador único para un recurso • Esta formada por un nombre y una dirección estructurada en donde localizar dicho recurso Recursos y URIs • Algunos ejemplos de URIs… URIs • Una URI debe ser lo mas descriptiva posible y apuntar a un único recurso • El formato estándar de una URI es el siguiente: • http://host:port/path?queryString#fragment • Un ejemplo: • http://www.weather.com:8080/weather/2013/01/01?location=Lisbon,Portug al&time=morning Representaciones • Cuando un cliente interactúa con un recurso, siempre lo hace a través de representaciones del mismo • El recurso SIEMPRE existe en el servidor • Una representación es cualquier información acerca del estado de un recurso Representaciones • Un recurso puede tener múltiples representaciones • Existen dos formas de seleccionar la representación que queremos • A través de una URL especifica • http://www.apress.com/java • http://www.apress.com/java/csv • http://www.apress.com/java/xml • A través de negociación de contenido Direccionalidad • El objetivo de esta propiedad es que los web services REST deben hacer que la aplicación sea lo mas direccionable posible • Esto es, cada pieza de información útil que queramos exponer, debe ser un recurso y a su vez debe tener una URI asociada • La URI es la única pieza de información a publicar para que el servicio pueda ser usado Conectividad • Si dos recursos se encuentran fuertemente relacionados (a nivel conceptual), entonces debe existir un enlace (link) entre estos • Los web services REST deben aprovechar esta facilidad de los hyperlinks, para informar a los clientes que hay disponible mas información y como debe hacerse para acceder a esta Conectividad • Por ejemplo, si obtenemos la información de un CD, podemos a su vez acceder a información relacionada Interfaz uniforme • El protocolo de facto es el HTTP • La interfaz esta compuesta por los métodos HTTP • GET, POST, PUT y DELETE • El destinatario de las acciones es la URI del recurso con el que se quiere interactúa • Facilita enormemente la interoperabilidad entre sistemas Estado • En REST se diferencia generalmente entre el estado del recurso y el estado de la aplicación • El estado del recurso, se mantiene en el servidor, siendo compartido por todos • El estado de la aplicación es mantenido en el cliente, siendo de su única propiedad y responsabilidad • Tiene múltiples ventajas en el manejo de la performance de la aplicación HTTP • Es el protocolo base de la web • Esta orientado a documentos, en base a un protocolo textual HTTP Request • Elementos importantes • El método HTTP: GET • La ruta (path): /java?limit=all&mode=list • Una serie de headers: User-Agent HTTP Response HTTP Response • Aspectos importantes • • • • El código de respuesta: 200 – OK Múltiples headers: Date, Server, Content-Type Representación (o entidad body): Es el cuerpo de la respuesta Generalmente en un browser se recibe el texto HTML de la pagina que queremos ver Headers Métodos HTTP • GET • Equivalente a un READ • POST • Equivalente a un INSERT • PUT • Equivalente a un UPDATE • DELETE • Equivalente a un ….. DELETE! Métodos HTTP • Algunos aspectos importantes • GET debe ser “seguro”, esto es, no debe cambiar el estado del recurso • GET debe ser idempotente, debiendo retornar el mismo resultado si se lo llama una o N veces (si no cambia en el medio de las llamadas) • DELETE es idempotente, pero no es seguro • PUT y POST no son seguros Negociación de contenido • Consiste en elegir la mejor representación cuando para un mismo recurso existen múltiples representaciones disponibles • Esta basada en los siguientes headers del request: • Accept, Accept-Charset • Accept-Encoding, Accept-Language • User-Agent Negociación de contenido • Por ejemplo, si utilizamos la siguiente URI para acceder a información sobre libros de Java • http://www.apress.com/java • Podemos indicar • En Accept el media type text/csv, para indicar que queremos una representación CSV de los datos • Podemos usar Accept-Language para indicar “en”, para a su vez pedir el CSV en ingles Content Types • HTTP utiliza los Internet Media Types (también conocidos como MIME Types) • Se especifican en los headers Content-Type y Accept • Se dividen en 5 categorías “top-level” • text, image, audio, video y application • Estas se dividen en subtipos • text/html, text/plain, image/gif, application/json Códigos de estado • Permiten devolver al cliente información de la solicitud, tanto en caso de éxito como de fallo • 1xx: Informativos • 2xx: Éxito • 3xx: Dirección • 4xx: Error del cliente • 5xx: Error del servidor Códigos de estado • Códigos 1xx : Mensajes • 100-111 Conexión rechazada • Códigos 2xx: Operación realizada con éxito • • • • • 200 OK 201-203 Información no oficial 204 Sin Contenido 205 Contenido para recargar 206 Contenido parcial Códigos de estado • Códigos 3xx: Redirección • • • • • • 301 Mudado permanentemente 302 Encontrado 303 Vea otros 304 No modificado 305 Utilice un proxy 307 Redirección temporal Códigos de estado • Códigos 4xx: Error por parte del cliente • • • • • • • 400 Solicitud incorrecta 402 Pago requerido 403 Prohibido 404 No encontrado 409 Conflicto 410 Ya no disponible 412 Falló precondición Códigos de estado • Códigos 5xx: Error del servidor • • • • • • 500 Error interno 501 No implementado 502 Pasarela incorrecta 503 Servicio no disponible 504 Tiempo de espera de la pasarela agotado 505 Versión de HTTP no soportada JAX – RS • Para escribir un servicio web que utilice REST, solo se necesita un cliente y un servidor que soporte HTTP • Como en el caso de SOAP, a fin de eliminar el trabajo con protocolos de bajo nivel, aparece el API JAX-RS • La implementación de referencia de esta API, se denomina Jersey (es un proyecto open source) JAX – RS • Si bien los conceptos anteriores pueden hacer pensar que tenemos que manipular la información a bajo nivel usando los protocolos anteriores, esto no es asi • JAX-RS es un API bastante elegante que permite especificar un recurso, en base a un POJO • Usamos la anotación @javax.ws.rs.Path sobre una clase Java que representa un recurso JAX – RS • En el ejemplo anterior, el recurso BookResource esta publicado en la URI /book • El método getBookTitle() queda asociado al método GET HTTP, produciendo un contenido de tipo “text/plain” • Para acceder al recurso, solo debemos usar un browser con la dirección http://www.myserver.com/book JAX – RS • El servicio REST no implementa ninguna interfaz ni extiende ninguna clase • Debemos usar la anotación @Path • Si queremos usar un EJB, entonces solo podemos usar @Stateless • La clase debe ser public, y no abstract ni final • Debe contener un constructor por defecto • La clase no debe incluir el método finalize() Interfaz de acceso al recurso • JAX-RS define una serie de anotaciones, para indicar que método HTTP se utilizara para acceder a un recurso • Estas anotaciones corresponden a los métodos HTTP disponibles • @GET, @POST, @PUT, @DELETE, @HEAD, @OPTIONS • Solo los métodos públicos de una clase pueden exponerse como métodos de recurso Interfaz de acceso al recurso • Cuando un método de recurso es invocado • Los parámetros para los cuales hay un extractor, son cargados con dicho valor • Los valores de parámetros no anotados, llamados entity parameters, es mapeado del cuerpo del request, a traves de un entity provider • Los métodos pueden devolver void, un tipo Java o un Response • Response es usado cuando es necesario devolver mas información (metadatos) en la respuesta Información contextual • Cuando un request es atendido, el recurso puede necesitar para llevar adelante su tarea, acceder a información de contexto • La anotación @javax.ws.rs.core.Context es usada para inyectar una referencia a objetos de tipo: • HttpHeaders, UriInfo, Request, SecurityContext, y Providers Manejo de excepciones • En un método de recurso, en cualquier momento podemos propagar una excepción al exterior del recurso • Esta excepción debe ser del tipo WebApplicationException, o una subclase de esta • La excepción será capturada por el runtime de JAX-RS, convirtiéndola en una HTTP Response apropiada Manejo de excepciones • El error por defecto es un error 500 con un mensaje en blanco • La clase WebApplicationException ofrece varios constructores que permiten modificar esto • El enumerado javax.ws.rs.core.Response.Status contiene valores que podemos utilizar al momento de construir una excepción Providers • Para simplificar el manejo de excepciones, podemos usar un Provider • Este permite mapear Excepciones en Responses Ciclo de vida HelloWorld • Creamos una web application • Para exponer recursos REST, necesitamos una implementación de REST (JAX-RS) • En el caso de EAP/Wildfly, utilizamos RESTEasy • Esta es una implementación que ya viene incorporada en el servidor • Necesitamos que el web.xml sea versión 3.0 web.xml <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> ... ... ... </web-app> HelloWorldResource HelloWorld • Luego de creado el recurso, deployeamos y ejecutamos la aplicacion web • Accedemos al recurso, a traves de la URL • http://localhost:8080/HelloWorld/tutorial/hello • Deberiamos obtener “Hello World!!” PathParam • Permite extraer “pedazos” de la URL package ejemplos; import javax.ws.rs.*; @Path("tutorial") public class HelloWorldPoliteResource { @GET @Path("sayhello/{name}") public String helloworld(@PathParam("name") final String name) { return "Hi!, how are you " + name; } } PathParam • Como antes, se deployea y ejecuta la aplicacion • Debemos entrar a la URL: • http://localhost:8080/HelloWorld/tutorial/sayhello/Pablo • Deberiamos obtener: “Hi!, how are you Pablo” Intercambio de XML • Podemos intercambiar objetos XML, tanto para el resultado como para los parametros • Para esto debemos usar providers JAXB (idem SOAP), que se encarguen de mapear instancias en documentos XML • Por ejemplo, vamos a intercambiar objetos Java, “Items” ItemResource package ejemplo; import javax.ws.rs.*; @Path("items") public class ItemResource { @GET @Path("item") @Produces({ "application/xml" }) public Item getItem() { Item item = new Item("IPhone5", 1500); return item; } } ItemResource • Si ejecutamos la aplicacion, al especificar application/xml, se utilizara el provider adecuado para obtener este XML <item> <description>IPhone5</description> <price>1500</price> </item> @FormParam ● Esta anotacion sirve para extraer informacion de un formulario <html> <body> <form method="POST" action="login"> Email Address: <input type="text" name="email"><br> Password: <input type="text" name="password"><br> <br> <input type="submit"> </form> </body> </html> @FormParam package ejemplos; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; @Path("/") public class LoginResource { @Path("login") @POST public String login( @FormParam("email") String email, @FormParam("password") String password) { return "Ingreso con el email: " + email + " y el password " + password; } } @QueryParam ● Es muy similar al anterior, solo que al usarlo, se trata de extraer el valor el query parameter con el nombre indicado @Path("login/{id}") public String loginQPM(@QueryParam("id") String idvalue) { return "Id es " + idvalue; } http://localhost:8080/<Nombre de proyecto>/login?id=12345 Consumo y producción de tipos • JAX-RS define una serie de tipos Java que pueden representar diferentes tipos de recursos • Por ejemplo: String, InputStream y beans anotados con JAXB • @javax.ws.rs.Consumes y @javax.ws.rs.Produces se aplican a recursos que pueden tener diferentes tipos de representaciones Consumo y producción de tipos • Estas anotaciones definen los media types intercambiados entre el cliente y el servidor • JAX-RS utiliza como abstracción de un media type la clase: • javax.ws.rs.core.MediaType • Esta tiene una serie de constantes que definen los media types producidos y consumidos por un recurso para un determinado método Podemos aplicar las anotaciones a nivel del recurso o de un método especifico Tipos retornados • Un servicio REST puede retornar • Cualquier tipo Java estándar • Un bean JAXB • Cualquier cosa que tenga una representación textual que pueda ser enviada por HTTP • En el ultimo caso, el runtime determina el media type de lo que se devuelve, invocando el Entity Provider apropiado (para obtener su representación textual) Tipos retornados • El runtime determina el código de retorno apropiado para devolver al cliente • 204 – No content, si el método devuelve null o void • 200 – Ok, si el método devuelve una respuesta no nula • Sin embargo, hay veces en que necesitamos un control mas fino de lo que se devuelve • En esos casos, usamos la Response API Response API • Provee un API para construir una respuesta (HTTP Response) como retorno de un método del recurso • Permite controlar el tipo de entidad devuelto, así como headers y banderas de control que forman el paquete de respuesta • Es la forma recomendada de retornar información de un método de un recurso Response API Response.ok().build(); Response.ok().cookie(new NewCookie( "SessionID", "5G79GDIFY09") ).build(); Response.ok("Plain Text").expires( new Date()).build(); Response.ok( new Customer ("John", "Smith"), MediaType.APPLICATION_JSON ).build(); Response API Response.noContent().build(); Response.accepted( new Customer("John", "Smith", "1234565") ).build(); Response.notModified().header( "User-Agent", "Mozilla“ ).build(); "[email protected]", Construcción de URIs • JAX-RS provee la clase javax.ws.rs.core.UriBuilder como medio para la construcción de URIs • Provee una serie de métodos que permiten construir una URI a un recurso en forma segura, incluyendo parámetros enviados al recurso Construcción de URIs Entity Providers • El rol de un Entity Provider es el de proveer un mapeo entre las representaciones y tipos Java esperados y devueltos por los recursos • Por ejemplo, JAXB mapea objetos Java en XML y viceversa • Si lo provisto por defecto no es suficiente, podemos provee un mapeo por customizado, a través de un entity provider Entity Providers • Un entity provider customizado, provee una forma de leer y escribir el formato customizado, hacia y desde un tipo Java especifico • Tenemos dos tipos de Entity Providers • MessageBodyReader • MessageBodyWriter Entity Providers • Una vez definidos ambos providers, podemos utilizar el formato customizado en los recursos o métodos del mismo Client API • Antes de JAX-RS 2.0 no existía una forma estándar de invocar servicios web REST • Esta API permite realizar invocaciones a servicios REST a través de HTTP en forma simple • Las clases necesarias para construir un cliente REST se encuentran en el package javax.ws.rs.client Client API • Clases e interfaces necesarias para construir un cliente Client • Es la interfaz de entrada al API • Esta permite gestionar y configurar conexiones HTTP • Permite crear WebTargets para recursos y enlaces • Usamos el objeto ClientBuilder para crear una instancia de Client • Client client = ClientBuilder.newClient(); Client • Por ejemplo, podemos crear un cliente y asociarle un provider definido convertir tipos específicos Client client = ClientBuilder.newClient(); client.configuration() .register(CustomCustomerReader.class) .setProperty("MyProperty", 1234); Targets e invocaciones • Con el cliente podemos crear WebTargets • Estos representa una URI contra la cual podemos enviar requests y recibir responses • Por ejemplos WebTarget target = client.target("http://www.myserver.com/book"); URI uri = new URI("http://www.myserver.com/book "); WebTarget target = client.target(uri); Targets e invocaciones • Con el WebTarget creado, podemos crear una invocación • Esta permite enviar solicitudes utilizando un método especifico Invocation invocation = target.request().buildGet() • Según el tipo de interacción, podemos crear solicitudes mas complejas Targets e invocaciones Invocaciones • Una vez que tenemos la invocación, debemos realizar la llamada • Ejecutamos el método “invoke”, obteniendo como respuesta un objeto de tipo Response • Por ejemplo: • Response response = invocation.invoke(); Poniendo todo junto… Responses • Permite obtener la información enviada desde el servicio REST • Podemos obtener • • • • Headers Cookies Status HTTP Message Body (Entidad) Responses • Utilizando un MessageBodyReader podemos obtener la entidad, convertida al tipo Java que el reader mapee • Por ejemplo, si especificamos que queremos un String, JAX-RS utilizara un StringReader • String body = response.readEntity(String.class); • Pero si por ejemplo, recibimos un Book en formato XML, podemos hacer: • Book book = response.readEntity(Book.class);
© Copyright 2024