Sesión 2: Acceso a servicios RESTful - Experto Javaexpertojava.ua.es › dadm › restringido ›...
Transcript of Sesión 2: Acceso a servicios RESTful - Experto Javaexpertojava.ua.es › dadm › restringido ›...
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a servicios web
Sesión 2: Acceso a servicios RESTful
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Puntos a tratar• Fundamentos de REST• Tipos de peticiones HTTP• Invocación de servicios• Parsing de XML• Parsing de JSON
2
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Acceso a servicios web desde el móvil• Normalmente accedemos a la web desde un navegador• Obtiene documentos (HTML) para mostrar al usuario
• Acceso desde una aplicación móvil • Necesitamos obtener información, no presentación• Resulta adecuado acceder a servicios web
• Definición de servicio• Interfaz que da acceso a un módulo de funcionalidad
• Servicio web• Servicio al que se accede mediante protocolos web (HTTP, XML)
• Tipos de servicios• SOAP: Muy pesado. Adecuado para integración de aplicaciones• RESTful: Ligero y sencillo. Adecuado para web y móviles
3
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Fundamentos de REST
• REST: REpresentational State Transfer. Son un conjunto de restricciones que, aplicadas al diseño de un sistema, crean un estilo arquitectónico caracterizado por:• Debe ser un sistema cliente-servidor• Tiene que ser sin estado• Tiene que soportar cachés• Tiene que ser un sistema uniformemente accesible (a través de URIs)• Tiene que ser un sistema por capas (escalabilidad)
• Estas restricciones no dictan qué tipo de tecnología utilizar. Podemos utilizar las infraestructuras de red existentes• Un ejemplo de sistema RESTful: la web estática
4
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Recursos• Un recurso es “cualquier cosa” que pueda ser accedido y
transferido a través de la red:
• Es una correspondencia lógica y temporal con un concepto del domino del problema
• Ejemplos: una noticia de un periódico, la temperatura de Alicante, un valor de IVA almacenado en una BD...
• Cada uno de los recursos puede ser accedido directamente, y de forma independiente, pero diferentes peticiones podrían “apuntar” al mismo dato
• La representación de un recurso depende del tipo solicitado por el cliente (tipo MIME)
5
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Representación• Lo que se intercambia entre los consumidores (clientes) y los
productores de servicios son representaciones de los recursos.• Una representación muestra el estado de un dato real
almacenado en algún dispositivo de almacenamiento en el momento de la petición
• Durante el ciclo de vida del servicio web, puede haber varios clientes solicitando recursos. Clientes diferentes pueden solicitar diferentes representaciones del mismo recurso
• El “lenguaje” de intercambio de información (representación) con el servicio queda a elección del desarrollador
• Ejemplos de representaciones comunes son:
6
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
URI• Una URI (Uniform Resource Identifier), en un servicio web
RESTful es un hiper-enlace a un recurso, y es la única forma de intercambiar representaciones entre clientes y servidores
• En un sistema REST la URI no cambia a lo largo del tiempo• Si, por ejemplo, en nuestro sistema tenemos información de
cursos, podríamos acceder a una lista de cursos disponibles mediante la siguiente URL:• http://jtech.ua.es/resources/cursos• Esto nos podría devolver un documento como el siguiente:
7
<?xml version="1.0"?><j:Cursos xmlns:j="http://www.jtech.ua.es" xmlns:xlink="http://www.w3.org/1999/xlink"> <Curso id="1" xlink:href="http://jtech.ua.es/resources/cursos/1"/> <Curso id="2" xlink:href="http://jtech.ua.es/resources/cursos/2"/> <Curso id="4" xlink:href="http://jtech.ua.es/resources/cursos/4"/> <Curso id="6" xlink:href="http://jtech.ua.es/resources/cursos/6"/></j:Cursos>
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Uniformidad de las interfaces• El desarrollo de REST está centrado en el concepto de nombres
(intercambio de recursos)• Un servicio RESTful modifica el estado de los datos a través de
la representación de los recursos• Un servicio RESTful limita la ambigüedad en el diseño y la
implementación restringiendo las operaciones que podemos realizar con los recursos: create, retrieve, update, delete• La correspondencia de estas acciones con métodos HTTP son:
8
Un servicio REST puede ejecutar lógica en el lado del servidor, pero cada respuesta debe ser una representación del recurso del dominio en cuestión
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Obtención de recursos
• Supongamos que tenemos las siguientes representaciones XML
9
http://restful.java/students/Janehttp://restful.java/students
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
GET/RETRIEVE
• http://restful.java/students/Jane con el método GET• Seguro e idempotente
10
200 OkDevuelve el recurso
404 Not found Si no existe el recurso
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
POST/CREATE
• http://restful.java/students/ con el método POST• No idempotente
11
201 CreateNuevo recurso creado
Location URI del recurso
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
PUT/UPDATE
• http://restful.java/students/Jane con el método PUT• Idempotente
12
204 No contentRecurso modificado
201 Created Nuevo recurso creado
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
DELETE/DELETE
• http://restful.java/students/Jane con el método DELETE
13
200 OkDevuelve el recurso borrado
204 No content
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Invocación desde una aplicación de escritorio
14
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Invocación desde una clase Java• Cliente RESTful de Twitter
15
public class ClienteTwitter { public void obtenerTimeline() { try { URL twitter = new URL("http://twitter.com/statuses/public_timeline.xml"); // Abrimos la conexión URLConnection tc = twitter.openConnection(); // Obtenemos la respuesta del servidor BufferedReader in = new BufferedReader(new InputStreamReader(tc.getInputStream())); // Leemos la respuesta del servidor y la imprimimos String line; while ((line = in.readLine()) != null) { escribirLog(line); } return result; } catch (MalformedURLException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }}
Android
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Resultado obtenido
• Mostramos parte de uno de los tweets
16
<?xml version="1.0" encoding="UTF-‐8"?> <statuses type="array"> ... <status> <created_at>Tue Feb 22 11:43:25 +0000 2011</created_at> <id>40013788233216000</id> <text>Haar doen voor de cam. #ahahah</text> <source>web</source> <truncated>false</truncated> <favorited>false</favorited> <in_reply_to_status_id></in_reply_to_status_id> <in_reply_to_user_id></in_reply_to_user_id> <in_reply_to_screen_name></in_reply_to_screen_name> <retweet_count>0</retweet_count> <retweeted>false</retweeted> <user> ... </user> </status>...</statuses>
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Invocación con HttpClient• En lugar de utilizar el paquete estándar java.net,
habitualmente se utiliza la librería HttpClient de Apache
17
HttpClient client = new DefaultHttpClient();HttpGet request = new HttpGet( "http://twitter.com/statuses/public_timeline.xml");try { ResponseHandler<String> handler = new BasicResponseHandler(); String contenido = client.execute(request, handler); tvResponse.setText(contenido); } catch (ClientProtocolException e) {} catch (IOException e) {} finally { client.getConnectionManager().shutdown();}
Android
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Configuración de peticiones• Con el estilo RESTful es habitual tener que acceder a URLs con
distintos comandos HTTP: GET, PUT, DELETE• En algunos casos debemos enviar contenido con la petición• Podemos pedir una representación con la cabecera Accept
18
HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("http://jtech.ua.es/recursos/peliculas");StringEntity s = new StringEntity("[contenido xml]");s.setContentType("application/xml");post.setEntity(s);post.setHeader("Accept", "application/xml"); ResponseHandler<String> handler = new BasicResponseHandler();String respuesta = client.execute(post, handler);
Android
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Invocación de servicios con iOS• Si queremos personalizar la petición deberemos utilizar NSMutableURLRequest
19
NSURL *url = [NSURL URLWithString:@"http://jtech.ua.es/resources/peliculas"];NSData *datosPelicula = ... // Componer mensaje XML con datos de la // película a crear NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL: url];[theRequest setHTTPMethod: @"POST"];[theRequest setHTTPBody: datosPelicula];[theRequest setValue:@"application/xml" forHTTPHeaderField:@"Accept"];[theRequest setValue:@"application/xml" forHTTPHeaderField:@"Content-‐Type"]; NSURLConnection *theConnection = [NSURLConnection connectionWithRequest: theRequest delegate: self];
iOS
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Parsing de estructuras XML• Trocear el XML en tags, atributos, contenido por medio de
librerías. • En Android tenemos:• SAXParser: Requiere implementar manejadores que reaccionan a
eventos al encontrar etiquetas o atributos.• XmlPullParser: Itera sobre el árbol conforme el código lo va
pidiendo.• En iOS tenemos en el SDK un parser de tipo SAX:• NSXMLParser: Requiere implementar un delegado al que se le
notificarán los eventos al encontrar etiquetas o atributos.• Tenemos también un parser C tipo SAX/DOM: libxml2• Podemos incluir librerías externas
TBXML, TouchXML, KissXML, TinyXML, GDataXML
20
iOS
Android
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Ejemplo de XML• Vamos a considerar al siguiente ejemplo de documento XML
• Lo utilizaremos para los parsers que veremos a continuación• Tenemos una lista de mensajes entre las etiquetas mensajes• Para cada mensaje tenemos una etiqueta mensaje• El usuario emisor se indica como atributo de la etiqueta• El texto del mensaje se indica como texto entre la etiqueta de
apertura y de cierre
21
<mensajes> <mensaje usuario="pepe">Hola, ¿qué tal?</mensaje> <mensaje usuario="ana">Fetén</mensaje></mensajes>
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Uso del XmlPullParser
22
XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance(); XmlPullParser parser = parserCreator.newPullParser(); parser.setInput(urlInputStream, null); int parserEvent = parser.getEventType(); while (parserEvent != XmlPullParser.END_DOCUMENT) {
switch (parserEvent) { case XmlPullParser.START_DOCUMENT: break; case XmlPullParser.END_DOCUMENT: break; case XmlPullParser.START_TAG: if(parser.getName()=="mensaje") { String usuario = parser.getAttributeValue(null, "usuario"); String mensaje = parser.nextText(); } break; case XmlPullParser.END_TAG: break; } parserEvent = parser.next(); }
Inicializamos el parser a partir del flujo de entrada que lee de la URL
Comprueba el nombre de la etiqueta (<mensaje>)
Obtiene el texto entre <mensaje> y </mensaje>
Android
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Uso de NSXMLParser• Se trata de un parser de tipo SAX• Debemos definir un delegado de tipo NSXMLParserDelegate
23
-‐ (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict; -‐ (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName; -‐ (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;
Encuentra etiqueta de apertura. P. ej. <mensaje>
Encuentra etiqueta de cierre. P. ej. </mensaje>
Encuentra texto entre etiquetas. P. ej. Hola
iOS
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Etiqueta de apertura
24
-‐ (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict { if([[elementName lowercaseString] isEqualToString:@"mensajes"]) { self.listaMensajes = [NSMutableArray arrayWithCapacity: 100]; } else if([[elementName lowercaseString] isEqualToString:@"mensaje"]) { self.currentMensaje = [UAMensaje mensaje]; self.currentMensaje.usuario = [attributeDict objectForKey:@"usuario"]; } else { // No puede haber etiquetas distintas a mensajes o mensaje [parser abortParsing]; }}
iOS
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Texto y etiqueta de cierre
25
-‐ (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSString* value = [string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]; if([value length]!=0 && self.currentMensaje!=nil) { self.currentMensaje.texto = value; }}
-‐ (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if([[elementName lowercaseString] isEqualToString:@"mensaje"]) { [self.listaMensajes addObject: self.currentMensaje]; self.currentMensaje = nil; } }
iOS
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Ejecución del parser• Tenemos que crear un objeto NSXMLParser• Debemos especificar el delegado que se encargará del parsing• También especificamos el contenido XML mediante un objeto de
tipo NSData
• Al ejecutar parse se realizará el parsing de forma síncrona• Devolverá YES si todo ha ido bien• Devolverá NO si ha habido un error, esto ocurrirá si en el delegado
se llama a abortParsing
26
NSXMLParser *parser = [[NSXMLParser alloc] initWithData: self.content];parser.delegate = self;BOOL result = [parser parse];
iOS
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Estructuras JSON
• JSON es una representación muy utilizada para formatear los recursos solicitados a un servicio web RESTful
• Se trata de ficheros de texto planos que pueden ser manipulados muy fácilmente utilizando Javascript (función eval())• Los elementos están contenidos entre llaves• Los valores de los elementos se organizan en pares con la
estructura “nombre:valor” separados por comas• Las secuencias de elementos están contenidas entre corchetes
• Ejemplo:
27
[ {"texto":"Hola, ¿qué tal?", "usuario":"Pepe" }, {"texto":"Fetén", "usuario":"Ana" } ]
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Parsing de JSON en Android• Podemos utilizar los objetos JSONArray y JSONObject• Pueden encontrarse anidados
• También podemos componer mensajes JSON• Establecer atributos con métodos put-‐ (equivalentes a los get-‐)• Obtenemos el texto JSON llamando a toString()
• Alternativas más sencillas de utilizar: GSON, Jackson
28
JSONArray mensajes = new JSONArray(contenido); for(int i=0;i<mensajes.length();i++) { JSONObject mensaje = mensajes.getJSONObject(i); String texto = mensaje.getString("texto"); String usuario = mensaje.getString("usuario"); ... }
Android
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Parsing de JSON en iOS• Integrado en el SDK a partir de iOS 5• Alternativas para versiones anteriores: JSONKit, json-‐framework
• Utilizamos la clase JSONSerialization tanto para realizar el parsing como para componer mensajes JSON
29
NSError *error = nil;NSData *data = ... // Contenido JSON obtenido de la redNSArray *mensajes = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; if(error==nil) { for(NSDictionary *mensaje in mensajes) { NSString *texto = [mensaje valueForKey:@"texto"]; NSString *usuario = [mensaje valueForKey:@"usuario"]; ... } }
Devuelve NSDictionary o NSArray según si el elemento principal es { } o [ ], respectivamente
iOS
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
Composición de mensajes JSON• Creamos la estructura de objetos NSArray y NSDictionary que
queramos representar en JSON
• Utilizamos JSONSerialization para obtener la representación JSON
30
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"Hola!", @"texto", @"Pepe", @"usuario", nil];
NSData *json = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
iOS
Experto en Desarrollo de Aplicaciones para Dispositivos Móviles
Acceso a servicios web © 2012-2013 Depto. Ciencia de la Computación e IA Acceso a servicios REST
¿Preguntas...?
31