openxava
/ documentación /
Lección 22: Llamada REST desde una validación
Curso:
1.
Primeros pasos |
2.
Modelo básico del dominio (1) |
3.
Modelo básico del dominio (2) |
4.
Refinar la interfaz de usuario |
5.
Desarrollo ágil |
6.
Herencia de superclases mapedas |
7.
Herencia de entidades |
8.
Herencia de vistas |
9.
Propiedades Java |
10.
Propiedades calculadas |
11.
@DefaultValueCalculator en colecciones |
12.
@Calculation y totales de colección |
13.
@DefaultValueCalculator desde archivo |
14.
Evolución del esquema manual |
15.
Cálculo de valor por defecto multiusuario |
16.
Sincronizar propiedades persistentes y calculadas |
17. Lógica desde la base de datos
|
18.
Validando con @EntityValidator |
19.
Alternativas de validación |
20.
Validación al borrar |
21. Anotación Bean Validation propia |
22: Llamada REST desde
una validación |
23.
Atributos en anotaciones |
24.
Refinar el comportamiento predefinido |
25.
Comportamiento y lógica de negocio |
26.
Referencias y colecciones |
A.
Arquitectura y filosofía |
B.
Java Persistence API |
C.
Anotaciones |
D.
Pruebas automáticas
En la lección anterior vistes como crear una anotación Bean Validation
propia. En esta leccion verás como se llama a un servicio web REST para
validar el ISBN.
Si no te gustan los videos sigue las instrucciones a continuación.
Llamar
a un servicio web REST para validar el ISBN
Aunque la mayoría de los validadores tienen una lógica simple, puedes
crear validadores con una lógica compleja si lo necesitas. Por ejemplo, en
el caso de nuestro ISBN, queremos, no sólo verificar el formato correcto,
sino también comprobar que existe de verdad un libro con ese ISBN. Una
forma de hacer esto es usando servicios web.
Como seguramente ya sepas, un servicio web es una funcionalidad que reside
en un servidor web y que tú puedes llamar desde tu programa. La forma
tradicional de desarrollar servicios web es mediante los estándares WS-*,
como SOAP, UDDI, etc. Aunque, hoy en día, la forma más simple de
desarrollar servicios es REST. REST consiste básicamente en usar la ya
existente “forma de trabajar” de internet para comunicación entre
programas. Llamar a un servicio REST consiste en usar una URL web
convencional para obtener un recurso de un servidor web. Este recurso
usualmente contiene datos en formato XML, HTML, JSON, etc. En otras
palabras, los programas usan internet de la misma manera que lo hacen los
usuarios con sus navegadores.
Hay bastantes sitio con servicios web SOAP y REST para consultar el ISBN
de un libro, vamos a usar
openlibrary.org
que proporciona una API REST gratuita para consultar su catálogo de
libros. Para probar la API de Open Library abre un navegador y ve a la
siguiente URL:
Donde el último parámetro es el
ISBN del libro, a partir del cual obtenemos un JSON con los datos del
libro, algo como esto:
Un JSON es simplemente data con
clave/valor que usa {} y [] para anidar y repetir. Si intentas obtener
los datos de un libro inexistente, como en esta URL:
Obtienes un JSON vacío, como
este:
Es decir, un JSON vacío,
simplemente unas llaves vacías, así: {}.
Para llamar a este servicio web
usaremos JAX-RS. JAX-RS es el estándar Java para llamar a servicios web
REST. OpenXava incluye soporte para llamar a servicios web usando
JAX-RS, por lo que no necesitas añadir ninguna librería adicional.
Modifiquemos
ValidadorISBN para usar este servicio
REST.
Veamos el resultado:
package com.tuempresa.facturacion.validadores;
import javax.validation.*;
import javax.ws.rs.client.*; // Para usar JAX-RS
import com.tuempresa.facturacion.anotaciones.*;
import org.apache.commons.logging.*; // Para usar Log
import org.openxava.util.*;
public class ValidadorISBN
implements ConstraintValidator<ISBN, Object> {
private static Log log = LogFactory.getLog(ValidadorISBN.class); // Instancia 'log'
private static org.apache.commons.validator.routines.ISBNValidator
validador =
new org.apache.commons.validator.routines.ISBNValidator();
public void initialize(ISBN isbn) {
}
public boolean isValid(Object valor, ConstraintValidatorContext contexto) {
if (Is.empty(valor)) return true;
if (!validador.isValid(valor.toString())) return false;
return existeISBN(valor); // Aquí hacemos la llamada REST
}
private boolean existeISBN(Object isbn) {
try {
// Aquí usamos JAX-RS para llamar al servicio REST
String respuesta = ClientBuilder.newClient()
.target("http://openlibrary.org/") // El sitio
.path("/api/books") // La ruta del servicio
.queryParam("jscmd", "data") // Los parámetros
.queryParam("format", "json")
.queryParam("bibkeys", "ISBN:" + isbn) // El ISBN es un parámetro
.request()
.get(String.class); // Una cadena con el JSON
return !respuesta.equals("{}"); // ¿Está el JSON vacío? Suficiente para nuestro caso
}
catch (Exception ex) {
log.warn("Imposible conectar a openlibrary.org " +
"para validar el ISBN. Validación fallida", ex);
return false; // Si hay errores asumimos que la validación falla
}
}
}
Simplemente abrimos la URL con el ISBN como parámetro de la petición. Si
el JSON resultante es un JSON vacío, es decir {}, la búsqueda ha fallado,
en caso contrario hemos encontrado el libro. Para nuestro caso, obtener el
JSON como una cadena para poder hacer una comparación simple es el camino
más corto, sin embargo JAX-RS permite convertir el JSON en un objeto Java
de tu propia clase (
Libro por ejemplo) rellenando las propiedades
correspondientes, sólo has de usar
.get(Libro.class) en lugar de
.get(String.class)
como última línea de la llamada.