martes, 13 de septiembre de 2011

Probando RESTful con Poster

Seguimos con RESTful en Java!
Ya luego comentaré qué pasó conmigo y por qué no estuve enviando contenido a mi blog.
Hasta el momento hemos visto casi de manera abstracta el funcionamiento de RESTful usando Jersey desde NetBeans.
Ahora veremos como probar todo un CRUD de RESTful desde un complemento de Firefox llamado Poster.
La mejor manera de probar un servicio es no creando una aplicación. Es decir, si vamos a probar como funciona algo, no tenemos que hacer un programa que utilice ese algo.
El objetivo principal del RESTful es proveer servicios estándar para todo tipo de cliente ¿cierto? Entonces, si hacemos una aplicación que consuma nuestro servicio, corremos el peligro de que ajustemos el servicio para que corra con nuestra aplicación y al final no sea estándar.

Así que, antes de mostrar el RESTful, debemos instalar el complemento Poster en nuestro Firefox (porque asumimos que como buenos programadores, usamos Firefox) Este se puede descargar desde aquí: https://addons.mozilla.org/es-ES/firefox/addon/poster/

Ahora, les comento que he ordenado un poco el proyecto que hemos estado haciendo en los post anteriores. Ahora tiene un EJB que manejará la colección de entidades (como debe ser) y que está separado de la clase de recursos (como debe ser).

Además, el manejo de las peticiones CRUD en un REST son como sigue:

Verbo RESTURIAcción a realizar
POST/personaCreate
GET/persona/idRead
PUT/persona/idUpdate
DELETE/persona/idDelete
Así, el código final del recurso REST es el siguiente:
@Path("/persona")
@Consumes({"application/json", "application/xml"})
@Stateless
public class PersonaService {

    @EJB
    private PersonaFacade facade;

    @POST
    public Response create(Persona p) {
        facade.insert(p);
        return Response.ok(p).build();
    }

    @GET
    @Path("{id}/")
    public Persona read(@PathParam("id") int i) {
        Persona p = facade.findById(i);
        return p;
    }

    @GET
    public List<Persona> read(@QueryParam("nombre")
            @DefaultValue("") String nombre) {
        List<Persona> l = nombre.isEmpty() ? facade.findAll() : facade.findByNombre(nombre);
        return l;
    }

    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") int i) {
        if (facade.delete(i)) {
            return Response.ok().build();
        }
        return Response.status(Response.Status.NOT_FOUND).build();
    }

    @PUT
    @Path("/{id}")
    public Response update(@PathParam("id") int i, Persona p) {
        p.setId(i);
        facade.update(p);
        return Response.ok().build();
    }
}

Y el EJB es el siguiente:
@Stateless
public class PersonaFacade {

    private static List<Persona> lista = new ArrayList<Persona>(); //lista temporal

    public void insert(Persona p) {
        lista.add(p); //agrega a la lista

    }

    public Persona findById(int id) {
        Persona p = new Persona(id); //crea un objeto temporal...
        int i = lista.indexOf(p); //... para buscarlo en la lista
        if (i < 0) {//si no lo encuentra        
            return null; //... devuelve null
        }
        return lista.get(i);  // sino, lo devuelve
    }

    public List<Persona> findAll() {
        return lista;
    }

    public List<Persona> findByNombre(String nombre) {

        List<Persona> $lista = new ArrayList<Persona>(); //un arreglo temporal
        for (Persona persona : lista) {  //se recorre la lista...
            if (persona.getNombre().contains(nombre)) { //se compara el nombre
                $lista.add(persona); //y si es parecido, lo agrega en la lista
            }
        }
        return $lista; //... para devolverlo
    }

    public boolean delete(Persona p) {
        return lista.remove(p);
    }

    public void update(Persona p) {
        int pos = lista.indexOf(p); //busca en la lista..
        if (pos >= 0) { //si lo encuentra...
            lista.set(pos, p); //... lo actualiza            
        }

    }

    public boolean delete(int i) {
        Persona p = findById(i);
        return delete(p);
    }
}

Ejecutando Poster

Ahora bien, una vez instalado el Poster en Firefox, lo abrimos haciendo clic en la barra inferior del navegador en el ícono color amarillo con una letra P. Esto nos abrirá la siguiente ventana:
Es bastante fácil su utilización como lo veremos a continuación.

Ejecutemos el proyecto desde nuestro NetBeans y veremos que se abrirá una ventana de bienvenida (no muy elegante) y un enlace para visualizar la descripción del recurso. Al hacer clic en ese enlace, se mostrará el WADL Podemos examinar por curiosidad para conocer los recursos existentes. Pero en este momento vamos a ver cómo funciona el Poster.

En la casilla URL se deberá poner el URI del servicio completo. Para nuestro ejemplo es http://localhost:8084/PersonasRestful/rest/persona (cambiar el puerto si es necesario)

