Web Services Archivo

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);