Upload
abimael-desales-lopez
View
2.281
Download
2
Embed Size (px)
Citation preview
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
REST con Java usando Jersey
Presenta
Ing. Abimael Desales López
https://www.facebook.com/JavaDevelopersMexico
JavaDevelopersMexico en Google +
“El conocimiento es libre y está en búsqueda de que lo hagas tuyo, sólo necesitas práctica y paciencia”
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Tutorial - REST con Java (JAX-RS) usando Jersey
Copyright © 2015 JavaDevelopersMexico 10/08/2015
Web services RESTful con Java (Jersey / JAX-RS)
Este tutorial explica cómo desarrollar web services RESTful en Java con Jersey la implementación de referencia de JAX-RS.
En este tutorial usamos los siguientes artefactos de software
Eclipse 4.4 (Luna)
Java 1.8.0_45, Tomcat 7.0 JAX-RS 2.0 (con Jersey 2.19).
Tabla de Contenido
Audiencia
1. REST - Representational State Transfer
1.1. ¿Qué es REST?
1.2. Métodos HTTP
1.3. Web Services RESTFul
2. JAX-RS con Jersey
2.1. JAX-RS
2.2. Jersey
2.3. Anotaciones JAX-RS
3. Instalación de Jersey
4. Contenedor Web
5. Prerrequisitos
6. Crea tu primer Webservice RESTful
6.1. Crea un nuevo proyecto web
6.2. Agrega los JARs de Jersey
6.3. Clase Java
6.4. Define el Servlet dispatcher de Jersey
6.5. Corre tu servicio rest
7. Crea un cliente
8. Web services RESTful y JAXB
8.1. Crea un proyecto
8.2. Crea un cliente
9. Webservice RESTful CRUD
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
9.1. Proyecto
9.2. Crea un formulario HTML simple
9.3. Servicio Rest
9.4. Corre
9.5. Crea un cliente
9.6. Usando el servicio REST vía una página HTML
Bibliografía y Webgrafía
Audiencia
Este tutorial está diseñado para profesionales de software quienes quieren aprender sobre
servicios web RESTful en pasos simples y fáciles. Este tutorial te proporcionará
conocimientos sobre los conceptos de servicios web RESTful, y después de completar este
tutorial estarás en un nivel intermedio de expertise desde donde puedes subir por ti mismo a
un nivel de expertise más alto a través de la práctica.
1. REST - Representational State Transfer
1.1. ¿Qué es REST?
REST es un estilo arquitectural que está basado en estándares web y el protocolo HTTP.
REST fue descrito por primera vez por Roy Fielding en el 2000.
En una arquitectura REST todo es un recurso. Un recurso es accesado vía una interfaz
común basada en los métodos HTTP estándar.
En una arquitectura basada en REST generalmente tienes un servidor REST que
proporciona acceso a los recursos y un cliente REST que accesa y modifica los recursos
REST.
Cada recurso debe soportar las operaciones HTTP comunes. Los recursos son identificados
por IDs globales (las cuales típicamente son URIs).
REST permite que los recursos tengan diferentes representaciones, p.e., texto, XML, JSON,
etc. El cliente REST puede preguntar por una representación específica vía el protocolo
HTTP (negociación de contenido).
1.2. Métodos HTTP
Los métodos PUT, GET, POST DELETE, y OPTIONS generalmente son usados en
arquitecturas basadas en REST.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
La siguiente tabla proporciona una explicación de estas operaciones.
GET Define un acceso de lectura del recurso sin efectos colaterales . El recurso nunca es
cambiado vía una request GET, p.e., la request no tiene efectos colaterales
(idempotente).
PUT Crea un nuevo recurso. También de debe ser idempotente
DELETE Usado para remover un recurso. Las operaciones son idempotentes. Pueden ser
repetidas sin llevar a diferentes resultados.
POST Usado para actualizar un recurso existente o crear un nuevo recurso
OPTIONS Usado para obtener las operaciones soportadas por un recurso
1.3. Web services RESTFul
Los web services RESTFul están basados en métodos HTTP y el concepto de REST. Un
web service RESTFul típicamente define la URI base URI para los servicios, los tipos MIME
soportados (XML, text, JSON, definido por el usuario,...) y el conjunto de operaciones (POST,
GET, PUT, DELETE) que son soportadas.
2. JAX-RS con Jersey
2.1. JAX-RS
Java define el soporte de REST vía la Java Specification Request (JSR) 311. Esta
especificación es llamada JAX-RS (la Java API for RESTful Web Services). JAX-RS usa
anotaciones para definir la relevancia de REST en las clases Java.
2.2. Jersey
Jersey es implementación de referencia para la especificación JSR 311.
La implementación Jersey provee una librería para implementar webservices Restful en un
contenedor de servlets Java.
En el lado del servidor Jersey provee una implementación de servlet que escanea las clases
predefinidas para identificar los recursos RESTful. En tu archivo de configuración web.xml
debes registrar este servlet para tu aplicación web.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
La implementación Jersey también proporciona una librería cliente para comunciarse con un
webservice RESTful.
La URL base de este servlet es:
http://tu_dominio:puerto/nombre-despliegue/url-pattern/path_de_clases_rest
Este servlet analiza la request HTTP entrante y selecciona la clase correcta y método para
responder a esta request. Esta selección está basada en anotaciones en la clase y métodos.
Una aplicación web REST consiste, por lo tanto, de clases (recursos) y servicios. Estos dos
tipos típicamente son mantenidos en diferentes packages ya que el servlet Jersey será
instruido vía el web.xml para que escanee ciertos packages para las clases de datos.
JAX-RS soporta la creación de XML y JSON vía la Java Architecture for XML Binding (JAXB).
2.3. Anotaciones JAX-RS
Las anotaciones más importantes en JAX-RS son listados en la siguiente tabla.
Tabla 1. Anotaciones JAX-RS
Anotación Descripción
@PATH(tu_path) Asigna el path a la URL base + /tu_path. La URL base está basada
en el nombre de tu aplicación, el servlet y la URL pattern del archivo
de configuración web.xml.
@POST Indica que el método siguiente responderá a una request POST
HTTP.
@GET Indica que el método siguiente responderá a una request GET
HTTP.
@PUT Indica que el siguiente método responderá a una request PUT
HTTP.
@DELETE Indica que el siguiente método responderá a una request DELETE
HTTP.
@Produces(MediaType.TEXT_PLAIN[,
more-types])
@Produces define qué tipo MIME es entregado por un método
anotado con @GET. En el ejemplo se produce texto ("text/plain").
Otros ejemplos serían "application/xml" o "application/json".
@Consumes(type[, mas-tipos]) @Consumes define qué tipo MIME es consumido por este método.
@PathParam
Usado para inyectar valores de la URL en un parámetro del método.
De esta forma inyectas, por ejemplo, el ID de un recurso en el
método para obtener el objeto correcto.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
El path completo a un recurso está basado en la URL base y la anotación @PATh en tu
clase.
http://tu_dominio:puerto/nombre-despliegue/url-pattern/path_de_clases_rest
3. Instalación de Jersey
Descarga la distribución Jersey como archivo zip desde el sitio de descarga de Jersey.
El zip contiene el JAR de la implementación Jersey y sus dependencias core. No proporciona
dependencias para JArs de tecerceros más allá de aquellos para el soporte de JSON y
JavaDoc.
4. Contenedor Web
Para este tutorial puedes usar cualquier contenedor web, por ejemplo Tomcat o la Google
App Engine.
Si quieres usar Tomcat como contenedor de servlet por favor mira Eclipse WTP y Apache
Tomcat para las instrucciones sobre cómo instalar y usar Eclipse WTP y Apache Tomcat.
Alternativamente también podrías usar la Google App Engine para correr la parte del servidor de los siguientes ejemplos de REST. Si usas la Google App Engine, no tienes que instalar y configure Tomcat.
Tip
Si estás usando GAE/J, tienes que crear proyectos de App Engine en vez de Dynamic Web Project. La siguiente descripción está basada en Apache Tomcat.
5. Prerrequisitos
Antes de proceder con este tutorial debes tener una comprensión básica del lenguaje Java, editores de texto, IDEs, servidores web, etc. Debido a que vamos a desarrollar aplicaciones de web services usando RESTful, será bueno que tengas conocimientos sobre otras tecnologías web como HTML, CSS, AJAX etc.
6. Crea tu primer Webservice RESTful
6.1. Crea un nuevo proyecto web
Crea un nuevo Dynamic Web Project llamado it.adesales.primer.rest.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Haz click en Next
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Asegúrate de crear el descriptor de deployment web.xml.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Seleccionando la casilla Generate web.xml deployment descriptor y además cambia el nombre
de content directory por Web en vez de WebContent para estandarizar la aplicación.
6.2. Agrega los JARs de Jersey
Copia todos los JARs de tu descarga de Jersey (los que hay dentro de las tres carpetas de
librerías, api, ext y lib) en la carpeta WEB-INF/lib.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
6.3. Clase Java
Crea la siguiente clase Java en el package it.adesales.primer.rest.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
package it.adesales.primer.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
// Plain old Java Object no extienden de clases o implementan una interface
// La clase registra sus métodos para la request GET HTTP usando la anotación @GET.
// Usando la anotación @Produces, define que puede entregar varios tipos MIME, texto
// XML y HTML.
// Por defaul, el navegador solicita el tipo MIME HTML.
//Asigna el path a la URL base + /hola
@Path("/hola")
public class Hola {
// Este método es llamado si se solicita TEXT_PLAIN
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHola() {
return "Hola Jersey";
}
// Este método es llamado si se solicita XML
@GET
@Produces(MediaType.TEXT_XML)
public String sayXMLHola() {
return "<?xml version=\"1.0\"?>" + "<hello> Hola Jersey" + "</hello>";
}
// Este método es llamado si se solicita HTML
@GET
@Produces(MediaType.TEXT_HTML)
public String sayHtmlHola() {
return "<html> " + "<title>" + "Hola Jersey" + "</title>"
+ "<body><h1>" + "Hola Jersey" + "</body></h1>" + "</html> ";
}
}
Esta clase se registra a sí misma como un recurso get vía la anotación @GET. Vía la anotación
@Produces define que entrega el texto y los tipos MIME HTML. Además define vía la anotación @Path que sus servicios están disponibles bajo la URL hola.
El navegador siempre solicitará el tipo MIME HTML. Para ver la versión texto, puedes usar
alguna herramienta como curl.
6.4. Define el despachador de Servlet de Jersey
Necesitas registrar Jersey como el despachador de servlet para solicitudes REST. Abre el archivo web.xml y modifícalo a lo siguiente.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>it.adesales.primer.rest</display-name>
<servlet>
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Registra recursos y proveedores bajo package com.vogella.jersey.first.-->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>it.adesales.primer.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
El parámetro jersey.config.server.provider.packages define en qué package buscará
Jersey clases de web service. Esta propiedad debe apuntar a tus clases de recursos. El URL pattern define la parte de la URL base donde tu aplicación será colocada.
6.5. Corre tu servicio rest
Corre tu aplicación web en Eclipse.
Debes ser capaz de accesar tus recursos bajo la siguiente URL en el navegador: http://localhost:8080/it.adesales.primer.rest/rest/hola
En mi caso también pruebo con una herramienta de nombre Postman, disponible para
Chrome, recomiendo que la utilicen y jueguen con ella para que se familiaricen :
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Este nombre es derivado del "display-name" definido en el archivo web.xml, aumentado con
el URL-pattern del servlet-mapping y la anotación @Path hola de tu archivo de clase. Debes obtener el mensaje "Hola Jersey".
El navegador solicita la representación HTML de tu recurso. En el siguiente capítulo vamos a escribir un cliente que leerá la representación XML.
7. Crea un cliente
Jersey contiene una librería cliente REST que se puede usar para probar o construir un cliente real en Java. El uso de esta librería es demostrado en el siguiente ejercicio.
Crea un nuevo proyecto Java y agrega el package it.adesales.primer.rest.cliente y agrega los JARs de Jersey al proyecto y al build path del proyecto. Crea la siguiente clase de test.
package it.adesales.primer.rest.cliente;
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.client.ClientConfig;
public class Test {
public static void main(String[] args) {
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target(getBaseURI());
String response = target.path("rest").
path("hola").
request().
accept(MediaType.TEXT_PLAIN).
get(Response.class)
.toString();
String plainAnswer =
target.path("rest").path("hola").request().accept(MediaType.TEXT_PLAIN).get(String.class);
String xmlAnswer = target.path("rest").path("hola").request().accept(MediaType.TEXT_XML).get(String.class);
String htmlAnswer=
target.path("rest").path("hola").request().accept(MediaType.TEXT_HTML).get(String.class);
System.out.println(response);
System.out.println(plainAnswer);
System.out.println(xmlAnswer);
System.out.println(htmlAnswer);
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8080/it.adesales.primer.rest").build();
}
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
}
8. Web services RESTful y JAXB
JAX-RS soporta la creación automática de XML y JSON vía JAXB. Si deseas una introducción
en XML por favor revisa el Tutorial Java y XML. Si deseas una introducción en JAXB por favor
revisa JAXB. Puedes continuar este tutorial sin leer estos tutoriales, pero ellos contienen más
información de fondo si quieres conocer mas sobre dichos temas.
8.1. Crea el proyecto
Crea un nuevo Dynamic Web Project llamado it.adesales.rest.jaxb. Asegúrate de seleccionar
el check para generar el descritor de deployment web.xml y renombrar la carpeta
WebContent a Web, como en el ejemplo anterior .
Copia todos los JARs de Jersey JARs a la carpeta WEB-INF/lib.
Crea tu clase de dominio Todo bajo el package it.adesales.rest.jaxb.model.
package it.adesales.rest.jaxb.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
// JAX-RS soporta un mapeo automático de clases JAXB anotadas a XML y JSON
// ¿No es esto cool?
public class Todo {
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
private String resumen;
private String descripcion;
public String getResumen() {
return resumen;
}
public void setResumen(String resumen) {
this.resumen = resumen;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
}
Crea la siguiente clase de recurso. Esta clase simplemente retorna una instancia de la clase
Todo.
package it.adesales.rest.jaxb.service;
import it.adesales.rest.jaxb.model.Todo;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/todo")
public class TodoRecurso {
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
// Este método es llamado si la request es XML
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Todo getXML() {
Todo todo = new Todo();
todo.setResumen("Este es mi primer todo XML");
todo.setDescripcion("Este es mi primer todo XML");
return todo;
}
// Esto puede ser usado para probar la integración con el navegador
@GET
@Produces({ MediaType.TEXT_XML })
public Todo getHTML() {
Todo todo = new Todo();
todo.setResumen("Este es mi primer todo HTML");
todo.setDescripcion("Este es mi primer todo HTML");
return todo;
}
}
Cambia tu web.xml a lo siguiente.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>it.adesales.rest.jaxb</display-name>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers under com.vogella.jersey.first
package. -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>it.adesales.rest.jaxb.service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Corre tu aplicación web en Eclipse y valida que puedes accesar tu servicio. Tu aplicación debe estar disponible bajo la siguiente URL.
http://localhost:8080/com.vogella.jersey.jaxb/rest/todo
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
8.2. Crea un cliente
Crea un nuevo proyecto Java it.adesales.rest.jaxb.client y agrega los JARs de Jersey al proyecto y al build path del proyecto. Crea la siguiente clase de test.
package it.adesales.rest.jaxb.client;
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.client.ClientConfig;
public class TodoTest {
public static void main(String[] args) {
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target(getBaseURI());
// Obtiene el XML
String htmlResponse = target.path("rest").path("todo").request()
.accept(MediaType.TEXT_XML).get(String.class);
// Obtiene el XML para la aplicación
String xmlResponse = target.path("rest").path("todo").request()
.accept(MediaType.APPLICATION_XML).get(String.class);
// Para una response JSON también agrega las librerías de Jackson a tu
//aplicación web. En este caso también cambiarías el registro del cliente a
// ClientConfig config = new ClientConfig().register(JacksonFeature.class);
// Get JSON for application
// System.out.println(target.path("rest").path("todo").request()
// .accept(MediaType.APPLICATION_JSON).get(String.class));
System.out.println(htmlResponse);
System.out.println(xmlResponse);
}
private static URI getBaseURI() {
return
UriBuilder.fromUri(“http://localhost:8080/it.adesales.rest.jaxb“).build(); }
}
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
9. Webservice RESTful CRUD
En esta sección vamos a crear un web service RESTful CRUD (Create, Read, Update, Delete). Permitirá mantener una lista de TODOs en tu aplicación web vía llamadas HTTP.
9.1. Proyecto
Crea un nuevo dynamic web project llamado it.adesales.rest.jaxb.crud y agrega las librerías de Jersey. Cambia el archivo web.xml al siguiente.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>it.adesales.rest.crud</display-name>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Registar recursos y proveedores bajo com.vogella.jersey.first -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>it.adesales.rest.crud.recursos</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Crea el siguiente modelo de datos y un Singleton que sirve como el proveedor de datos para el
modelo. Nosotros usamos la implementación basada en una enumeración, puedes probar con otras opciones como usar objetos Mocks. Por favor revisa los links para más detalles. La clase Todo está anotada con una anotación JAXB. Véase Java y XML para aprender sobre JAXB.
package it.adesales.rest.crud.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Todo {
private String id;
private String resumen;
private String descripcion;
public Todo(){}
public Todo (String id, String resumen){
this.id = id;
this.resumen = resumen;
}
public String getId() {
return id;
}
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
public void setId(String id) {
this.id = id;
}
public String getResumen() {
return resumen;
}
public void setResumen(String resumen) {
this.resumen = resumen;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
}
package it.adesales.rest.crud.dao;
import java.util.HashMap;
import java.util.Map;
import it.adesales.rest.crud.model.Todo;
public enum TodoDao {
instance;
private Map<String, Todo> contentProvider = new HashMap<>();
private TodoDao() {
Todo todo = new Todo("1", "Aprende REST");
todo.setDescripcion("Lee mi artículo completo");
contentProvider.put("1", todo);
todo = new Todo("2", "Haz algo");
todo.setDescripcion("Visita mis sitios de Java Developers México");
contentProvider.put("2", todo);
}
public Map<String, Todo> getModel(){
return contentProvider;
}
}
9.2. Crea un formulario HTML simple
El servicio REST puede usarse vía formularios HTML. El siguiente formulario HTML permitirá
postear nuevos datos al servicio. Crea una carpeta de nombre pages dentro de la carpeta Web y dentro de esta crea la siguiente página llamada crea_todo.html.
<!DOCTYPE html>
<html>
<head>
<title>Formulario para crear un nuevo recurso</title>
</head>
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
<body>
<form action="../it.adesales.rest.crud/rest/todos" method="POST">
<label for="id">ID</label>
<input name="id" />
<br/>
<label for="resumen">Resumen</label>
<input name="resumen" />
<br/>
Descripción:
<TEXTAREA NAME="descripcion" COLS=40 ROWS=6></TEXTAREA>
<br/>
<input type="submit" value="Submit" />
</form>
</body>
</html>
9.3. Servicio Rest
Crea las siguientes clases que se usarán como recursos REST.
package it.adesales.rest.crud.recursos;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;
import it.adesales.rest.crud.dao.TodoDao;
import it.adesales.rest.crud.model.Todo;
public class TodoRecurso { @Context
UriInfo uriInfo;
@Context
Request request;
String id;
public TodoRecurso(UriInfo uriInfo, Request request, String id) {
this.uriInfo = uriInfo;
this.request = request;
this.id = id;
}
//Integración de la Aplicación
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Todo getTodo() {
Todo todo = TodoDao.instance.getModel().get(id);
if(todo==null)
throw new RuntimeException("Get: Todo con " + id + " no encontrado");
return todo;
}
// para el navegador
@GET
@Produces(MediaType.TEXT_XML)
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
public Todo getTodoHTML() {
Todo todo = TodoDao.instance.getModel().get(id);
if(todo==null)
throw new RuntimeException("Get: Todo con " + id + " no encontrado ");
return todo;
}
@PUT
@Consumes(MediaType.APPLICATION_XML)
public Response putTodo(JAXBElement<Todo> todo) {
Todo c = todo.getValue();
return putAndGetResponse(c);
}
@DELETE
public void deleteTodo() {
Todo c = TodoDao.instance.getModel().remove(id);
if(c==null)
throw new RuntimeException("Delete: Todo con " + id + " no encontrado");
}
private Response putAndGetResponse(Todo todo) {
Response res;
if(TodoDao.instance.getModel().containsKey(todo.getId())) {
res = Response.noContent().build();
} else {
res = Response.created(uriInfo.getAbsolutePath()).build();
}
TodoDao.instance.getModel().put(todo.getId(), todo);
return res;
}
}
package it.adesales.rest.crud.recursos;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import com.vogella.jersey.todo.dao.TodoDao;
import com.vogella.jersey.todo.model.Todo;
// Mapeará el recurso a la URL todos
@Path("/todos")
public class TodosRecurso {
// Permite insertar objetos contextuales en la clase,
// p.e. ServletContext, Request, Response, UriInfo
@Context
UriInfo uriInfo;
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
@Context
Request request;
// Retorna la lista de todos al usuario en el browser
@GET
@Produces(MediaType.TEXT_XML)
public List<Todo> getTodosBrowser() {
List<Todo> todos = new ArrayList<Todo>();
todos.addAll(TodoDao.instance.getModel().values());
return todos;
}
// Retorna la lista de todos para las aplicaciones
@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public List<Todo> getTodos() {
List<Todo> todos = new ArrayList<Todo>();
todos.addAll(TodoDao.instance.getModel().values());
return todos;
}
// retorna el número de todos
// Usa http://localhost:8080/it.adesales.rest.crud/rest/todos/conteo
// para obtener el número total de registros
@GET
@Path("conteo")
@Produces(MediaType.TEXT_PLAIN)
public String getCount() {
int count = TodoDao.instance.getModel().size();
return String.valueOf(count);
}
@POST
@Produces(MediaType.TEXT_HTML)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void newTodo(@FormParam("id") String id,
@FormParam("resumen") String resumen,
@FormParam("descripcion") String descripcion,
@Context HttpServletResponse servletResponse) throws IOException {
Todo todo = new Todo(id, resumen);
if (descripcion != null) {
todo.setDescripcion(descripcion);
}
TodoDao.instance.getModel().put(id, todo);
servletResponse.sendRedirect("../crea_todo.html");
}
// Define que el siguiente parámetro path después de todos es tratado
// como un parámetro y pasado al TodoResources
// Permite al type http://localhost:8080/it.adesales.rest.crud/rest/todos/1
// 1 será tratado como parámetro todo y pasado a TodoResource
@Path("{todo}")
public TodoRecurso getTodo(@PathParam("todo") String id) {
return new TodoRecurso(uriInfo, request, id);
}
}
Este TodosRecurso usa la anotación @PathParam para definir que el id es insertado como
parámetro.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
9.4. Corre
Corre tu aplicación web en Eclipse y prueba la disponibilidad de tu servicio REST bajo: http://localhost:8080/it.adesales.rest.crud/rest/todos . Debes ver la representación XML de tus elementos TODO.
Para ver el conteo de los elementos de TODO usa la dirección http://localhost:8080/it.adesales.rest.crud/rest/todos/conteo
para ver un TODO existente usa "http://localhost:8080/it.adesales.rest.crud/rest/todos/{id}", p.e., http://localhost:8080/it.adesales.rest.crud/rest/todos/1 para ver el TODO con ID 1. Actualmente tenemos sólo TODOs con los ids 1 y 2, todas las otras requests darán como resultado un código de error HTTP.
En la siguiente pantalla se muestra la versión solicitada en XML del todo con id=1.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
En la siguiente pantalla se muestra el todo con id=2 desde la herramienta de chrome Postman.
La siguiente pantalla es de una request POST, ingresando los parámetros y el Content-Type por la herramienta Postman.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Si consultamos los recursos disponibles después de haber emitido la request POST a través de la herramienta Postman, podremos ver lo siguiente desde el navegador o la misma tool:
Por favor, nota que con el navegador sólo puedes emitir solicitudes GET HTTP. En el siguiente capítulo usaremos las librerías cliente de Jersey para emitir get, post y delete.
Sólo quisiera hacer una aclaración, debido a que otra aplicación ocupa el puerto 8080 de mi equipo, he tenido que cofigurar Tomcat para que ocupe el puerto 80 en vez del 8080 que trae por default, por ello en mis requests después de localhost omito el puerto ya que es el default 80 donde un equipo escucha requests HTTP.
Puedes omitir el siguiente punto si utilizas la herramienta Postman ya que es el cliente.
9.5. Crea un cliente
Para probar tu servicio puedes crear una nueva clase en el proyecto servidor. Este proyecto
ya tiene todas las librerías requeridas en el classpath, de forma que este es más rápido que crear un nuevo proyecto.
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Crea la siguiente clase.
package com.vogella.jersey.todo.client;
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.client.ClientConfig;
import it.adesales.rest.crud.model.Todo;
public class Tester {
public static void main(String[] args) {
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget service = client.target(getBaseURI());
// crea un todo
Todo todo = new Todo("3", "Blabla");
Response response =
service.path("rest").path("todos").path(todo.getId()).request(MediaType.APPLICATI
ON_XML).put(Entity.entity(todo,MediaType.APPLICATION_XML),Response.class);
// El código de retorno debe ser 201 == recurso creado
System.out.println(response.getStatus());
// Obtén los Todos
System.out.println(service.path("rest").path("todos").request().accept(MediaType.
TEXT_XML).get(String.class));
// // Obtén JSON para la aplicación
//
System.out.println(service.path("rest").path("todos").request().accept(MediaType.
APPLICATION_JSON).get(String.class));
// Obtiene el XML para la aplicación
System.out.println(service.path("rest").path("todos").request().accept(MediaType.
APPLICATION_XML).get(String.class));
//Obtiene Todo con id 1
Response checkDelete =
service.path("rest").path("todos/1").request().accept(MediaType.APPLICATION_XML).
get();
//Elimina Todo con id 1
service.path("rest").path("todos/1").request().delete();
//Obtiene todos los Todos con id 1 quedeben ser eliminados
System.out.println(service.path("rest").path("todos").request().accept(MediaType.
APPLICATION_XML).get(String.class));
//Crea un Todo
Tutorial - REST con Java (JAX-RS) usando Jersey
www.facebook.com/JavaDevelopersMexico Ing. Abimael Desales López
Form form =new Form();
form.param("id", "4");
form.param("resumen","Demostración de la librería cliente para formularios");
response =
service.path("rest").path("todos").request().post(Entity.entity(form,MediaType.AP
PLICATION_FORM_URLENCODED),Response.class);
System.out.println("Response del formulario" + response.getStatus());
//Obtiene todos los todos, id 4 deben haber sido creados
System.out.println(service.path("rest").path("todos").request().accept(MediaType.
APPLICATION_XML).get(String.class));
}
private static URI getBaseURI() {
return
UriBuilder.fromUri("http://localhost:8080/it.adesales.rest.crud").build();
}
}
9.6. Usando el servicio REST vía página HTML
El ejemplo anterior contiene un formulario que llama a un método post de tu servicio rest.
Bibliografía y Webgrafía
El presente artículo ha sido conformado por ejemplos de libros y de artículos de la web, de los cuales se pretende ofrecer lo mejor de cada uno, una mención especial a la página de Lars Vogel y a tutorialespoint.com, gracias por sus buenos artículos, ha sido el comienzo y aquí hemos buscado mejorarlos, estos se mencionan a continuación:
1.- http://www.vogella.com/
2.- http://www.tutorialspoint.com/
3.- https://es.wikipedia.org/wiki/Representational_State_Transfer
4.- Kalali Masoud y Bhakti Mehta, Developing RESTful Services with JAXRS 2.0, WebSockets and
JSON, PACKT Publishing, UK, 2013, 128 p.
5.- Burke, Bill. RESTful Java with JAXRS 2.0. O’ Really Editorial, Second Edition, USA, 2014, 392 p.
Siéntete libre de escribirme y hacerme llegar tus opiniones.