En la casilla central llamada "Content type" se pondrá el tipo de datos que se manejará en el envío. Le pondremos el valor: application/json

En la caja grande de entrada es el contenido a enviar. Ahí pondremos los datos a enviar.

Create

Para crear un nuevo objeto en la "base de datos" usando el servicio, necesitamos colocar el contenido siguiente:
{
  "nombre":"Ann",
  "fechaNacimiento":"2010-11-12"
}

Luego, hacemos clic en el botón central "POST". El Poster nos mostrará un resultado:


Este resultado es porque se ha puesto que devuelva el objeto que se agregó.
Intentemos agregar más objetos y hacer POST por cada uno de ellos.

Read

Para obtener el listado de todos los objetos registrados en el servicio, nos aseguramos que el URL apunte a URI /rest/persona y hacemos clic en el botón GET. El Poster nos mostrará el siguiente contenido.


Esto me devuelve el listado completo. Pero si solo quiero uno de ellos, y conozco el ID, pondremos en el URI el ID de una persona. Por ejemplo /rest/persona/2 y luego hacemos clic en "GET".


Update

Para actualizar un registro se debe tener lo siguiente: apuntar a un URI incluyendo el ID /rest/persona/2 y en el contenido colocar las propiedades a actualizar. Por ejemplo:
{
  "nombre":"Alfred",
  "fechaNacimiento":"2010-11-12"
}
Y hacemos clic en el botón PUT
Esta petición no nos ha respondido nada, ya que así lo hemos pusimos en el RESTful.
Podemos verificar el contenido haciendo un GET de todos los objetos registrados.

Delete

Igual que el PUT y UPDATE... solo le indicamos el ID en el URI y hacemos clic en "DELETE". Luego verificamos haciendo un GET de todos los objetos registrados y veremos si está o no.

Cambiando el objeto resultado

Como podemos ver, todas las peticiones que hemos hecho (PUT y POST) tienen el formato JSON, pero los resultados a nuestras peticiones tienen formato XML. Bueno, por omisión el Jersey devolverá bajo ese tipo. Pero también permite devolver formato JSON si así lo solicita el cliente POSTER. Para ello vamos a la pestaña "Headers" del Poster y agregamos la siguiente cabecera:
  • Accept: application/json
.. y hacemos clic en "Add/Change"
Y luego, hagamos el GET de todos los objetos para visualizar el contenido.


Recursos

El proyecto utilizado se puede descargar desde aquí:
http://kenai.com/projects/apuntes/downloads/download/CRUDPersonasRest/personas-restful-crud.tar.gz




5 comentarios:

  1. muy agradecido, he llevado un curso de java y he aprendido hacer aplicaciones desktop la forma mas basica, al final, ademas aprendi, hacer un servicio web SOAP para CRUD lo cual me llevo mucho tiempo por que soy nuevo y al inicio no sabia como retornar los valores.
    Con estas clases, todo se hace sencillo, lo felicito y agradezco por compartir sus conocimientos.
    Le comento que yo programo desde hace anios solo con power builder, pero a partir del curso de java que termine hace un par de meses y gracias a Dios pude encontrar esta pagina que ha abierto una luz en mi objetivo.
    cliente --------servicio web rest--------bd
    He leido informacion con respecto a como desarrollar la parte cliente, he encontrado algunas alernativas la que aprendi (swing) y otra que estoy buscando informacion GWT y SmartGWT....
    Tengo una pregunta, es facil consumir el recurso desde GWT o smartGWT...estoy buscando algunos ejemplos y encuentro GWT con llamadas a RPC SOAP, por favor si sabe de aguna teoria de algun ejemplo para consumir desde GWT le agradecere mucho
    Que Dios le bendiga
    atte
    Peter

    ResponderEliminar
  2. Poster lo probé y esta excelente pero existe una extensión para Chorme que es simplemente genial se llama POSTMAN si alguien lo quiere utilizar.

    ResponderEliminar
    Respuestas
    1. Ahora hay mas herramientas para depuracion de REST. A la fecha que publiqué el post (hace casi un año) habían muy pocos.
      Gracias por tu aporte!

      Eliminar
  3. Recomiendo utilizar POSTMAN es una extención para Chrome, la pueden buscar en la Chrome Web Store.

    Es lo que todo RESTafaris debería utilizar.

    ResponderEliminar
    Respuestas
    1. Gracias @Unknown!!

      Este post es desde hace un año y desde entonces han aparecido mucho más plugins. Gracias nuevamente

      Eliminar

Si quieres hacer una pregunta más específica, hazla en los foros que tenemos habilitados en Google Groups


Ah! solo se permiten comentarios de usuarios registrados. Si tienes OpenID, bienvenido! Puedes obtener su OpenID, aquí: http://openid.net/