Mster
Universitario
en
Ingeniera
Inform3ca
REST: introduccin
Sistemas de Informacin Orientados a Servicios
RODRIGO SANTAMARA
Invocacin de un
servicio web
Autenticacin
Navegadores
cURL
Java
Creacin de un
servicio web en Java
REST: introduccin
Invocacin de un servicio web
3
AUTENTICACIN
NAVEGADORES
CURL
JAVA
Uso de un servicio web
4
Existen muchos servicios web cuya API se puede
utilizar (generalmente, previa autenticacin)
Una buena coleccin actualizada:
[Link]
Un ejemplo que no necesita autenticacin: The Cat
API
[Link]
h7p://[Link]/humor?utm_source=tny&utm_campaign=generalsocial&utm_medium=facebook&mbid=social_facebook
Autenticacin
6
Actualmente, casi todos los servicios web requieren
algn tipo de autenticacin previa
Generalmente a travs de OAuth (Open Authorization), un
protocolo de autenticacin de APIs
O
mediante algn sistema ms sencillo de registro
Complica las invocaciones a la API (sobre todo de manera
manual)
Mejora la seguridad de los servidores de servicios web
Navegadores
7
Antes hemos invocado servicios directamente desde
un navegador web
Al ser URLs, es posible siempre que sean servicios GET
Ejemplos: The Cat API
[Link]
Obtener un xml con 20 gatos aleatorios:
[Link]
format=xml&results_per_page=20
Obtener
un gif aleatorio (slo la fuente)
[Link]
cURL
8
cURL es una orden UNIX para intercambio de
informacin mediante el protocolo HTTP
Es un modo rpido y efectivo de probar servicios web manualmente
Sintaxis
curl [opciones] 'url'
opciones
--request 'tipo' (GET, POST, UPDATE, DELETE)
--header 'cabecera'
-k evita uso de certificados
--data 'datos adicionales'
ejemplo:
curl
'[Link]
format=html&type=gif'
Java
9
Utilizamos clases de [Link] y [Link], como para acceder a cualquier
otro recurso web:
URL url = new URL("[Link]
HttpURLConnection conn = (HttpURLConnection) [Link]();
[Link]("GET");
if ([Link]() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ [Link]());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
([Link]())));
String output;
[Link]("Output from Server .... \n");
while ((output = [Link]()) != null) {
[Link](output);
}
[Link]();
Creacin de un servicio web
10
JAX-RS Y ANOTACIONES
ECLIPSE + TOMCAT + JERSEY
SERVIDOR Y CLIENTE
INTERFACES
REST
JAX-RS
11
Para crear un servicio web necesitamos algo ms que
los objetos de Java para manejo de conexiones
JAX-RS (Java API for RESTful web services) es una
API de Java para crear servicios web tipo REST
Jersey ([Link]) es su implementacin ms estable
Un objeto java (POJO Plain Old Java Object) se
convierte en un recurso web aadindole
anotaciones
Sintaxis incorporada a Java en la versin 1.5
Provee informacin sobre el cdigo, pero no es cdigo
Informacin
para la compilacin, desarrollo o ejecucin
JAX-RS: anotaciones
12
@Path indica la ruta relativa a aadir a la URI para
acceder a una clase o mtodo
@GET, @PUT, @POST, @DELETE, @HEAD hacen
referencia al tipo de peticin HTTP que satisface un
mtodo
@Produces especifica el tipo MIME que retorna
(plain, html, json, xml, etc.) un mtodo
@Consumes especifica el tipo MIME que requiere un mtodo
Existen ms anotaciones, stas son slo las
esenciales
JAX-RS: anotaciones
13
Por ejemplo:
@GET!
@Produces(MediaType.TEXT_PLAIN)!
@Path(/saludo);!
public String saludar(){ return Hola; }!
Retornar un mensaje en texto plano que dice
Hola al acceder a [Link]
(mtodo GET)
Esquema
14
Anotaciones
Java 1.5
JAX-RS
Cliente REST
(va JAX-RS)
!
ClientConfig conf = new DefaultClientConfig();!
Client client = [Link](conf);!
!
URI uri=UriBuilder!
!.fromUri("[Link]
WebResource service= [Link](uri);!
!
[Link]([Link](classPath")!
!.path(hello").accept(MediaType.TEXT_PLAIN)!
!.get([Link]))!
Servicio REST
@GET!
@Produces(MediaType.TEXT_PLAIN)!
@Path(hello);!
public String saludar(){ return Hola; }!
Preparacin del entorno
15
Descargar Tomcat 6.0 de [Link]
Descargar Eclipse
Instalar plugin para desarrollo web: WTP
Help/Install
New Software
[Link]
Web, XML, Java EE, etc.
O bien descargar la versin para desarrolladores EE
Descargar Jersey ([Link] buscar el
enlace en Downloads (JAX-RS 2.0 API jar)
Al crear el proyecto tendremos que agregar dichos jars
Creacin del proyecto
16
Crear un nuevo proyecto web:
File/New/Project Web/Dynamic Web Project
En la carpeta WebContent/WEB-INF/lib, incluir
todos los jars que hay en las carpetas jersey/lib,
jersey/api y jersey/ext
En [Link] se encuentran algunas
de las clases y ficheros que vamos a usar de ejemplo
Fichero [Link]
17
Modificar el fichero WebContent/WEB-INF/[Link]
por este otro:
[Link]
display-name debe coincidir con el nombre del
proyecto
[Link]
debe tener como valor una lista de nombres de paquetes
en los que tenemos recursos REST, separados por punto
y coma.
url-pattern dentro de servlet-mapping debe ser
la ruta base a partir de la que se ubicarn los recursos
REST
Ejemplo de servicio
18
//Sets the path to base URL + /hello
@Path("/hello")
public class Hello
{
// This method is called if TEXT_PLAIN is request
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
return "Hello Jersey";
}
// This method is called if XML is request
@GET
@Produces(MediaType.TEXT_XML)
public String sayXMLHello() {
return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>";
}
// This method is called if HTML is request
@GET
@Produces(MediaType.TEXT_HTML)
public String sayHtmlHello() {
return "<html> " + "<title>" + "Hello Jersey" + "</title>"
+ "<body><h1>" + "Hello Jersey" + "</body></h1>" + "</html> ";
}
}
[Link]
Ruta del servicio
19
[Link]
localhost o la ip del equipo remoto
(mejor ips que nombres, pues pueden estar
corruptos en el lab. de informtica)
indicado con la anotacin @Path antes de un mtodo
puede no usarse si se tiene ruta ya en la clase
indicado con la anotacin @Path antes de una clase
podemos no usarlo, pero es recomendable para
guardar un cierto orden
indicado en el tag <url-pattern> de <servlet-mapping> en [Link]
p. ej. si queremos que sea servlet usamos /servlet/*
Podemos no usarlo, poniendo simplemente /*
nombre del proyecto en el IDE, que debe
coincidir con el tag <display-name> de [Link]
Arranque del servicio
20
Arrancar el servicio: Run/Run As/Run on Server
Especificar Tomcat como servidor en el que arrancarlo
Target
runtime (o New si no est)
Errores frecuentes:
[Link]: [Link]
Los jar de Jersey no se han incluido correctamente en WebContent/WEB-INF/lib
[Link]: The ResourceConfig instance does not contain any root
resource classes.
El parmetro [Link] no se ha configurado correctamente en [Link]: debe
contener los nombres de los paquetes que contienen clases anotadas.
El servidor arranca pero no hay nada en las rutas esperadas
El parmetro [Link] no se ha configurado correctamente en [Link]: debe
contener los nombres de los paquetes que contienen clases anotadas.
Revisar los @Path, y los tags <display-name> y<servlet-mapping> en [Link]
Ejemplo de cliente
21
public class Test {
public static void main(String args[])
{
Client client=[Link]();;
URI uri=[Link]("[Link]
WebTarget target = [Link](uri);
[Link]([Link]("rest").path("hello").request(MediaType.TEXT_PLAIN).get
([Link]));
[Link]([Link]("rest").path("hello").request(MediaType.TEXT_XML).get
([Link]));
[Link]([Link]("rest").path("hello").request(MediaType.TEXT_HTML).get
([Link]));
}
}
Se ejecuta como una aplicacin Java normal
[Link]
Ejercicio
22
Crear un servicio REST hello mediante Eclipse,
Tomcat y Jersey.
Iniciar en la mquina local y probar accesos de clientes
Desde
un navegador y desde java
Desde la mquina local y desde otras mquinas
Paso de argumentos
23
Paso de argumentos: anotacin @QueryParam:
@Path(calculator")
public class Calculator
{
@Path(sq")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String square(@DefaultValue("2") @QueryParam(value="num") long num)
{
return ""+num*num;
}
}
Desde URL
[Link]
Desde Java
[Link]("calculator/sq").queryParam("num", "+3).request
(MEDIATYPE.TEXT_PLAIN).GET([Link])
Retorno de objetos
24
En principio, Jersey retorna tipos MIME (es decir,
texto, en distintos formatos)
Jersey no soporta la serializacin de tipos primitivos
Debemos usar String + documentacin de la API
Si intentamos, por ejemplo, retornar un long:
[Link]: A message body writer for Java class
[Link], and Java type long, and MIME media type XXX was not found
Solucin: convertir objetos Java en texto (p. ej. XML)
Jersey da soporte para ello a JAXB, una arquitectura para
asociar clases Java a representaciones XML
Retorno de objetos nuevos
25
declaracin
@XmlRootElement
public class Planet
{
public int id;
public String name;
public double radius;
}
servicio
Usamos @XmlRootElement + APPLICATION_XML
@Path("planet")
public class Resource {
@GET
@Produces(MediaType.APPLICATION_XML)
public Planet getPlanet() {
Planet p = new Planet();
[Link] = 1;
[Link] = "Earth";
[Link] = 1.0;
return p;
}
}
cliente
Planet planet = [Link]("rest/planet").request
(MediaType.APPLICATION_XML_TYPE).get([Link]);
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<planet>
<id>1</id>
<name>Earth</name>
<radius>1.0</radius>
</planet>
Retorno de POJOs
26
Usamos la clase JAXBElement +
APPLICATION_XML
servicio
@Path("calendario")
public class Calendario {
@GET
@Produces(MediaType.APPLICATION_XML)
public JAXBElement<Date> getDate()
{
Date p = new Date([Link]());
return new JAXBElement<Date>(new QName("date"), [Link], p);
}
}
cliente
GenericType<JAXBElement<Date>> dateType = new GenericType<JAXBElement<Date>>() {};
Date fecha = (Date) [Link]("rest/calendario").request
(MediaType.APPLICATION_XML_TYPE).get(dateType).getValue();
[Link]("### + [Link]());
Creacin de un servicio REST
27
Respecto al uso de argumentos y el retorno de
objetos, un buen diseo de un sistema distribuido
minimiza las interfaces
Suponen
una carga en el trfico de red
Y ms si hay que convertirlos a XML
Incrementan el riesgo de errores
Interpretaciones equivocadas de la API
Las clases tienen que estar disponibles por los clientes
Etc.
Muchos objetos son evitables con un uso inteligente de String
Ciclo de vida de los objetos
28
En Jersey, los objetos tienen un ciclo de vida per-
request
Cada clase que se ofrece como recurso se instancia con cada
nueva peticin y se destruye al terminar dicha peticin
Esto
impide mantener objetos que varan su estado a lo largo del
tiempo (a travs de distintas peticiones)
Solucin:
Utilizar
la anotacin @Singleton para la clase
As, la clase se instancia una vez por aplicacin web, y
permanece instanciada hasta que se apague o reinicie el servicio
Ejercicio
29
Crear un servicio REST calculator que permita
realizar potencias cuadradas (sq) y sumas de dos
elementos (add)
Obtendr mediante parmetros el nmero a elevar al cuadrado
y los dos nmeros a sumar (todos enteros)
Retornar el resultado como una cadena de texto
Aadir una tercera funcin stack(int n) que sume el
valor n a una variable interna del servicio que
comienza en 0
Tutoriales
30
[Link]
Preparacin bsica para trabajar con Jersey+Tomcat+Eclipse
[Link]
[Link]
Manual completo de Jersey, en especial:
Paso
de argumentos (cap 3.2)
Ciclo de vida de los recursos (3.4)
Carrera 100m lisos
31
EJERCICIO
Servicio
32
Crear un servicio REST mediante una clase Carrera100
El servicio se llamar carrera100 y aceptar 4 atletas
Mantendr informacin sobre
Nmero
de atletas inscritos en la carrera
Tiempo de inicio de la carrera y de llegada de cada atleta
Ofrecer los mtodos
reinicio:
pone los tiempos y los atletas inscritos a cero
preparado: detiene al atleta que lo llama hasta que todos los atletas
estn preparados
listo: detiene al atleta que lo llama hasta que todos los atletas estn
listos. Una vez estn todos listos, la carrera empieza
llegada(dorsal): guarda el tiempo de llegada del atleta y retorna el
tiempo obtenido por el atleta.
resultados: retorna una cadena con algn formato que muestre los
resultados de la carrera
Cliente
33
La clase Atleta ser un hilo (Thread) que:
Se construir con un determinado dorsal
Durante su ejecucin
1.
2.
3.
4.
Invoca carrera100/preparado
Invoca carrera100/listo
Corre (duerme entre 9.56 y 11.76s)
Invoca carrera100/llegada?dorsal=midorsal
Para hacer una carrera puede haber una clase
MainCarrera
1.
2.
3.
Invoca carrera100/reinicio
Crea 4 Atletas y los pone a correr
Invoca carrera100/resultados
Ejemplo con 2 procesos
34
Carrera
A1
A2
preparado
preparado
numPreparados++
numPreparados++
listo
listo
numListos++
numListos++
9.56-11.76s
llegada
llegada
> A2: 9.83s
> A2: 11.07s
Despliegue
35
Ejecutar el servicio y la carrera en el mismo
ordenador
Probar con 2 ordenadores
En uno corre el servicio y dos atletas
En el otro corren los otros dos atletas
Probar con 3 ordenadores, con 6 atletas
En cada uno corren dos atletas
En uno de ellos corre el servicio
Despliegue: determinar IP del servidor
36
Para que los clientes sepan dnde est
/sbin/ifconfig
/sbin/ifconfig | grep 'inet addr:' | grep -v
'[Link]' | cut -d: f2 | awk '{print $1}
Para
extraer los nmero de la ip
Despliegue: reparto de clases
37
Bsico:
Almacenar las clases en Z:
Estarn disponibles en todos los ordenadores si nos conectamos con
el mismo usuario
Avanzado:
Pensando en otros sistemas donde no tengamos un servicio
distribuido de directorios
Podemos generar un script de envo remoto mediante ssh/scp
Ver
los scripts [Link] y [Link] en
[Link]
Pro:
Podemos generar un .jar con las clases y bibliotecas necesarias y
enviarlas mediante scripts/ssh
Despliegue: ejecucin
38
El servidor se arranca inicialmente
Bsico: usaremos Eclipse para ello
Avanzado: generar proyecto .war o similares
Pro: crear un demonio que arranque con el ordenador
Luego arrancamos los clientes
Bsico: a travs de Eclipse (requiere arrancar Eclipse en todos
los ordenadores)
Avanzado: ejecutarlos desde consola, localmente (requiere
acceso fsico a todos los ordenadores)
Pro: ejecutarlos desde consola, remotamente (todo se hace
desde un solo ordenador)
Podemos
usar los scripts vistos en el reparto de clases
Despliegue: reinicio y resultados
39
Reinicio
Clase MainCarrera que reinicie el servicio
Reinicio manual a travs del navegador
Reinicio a travs de un Atleta ([Link]. el que tiene dorsal 0)
Nos
tenemos que asegurar que arranca antes que el resto
Resultados
Las mismas opciones que para el reinicio
Coordinacin y tiempos
40
Probar qu pasa si los Atletas no esperan a las
rdenes de preparados y listos, y empiezan a correr
en cuanto pueden
En distintos despliegues
Probar qu pasa si los tiempos los miden los propios
Atletas
En distintos despliegues
De forma relativa (he tardado t_final menos t_inicial)
Obteniendo
ellos el t_inicial
Tomndolo el t_inicial de la carrera
De forma absoluta (he llegado en t_final)
Anlisis
41
Qu posibles fallos encuentras en el sistema
implementado?
Relativos a los tiempos
Relativos a la coordinacin
Relativos a posibles fallos de proceso
Relativos a posibles fallos de comunicacin
Se te ocurren mejoras posibles para el sistema?