Commit e75edf47 authored by DANIEL DIAZ SANCHEZ's avatar DANIEL DIAZ SANCHEZ
Browse files

Add new file

parents
Este proyecto por su sencilles NO tiene código por lo que no se puede clonar.
# Acceso a API REST y decodificación de JSON
### Aplicaciones y librerías a utilizar
* Eclipse (podéis usar el que descargásteis el primer día)
* [Unirest](http://unirest.io/java.html): librería de peticiones HTTP (más adelante veremos como descargarla)
* [Commons](https://commons.apache.org/): librerías de funciones auxiliares (más adelante veremos como descargarla)
* [Google-Gson](https://github.com/google/gson): librería de manipulación de JSON (más adelante veremos como descargarla)
## Prueba de Unirest
A continuación, crearemos un proyecto java nuevo (New > java project):
<img src="https://gitlab.pervasive.it.uc3m.es/distributed-computing-assignements/1-restAPIs-unirest-json/raw/master/img/img002.png" width="500px"/>
Dentro de ese proyecto creamos un paquete (package) con un nombre cualquiera (es mala práctica crear las clases directamente en la raíz, por eso es mejor usar un paquete) por ejemplo "cdistRest".
<img src="https://gitlab.pervasive.it.uc3m.es/distributed-computing-assignements/1-restAPIs-unirest-json/raw/master/img/img003.png" width="500px"/>
Para realizar las peticiones vamos a usar una librería llamada UNIREST que es bastante clara y sencilla de usar.
### Añadir dependencias a un proyecto
Vamos a utilizar [Maven](https://maven.apache.org/) que ya viene integrado en eclipse para trabajar con las dependencias (librerías que usará nuestro programa). Si no usáramos maven tendríamos que añadir las librerías manualmente.
Por ejemeplo, para usar esta librería (Unirest) sería necesario bajarse un zip con la librería (ficheros jar) y las dependencias que dicha librería tenga. Más tarde habría que añadirlas manualmente añadiendo los jars (indicando la localización en el disco duro) en la pantalla de gestión de las dependencias ((Build Path> Configure Build Path pestaña Libraries):
<img src="https://gitlab.pervasive.it.uc3m.es/distributed-computing-assignements/1-restAPIs-unirest-json/raw/master/img/img005.png" width="500px"/>
Con maven es más sencillo:
1. Lo primero es transformar el proyecto en un proyecto con gestión de dependencias Maven. Para ello hay que hacer click con el botón derecho sobre el proyecto, ir al menú Configure y hacer click en Convert to Maven Project.
2. Aceptar el diálogo que emerge tras convertirlo en Maven y dar una versión a nuestro programa (déjalo por defecto como propone eclipse)
3. Abrir el fichero pom.xml generado
4. Añadir la dependencia deseada como se indica a continuación
Para saber qué dependencia añadir lo más sencillo es buscar en la página de la librería que se desea utilizar. En este caso, visitando la página de [Unirest](http://unirest.io/java.html) veremos más abajo instrucciones de instalación, entre las que encontramos maven.
Editamos el fichero pom.xml del proyecto añadiendo el texto después de build:
```xml
<dependencies>
<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.4.9</version>
</dependency>
</dependencies>
```
quedando así (se muestra solo el final del fichero):
```xml
...
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.4.9</version>
</dependency>
</dependencies>
</project>
```
Guarda el fichero pom.xml y verás como Eclipse descarga los ficheros necesarios automáticamente. Podrás verlos en la carpeta Maven dependencies de tu proyecto.
Si alguna vez no encontramos alguna librería, se puede buscar en maven central (o google) y localizaremos la librería en esta [página](https://mvnrepository.com/artifact/com.mashape.unirest/unirest-java/1.4.9).
### Analizar las peticiones HTTP a una aplicación
Usaremos como ejemplo la aplicación [4-app-engine-servlet-api-search](https://gitlab.pervasive.it.uc3m.es/distributed-computing-assignements/4-app-engine-servlet-api-search) que hicimos el otro día.
Vamos a analizar dicha aplicación desde el punto de vista de las peticiones que le hacemos. Sabemos que nuestra aplicación nos muestra un interfaz de usuario amigable en la página http://localhost:8888/shareSomething.jsp y que cuando ponemos un texto en la búsqueda y pulsamos el botón "Search it!" o bien escribimos algo en la caja de texto de abajo y pulsamos "send it!" se generan peticiones HTTP POST a la dirección http://localhost:888/shareSomething donde se encuentra el servlet.
Nuestra aplicación es algo rudimentaria, y no dispone de un interfaz rest claramente definido, pero de momento, nos vale para el propósito de comenzar con la librería.
Si analizamos las peticiones, encontramos lo siguiente.
* Para compartir algo (botón send it!), tras escribir, por ejemplo "prueba" en la caja de texto y pulsar el botón "send it", se genera la siguiente petición HTTP:
```
POST /shareSomething HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Content-Length: 77
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://192.168.1.8:8888/shareSomething
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8,es;q=0.6
searchText=&something=prueba&username=anonymousUser192.168.1.6&POST=Send+it%21
```
Para realizar esta petición correctamente sólo tenemos que usar las cabeceras HTTP `Host`, e incluir el cuerpo.
En el cuerpo `searchText=&something=prueba&username=anonymousUser192.168.1.6&POST=Send+it%21`, podemos ver que, además de los parámetros normales de la aplicación, incluye el texto a compartir `something=prueba` . Por lo que la petición, simplificada (*lo demás lo añade el navegador*) sería:
```
POST /shareSomething HTTP/1.1
Host: localhost:8888
Content-Length: 77
Content-Type: application/x-www-form-urlencoded
searchText=&something=prueba&username=anonymousUser192.168.1.6&POST=Send+it%21
```
* Para buscar algo (botón Search it!), tras escribir, por ejemplo "texto búsqueda" y pulsar el botón, se genera la siguiente petición:
```
POST /shareSomething HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Content-Length: 95
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:8888/shareSomething
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8,es;q=0.6
searchText=texto+b%C3%BAsqueda&SEARCH=Search+it%21&something=&username=anonymousUser192.168.1.6
```
* Que simplificada sería:
```
POST /shareSomething HTTP/1.1
Host: localhost:8888
Content-Length: 95
Content-Type: application/x-www-form-urlencoded
searchText=texto+b%C3%BAsqueda&SEARCH=Search+it%21&something=&username=anonymousUser192.168.1.6
```
### Realizar peticiones HTTP
Vamos a utilizar UniRest debido a que es sencilla de usar, fácil de entender, y además gestiona la concurrencia y los hilos por nosotros. Hay otras alternativas, pero esta es muy intuitiva.
En el proyecto que hemos creado para esta prácica, añadimos una clase llamada `RequestSomething.java` dentro del paquete anteriormente creado (`CdistRest` o el que hayáis elegido).
Utiliza el siguiente código:
```java
package cdistRest;
import java.io.IOException;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.GetRequest;
import com.mashape.unirest.request.body.MultipartBody;
public class RequestSomething {
public static void main(String args[])
{
try {
/* solicitamos la página donde está el JSP */
// localhost:8888/shareSomething.jsp
// declaramos una variable para la respuesta
HttpResponse<String> stringResponse = null;
// declaramos una petición tipo get
GetRequest getReq = null;
// construimos la petición
getReq = Unirest.get("http:// localhost:8888/shareSomething.jsp")
// si tuviera algún campo /shareSomething.jsp?param=value
//.field("param", "value")
.header("host", " localhost:8888");
System.out.println("Request to: " + getReq.getUrl());
// obtenermos la respuesta
stringResponse = getReq.asString();
// imprimimos el resultado
System.out.println("Result : " + stringResponse.getBody().toString());
/* hacemos varios POSTs al servlet (no al JSP) para publicar */
// declaramos una variable para la respuesta
HttpResponse<String> stringResponseToPost = null;
// declaramos una petición tipo POST
MultipartBody postReq = null;
String somethings[] = {"Primera cosa para publicar", "Segunda cosa para publicar", "Tercera cosa para publicar"};
for(String something: somethings)
{
postReq = Unirest.post("http://localhost:8888/shareSomething")
.field("searchText", "")
.field("something", something)
.field("username", "anonymouslocalhost")
.field("POST","Send it!");
// obtenermos la respuesta
stringResponse = postReq.asString();
}
/* hacemos varios POSTs al servlet (no al JSP) para buscar */
String busquedas[] = {"cosa", "para", "publicar"};
for(String busqueda: busquedas)
{
postReq = Unirest.post("http://localhost:8888/shareSomething")
.field("searchText", busqueda )
.field("SEARCH","Search it!")
.field("something", "")
.field("username", "anonymouslocalhost");
// obtenermos la respuesta
stringResponse = postReq.asString();
}
Unirest.shutdown();
} catch (UnirestException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
```
Para probarlo, primerlo ejecuta la aplicación web, verifica que funciona con un navegador. Luego haz debug con el programa recién creado y observa como funciona.
## Formato JSON
En la prueba anterior hemos realizado peticiones en un formato específico de la aplicación. En la vida real no se hace así, suele usarse JSON.
La información que obtenemos como respuesta a las peticiones que hacemos a nuestra aplicación es HTML, que es bastante complicado de interpretar de forma automática. De hecho, HTML está destinado a presentar información más que a comunicar información estructurada entre máquinas, por eso decimos que nuestra aplicación es rudimentaria (ya la evolucionaremos más adelante).
Uno de los formatos más comunes para intercambiar información es JSON. Aquí tenéis un ejemplo de una información codificada en JSON:
```json
[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName": "Jones"}
]
```
Para procesar JSON usaremos la librería [GSON de Google](https://github.com/google/gson). Añadiremos esta dependencia usando maven. La porción XML para añadir la puedes encontrar en la página del proyecto, haciendo click en maven. Te llevará a esta [página en el caso de la versión 2.7](http://search.maven.org/#artifactdetails%7Ccom.google.code.gson%7Cgson%7C2.7%7C)
En la página puedes encontrar la porción de XML que sería:
```xml
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
```
Quedando el final del fichero pom.xml así:
```xml
...
</build>
<dependencies>
<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.4.9</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
</project>
```
Guarda el fichero y prueba este código:
```java
package cdistRest;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
public class TestJSON {
public class Employee {
private String firstName;
private String lastName;
public Employee(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}
public String toString()
{
return "name : " + firstName + " surname : " + lastName;
}
}
public TestJSON() {
// Crear un JSON
Collection<Employee> colection = new ArrayList<Employee>();
Employee e1 = new Employee("John", "Doe");
Employee e2 = new Employee("Anna", "Smith");
Employee e3 = new Employee("Peter", "Jones");
colection.add(e1);
colection.add(e2);
colection.add(e3);
Gson gson = new Gson();
String json_represntation = gson.toJson(colection);
System.out.print(json_represntation);
// al revés, pero más complicado
// procesar un mensaje recibido con JSON, en el que no solo hay tipos Empoyee
/*
{
"mensaje": "mi mensaje",
"id": "21"
}
[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName": "Jones"}
]
*/
/* los pares string : string son como Maps<String, String> */
/* los pares string : object son Maps<String, Object> */
Type jType = new TypeToken<HashMap<String,Object>>(){}.getType();
String json_recibido = "{\"mensaje\": \"mi mensaje\", \"id\": \"21\"}";
String json_recibido2 = "[{\"firstName\":\"John\", \"lastName\":\"Doe\"},{\"firstName\":\"Anna\", \"lastName\":\"Smith\"},{\"firstName\":\"Peter\", \"lastName\": \"Jones\"}]";
HashMap<String,Object> mensaje = gson.fromJson(json_recibido, jType);
System.out.println(mensaje.get("mensaje"));
System.out.println(mensaje.get("id"));
JsonParser parser = new JsonParser();
JsonArray employees = parser.parse(json_recibido2).getAsJsonArray();
for(JsonElement jemployee : employees)
{
Employee employee = gson.fromJson(jemployee, Employee.class);
System.out.println("Info empleado " + employee.toString());
}
}
public static void main(String args[]) {
new TestJSON();
}
}
```
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment