M4-UF1 FRAMEWORK SPRING
UNIDAD 11: Servicios Web
eugeniaperez.es
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Un servicio web constituye un método que es accedido a través de la red. Es decir, se puede acceder a él de manera remota desde otra máquina que tenga conectividad con la máquina que aloja el servicio.
El término API sirve para identificar una serie de servicios web disponibles y relacionados entre sí. Ejemplos son Google Maps, ebay, Amazon, etc.
¡Reutilización de código!
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Por lo tanto una API representa un catálogo de métodos públicos que podemos utilizar desde nuestras aplicaciones.
Quiero desarrollar una web de "música" que presente información extraída de diversas APIs que me proporcionan información para tal propósito:
http://www.lastfm.es/api
http://www.lastfm.es/api/rest
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Las dos maneras fundamentales de implementar servicios web independientemente de la tecnología son:
- SOAP: forma tradicional. Basada en ficheros XML. Más lento parseo entre el cliente/servidor. Mayor complejidad
- REST: basado en las APIs Restful. Método más sencillo que aprovecha la potencia del objeto HTTP. Basado en JSON.
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
SOAP es un protocolo estándar que define cómo diferentes procesos pueden comunicarse por medio de
intercambio de datos XML.
Un mensaje SOAP es un documento XML ordinario con una estructura definida en la especificación del protocolo.
Al utilizar XML el parseo es más costoso y la comunicación entre cliente y servidor más lenta.
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Veamos un ejemplo de cómo crear servicios Web SOAP en Spring. Para ello, descárgate el proyecto y carga complete:
https://github.com/spring-guides/gs-producing-web-service.git
- Dependencias (org.springframework.boot y wsdl4j)
- Esquema XSD, en src/main/resources, que va a definir el tipo de datos de nuestras peticiones y respuestas
- Maven generate-sources ...
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
El XSD de countries define objetos con sus atributos del WS:
<xs:element name="getCountryRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Las peticiones (request) que consistirán en un objeto con un atributo nombre de tipo String.
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
La response devuelve un Country, que es un objeto complejo:
<xs:element name="getCountryResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="country" type="tns:country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="country">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="population" type="xs:int"/>
<xs:element name="capital" type="xs:string"/>
<xs:element name="currency" type="tns:currency"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="currency">
<xs:restriction base="xs:string">
<xs:enumeration value="GBP"/>
<xs:enumeration value="EUR"/>
<xs:enumeration value="PLN"/>
</xs:restriction>
</xs:simpleType>
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Dentro del pom.xml:
Genera unas clases Java a partir de los XSD (En nuestro caso src/main/resources/countries.xsd)
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Desde el proyecto: Run As -> Maven generate-sources
Se generan las anteriores clases...
Varios countries para enviar la respuesta (datos consulta)
Define el servicio web
Lanza el servicio
Genera el WSDL que es el descriptor del WS
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Clase endpoint (define el servicio web):
@Endpoint
public class CountryEndpoint {
private static final String NAMESPACE_URI =
"http://spring.io/guides/gs-producing-web-service";
private CountryRepository countryRepository;
@Autowired
public CountryEndpoint(CountryRepository countryRepository) {
this.countryRepository = countryRepository;
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
@ResponsePayload
public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
GetCountryResponse response = new GetCountryResponse();
response.setCountry(countryRepository.findCountry(request.getName()));
return response;
}
}
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
La clase Endpoint posee el método getCountry, que es el servicio web propiamente dicho.
Recibe un objeto GetCountryRequest y retorna un GetCountryResponse.
Es decir, genera una respuesta a partir del parámetro name de la petición: se busca en el repositorio el país que recibido y se establece la respuesta como retorno del servicio.
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Sobre la clase WebServiceConfig que contiene la configuración, genera el WSDL y que se lanza finalmente...
Esta configuración genera como resultado un fichero WSDL: sirve para describir nuestro servicio web para que los clientes lo puedan consultar y ver así cómo deben generar las peticiones y qué tipo de respuestas pueden esperar.
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
La siguiente dependencia en el pom.xml descarga un Tomcat empotrado para servir el servicio web:
Para cambiar el puerto 8080 por defecto, en src/main/resources genero un application.properties con una entrada: server.port = 8888
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-ws</artifactId>
</dependency>
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Finalmente se arranca la clase Application.java (Run As -> Java Application)
Y se puede visualizar la especificación del WSDL
Desde el navegador: http://localhost:8080/ws/countries.wsdl
Si cambio el puerto: http://localhost:8888/ws/countries.wsdl
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Especificación del WSDL
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
¡¡Ahora sólo nos queda probarlo!!
No obstante, esto es un poco más complicado, ya que debemos componer un mensaje SOAP, y eso requiere de un formato XML de acuerdo a nuestro XSD.
Existen clientes que nos facilitan la tarea. Uno de ellos es SOAPUI (versión gratuita):
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
- Generamos la petición a través de SOAPUI:
- Ejecutamos
- En Projects -> New SOAP Project
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
Se genera el esqueleto del mensaje a enviar y relleno los valores:
En CountriesRepository tendría la información a ser retornada por el servicio
Request
Response
UNIDAD 11: servicios web
eugeniaperez.es
11.1 Spring y Soap
La configuración tanto de los servicios como de los clientes con SOAP es mucho más compleja.
La transmisión de la información al ser en XML es más lenta y su parseo en el cliente más costosa.
Era el método tradicional anteriormente a REST, dado que antes se tendía a trabajar con XMLs.
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Rest (Representational State Transfer) se refiere a una colección de principios para el diseño de arquitecturas web.
Rest NO es un estándar, solo un estilo de arquitectura basado en estándares:
- HTTP
- URL
- Representación de recursos: XML/HTML/GIF/JPEG, etc
- Tipos MIME: text/xml, text/html, etc
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Lo mejor para captar la idea de lo que supone REST es ver la anatomía de una RESTful url.
Las URLs son nominales y no verbales, y representan un recurso:
Sobre esto se realizarían variaciones en función de si es inserción, actualización, borrado, etc. En contraposición a las peticiones tradicionales (sin un fw MVC):
http://www.miapp.net/cliente/42
http://www.miapp.net/cliente.php?id=45&ac=delete
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Se permite utilizar toda la potencia que nos ofrecen los distintos métodos HTTP, y no sólo GET y POST, que son los que se han venido usando tradicionalmente:
- GET: para leer datos, (READ)
- PUT: para modificar datos, (UPDATE)
- DELETE: para borrar datos, (DELETE)
- POST: para crear datos, (CREATE)
Esto nos permite realizar un CRUD completo a través del controlador...
unidad 11: servicios web
eugeniaperez.es
Descarga el código en Bitbucket
Descarga el proyecto springmvc.rest del repositorio de Bitbucket:
Usuario:
Psswd:
URL: https://eugenia_perez@bitbucket.org/eugenia_perez/springmvc.rest.git
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Desarrollo del servicio web
Antes de nada, es muy importante incorporar estas dependencias al pom:
- jackson-core
- jackson-databind
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Desarrollo del servicio web
- El controlador será de tipo @RestController
- Se puede unificar el mapeo al comienzo de la clase: @RequestMappping("nombre_controlador")
- Fíjate que en lugar de retornar vistas ahora retorna objetos de nuestro modelo de dominio (y no elementos que son una vista o un ModelView). Estos serán serializados por el framework, por defecto en JSON.
No busco cambiar de
página, sino datos...
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
¡Ya tenemos nuestra API Rest! -> Estas acciones pueden ser llamadas desde cualquier dispositivo con conectividad a nuestra máquina, con la simple ayuda de un cliente que sea capaz de realizar peticiones HTTP.
Por ejemplo, comenzaremos haciendo una petición mediante el navegador. Vamos a hacer una petición GET a la URL:
http://localhost:8080/springmvc/series
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
Recuerda que el API Rest que se ofrece responde a:
SelectAll [GET]:
SelectById [GET]:
Insert [POST]:
Update [PUT]:
Delete [DELETE]:
http://localhost:8080/springmvc/series
http://localhost:8080/springmvc/series/id
http://localhost:8080/springmvc/series
http://localhost:8080/springmvc/series/id
http://localhost:8080/springmvc/series/id
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
¿Qué acción responderá? El método get de nuestro controlador (devuelve todas las películas en BD...):
1) A través del navegador
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
2) A través de un cliente REST del navegador:
Instalo el plugin de Google Advanced REST client.
Lo inicio: http://localhost:8080/springmvc/series
- GET: muestra todas
- POST: inserta una serie {"title":"Fargo","numberOfEpisodes":"100","dateReleased":"2015-02-01","country":"USA"} Cambio content-type a application/json
Se inserta en BD
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
3) A través de una llamada Ajax mediante JQuery:
Mediante el fichero jsClient.html en src/main/webapp/resources.
Crea una fila por cada película retornada y la añade a la table:
$.get('http://localhost:8080/springmvc/series', function(data){
var tableData = $('table tbody');
$.each(data, function(idx, elm){
tableData.append('<tr><td>' + elm.id + '</td><td>' + elm.title + '</td><td>' + elm.dateReleased +
'</td><td>' + elm.numberOfEpisodes + '</td><td>' + elm.country + '</td></tr>')
});
});
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
3) A través de una llamada Ajax mediante JQuery:
Utilizo el método PUT para actualizar el número de episodios de la serie con ID 1:
$('#updateSeries').on('click', function(){
$.ajax({
url: "http://localhost:8080/springmvc/series/1",
type: "PUT",
data: JSON.stringify({
"id" : 1,
"title" : "Better call Saul",
"numberOfEpisodes" : "100",
"dateReleased" : "2015-02-01",
"country":"USA"
}),
contentType: "application/json"
}).done(function(response){
alert(response);
});
});
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
3) A través de una llamada Ajax mediante JQuery:
Para ejecutarlo:
http://localhost:8080/springmvc/resources/jsClient.html
UNIDAD 11: servicios web
eugeniaperez.es
11.2 Spring y Rest
Consumo del servicio web desde cliente
4) Consumo desde otras aplicaciones, como una aplicación en Java.
Aunque el escenario más común de los servicios web REST es nutrir de datos a código Javascript que corre en el cliente, estos están disponibles a cualquiera otra tecnología servidor que los invoque.
Nos descargamos el proyecto a continuación.
unidad 11: Servicios web
eugeniaperez.es
Descarga el código en Bitbucket
Descarga el proyecto restclient del repositorio de Bitbucket:
Usuario:
Psswd:
URL: https://eugenia_perez@bitbucket.org/eugenia_perez/restclient.git
Unit 11
By eugenia_perez
Unit 11
- 1,235