Visitas: 93  
Tiempo total: 1 días con 15:31:52 hrs  

A continuación describiré lo necesario para poder implementar una API que permita el envió de información entre dispositivos externos y nuestra aplicación web utilizando el formato de intercambio de datos JSON. El principal objetivo es solucionar el problema del envió de imágenes y las estructuras o entidades de la base de datos usadas por Spring MVC.

Spring MVC permite la publicación de los resultados de las consultas de las bases de datos utilizando REST, con esto podemos definir únicamente un método que devuelva una entidad o lista de entidades y ver en el navegador el resultado en formato JSON de una manera bastante fácil.

Envió de imágenes

Una aplicación web permite la carga de imágenes a través de un formulario HTML utilizando la propiedad:

enctype=”multipart/form-data”

En el framework MVC se debe de capturar la imagen con la siguiente instrucción en el método POST, en mi caso:

@RequestParam(value = “imagen”, required = false) MultipartFile imagen

Aquí hacemos la suposición que el formulario tiene el campo con nombre imagen, que es el campo que permite al usuario la carga de la imagen. Con este simple código cargamos y manipulamos la imagen de acuerdo a nuestros requerimientos, pero si necesitamos utilizar una API para un dispositivo externo que nos envié la imagen utilizando JSON surge el problema de que no hay manera de recibir la imagen tipo MultipartFile. Como se soluciona esto?

Existe un modo de codificar las imágenes a texto, con esto únicamente debemos crear un campo en la estructura JSON para recibir la imagen codificada, decodificarla y almacenarla de acuerdo a nuestra implementación. En este ejemplo, utilizare la decodificación Base 64:

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import javax.imageio.ImageIO;
import sun.misc.BASE64Decoder;

public class Lib {

public static BufferedImage decodeToImage(String imageString) {

BufferedImage image = null;
byte[] imageByte;
try {
BASE64Decoder decoder = new BASE64Decoder();
imageByte = decoder.decodeBuffer(imageString);
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
return image;
}

public Image bufferedImagetoImage(BufferedImage bi) {
return Toolkit.getDefaultToolkit().createImage(bi.getSource());
}

}

En el código podemos observar las funciones decodeToImage que permite convertir el texto codificado a tipo BufferedImage, y el segundo método bufferedImagetoImage a tipo Image para una posible implementación del lector.

Puedes ver un ejemplo de cómo es el resultado de la codificación de una imagen a Base64 en la siguiente URL:

http://www.dailycoding.com/Utils/Converter/ImageToBase64.aspx

El código anterior de la clase Java ejemplo es directamente de una de las fuentes de consulta, puedes encontrarla al final de la publicación y es la solución más simple y correcta que encontré después de leer varias posibles soluciones.

Como enviar entidades en JSON hacia mi API

En este caso se está implementando una API, y REST no utiliza sesiones para cada conexión de cada dispositivo, por esta razón si se tiene un sistema que necesite autentificar a usuarios, se deben de utilizar tokens con OAuth 2.0 o bien, tokens implementados por el usuario que permitan ver quién es la persona que está consultando la información y para saber si tiene permisos para gestionarla.

Al utilizar Spring MVC te darás cuenta que para cada tabla de la base de datos que vas a manipular, debes de crear una clase que la represente como entidad. Esto es a través de Hibernate que lo que hace es implementar la base de datos con conceptos orientados a objetos, esto de cierta manera facilita el trabajo de la información pero también agrega ineficiencia en la gestión de la base de datos, afectando las consultas y velocidad del sistema.

Supongamos el siguiente entorno, necesitamos recibir información en JSON de distintas entidades, si la información recibida no tiene el formato correcto debe de retornar un error de sintaxis, si no es así utilizamos la información almacenándola en la clase o entidad correcta de acuerdo a nuestra implementación.

Esto, es posible con el siguiente código:

 

@RequestMapping(method=RequestMethod.POST, produces="application/json")
public @ResponseBody List<Entidad> metodo_post(@RequestBody String json) throws Exception{

Aquí observamos únicamente la definición del método que recibe la información POST de determinada URL, aparte de los parámetros que utilicemos, en este ejemplo esta la cadena JSON, que recibe la información en el siguiente formato:

{
“entidad_1”:

{

“atributo_1″:””,
“atributo_2″:””,
“atributo_3″:””

},

“entidad_2”:

{

“atributo_1″:””,
“atributo_2″:””,
“atributo_3″:””,
“atributo_4″:””,

},

“entidad_3”:

{

“atributo_1″:””

}

}
Para almacenar cada entidad en la clase Java indicada, con el siguiente método:

ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(json);
Entidad entidad_1;
try{
entidad_1 = mapper.readValue(node.get("entidad_1"), Entidad.class);
}catch(Exception e){
return null;
}

En este caso la clase leída es entidad_1, y para leer la siguiente:

Entidad_2 entidad_2;
try{
entidad_2 = mapper.readValue(node.get("entidad_2"), Entidad_2.class);
}catch(Exception e){

}

En este caso no importa si el dispositivo envía mas entidades en la estructura JSON, en nuestra aplicación leemos las entidades que vamos a utilizar y establecemos que hacer al momento de encontrar un error en su lectura. Este código puede servir para leer el token generado en dado caso nosotros implementemos dicho sistema, y permitir las demás acciones solo si el token enviado y el usuario propietario es el correcto para determinada acción.

En esta publicación, la API utilizaba únicamente información básica, es decir envió de información en texto e imágenes, razón por la cual mi código no fue más del código mostrado aquí. Puedo mencionar también el envió de parámetros por la URL, que por problemas de compatibilidad entre navegadores y sus distintos tipos de interpretación, se limito a datos tipo entero, para evitar problemas con acentos y demás caracteres propios del español:

Para una URL:
@RequestMapping(value=”/direccion/{id}”)

Se recibe el entero id de la siguiente manera en el método POST:
@PathVariable(value=”id”) int id

Como puedo probar mi API?

Hasta ahora he mostrado el código para crear una API para usuarios de dispositivos externos, pero se debe de comprobar el correcto funcionamiento de cada funcionalidad publicada, para esto usamos la aplicación JAVA RESTClient de WizTools.org que permite probar las direcciones REST enviando la información en formato JSON vía POST, permite también muchos más tipos de formato y envíos de información.

Descarga esta aplicación en el siguiente enlace:

http://code.fosshub.com/WizToolsorg-RESTClient/downloads

En mi caso, el .jar que utilice es:

restclient-ui-3.3.1-jar-with-dependencies.jar

Referencias

[http://stackoverflow.com/questions/254184/filter-extensions-in-html-form-upload]
[http://es.wikipedia.org/wiki/JSON]
[http://oauth.net/2/]
[http://es.wikipedia.org/wiki/Hibernate]
[http://www.dailycoding.com/Utils/Converter/ImageToBase64.aspx]
[http://code.fosshub.com/WizToolsorg-RESTClient/downloads]
[http://stackoverflow.com/questions/16235361/how-to-read-base64-encode-image-file-remotely]
[http://itjbg.wordpress.com/2012/06/29/convert-bufferedimage-to-image-in-java/]