martes, marzo 24, 2009

Webservices REST en Java con Jetty y Jersey

En este post voy a explicar como hacer una aplicacion Java SE que exponga una API REST tanto JSON como XML.

primero empezamos creando un proyecto comun en netbeans, le ponemos el nombre que se nos ocurra, te recomiendo addressbook asi no tenes que cambiar el codigo :D.

despues tenemos que agregar todos los jars que vamos a usar en el proyecto.

aca doy una lista de las ultimas versiones, pero pueden quedar desactualizadas rapido, asi que fijense si no hay mas nuevas.

Primero que todo necesitamos un servidor web embebido, para ello vamos a usar jetty, el cual bajamos de aca: http://dist.codehaus.org/jetty/ yo baje este http://dist.codehaus.org/jetty/jetty-6.1.15/jetty-6.1.15.zip al descomprimir el zip, en la carpeta lib estan los jars que hacen falta

Tambien necesitamos una libraria para poder exponer nuestros webservices REST, para ello vamos a usar jersey, yo baje el bundle (contiene todos los jars adentro que requiere) de aca http://download.java.net/maven/2/com/sun/jersey/jersey-bundle/, particularmente yo baje la version 1.0.2 de aca http://download.java.net/maven/2/com/sun/jersey/jersey-bundle/1.0.2/jersey-bundle-1.0.2.jar

el jar asm lo podemos descargar de aca http://maven.objectweb.org/maven2/asm/asm/ yo baje la version 3.1 de aca http://maven.objectweb.org/maven2/asm/asm/3.1/asm-3.1.jar

el jar jsr311 se encuentra en http://download.java.net/maven/2/javax/ws/rs/jsr311-api/ yo baje http://download.java.net/maven/2/javax/ws/rs/jsr311-api/1.0/jsr311-api-1.0.jar

Para empezar agregamos los siguientes jar al proyecto:

jersey-bundle-1.0.2.jar
jetty-util-6.1.15.jar
servlet-api-2.5-20081211.jar
jetty-6.1.15.jar
jsr311-api-1.0.jar
asm-3.1.jar

Creamos un archivo main con el siguiente contenido

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package addressbook;

import com.sun.jersey.spi.container.servlet.ServletContainer;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.handler.DefaultHandler;
import org.mortbay.jetty.handler.HandlerList;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;

/**
*
* @author mariano
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception{
org.mortbay.jetty.Server server;
ServletHolder holder;
Context contextWS;

holder = new ServletHolder(ServletContainer.class);

holder.setInitParameter("com.sun.jersey.config.property.packages",
"addressbook.ws");

server = new org.mortbay.jetty.Server(9999);

contextWS = new Context(server, "/ws", Context.SESSIONS);
contextWS.addServlet(holder, "/*");
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { contextWS, new DefaultHandler()});
server.setHandler(handlers);

server.start();
}

}



lo que hace es inicializar el server en el puerto 9999 y pasarle un handler para los requests que estan bajo el path /ws.

la linea

holder.setInitParameter("com.sun.jersey.config.property.packages", "addressbook.ws");


le dice que busque los manejadores de ws en el paquete addressbook.ws, por lo tanto el siguiente paso es crear el paquete addressbook.ws.

Por lo que veran el ejemplo va a ser un libro de direcciones o cosas por el estilo.

despues de crear el paquete creamos una clase adentro que llamamos AddressBook

el contenido es el siguiente:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package addressbook.ws;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;

/**
*
* @author mariano
*/
@Path("book")
public class AddressBook {

@GET
@Path("all")
public static String getAll()
{
return "all";
}

@GET
@Path("search/{type}/{query}")
public static String getAll(@PathParam("type") String type, @PathParam("query") String query)
{
return type + " " + query;
}
}



El codigo es bastante simple, en la clase le decimos cual es el path base de esa clase, y en cada metodo le decimos que tipo de request responde (en lenguaje REST tenemos GET, POST, PUT y DELETE) y tambien podemos especificarle parametros los cuales van entre llaves en @Path y tambien en el metodo debemos anotar cual parametro del path se asigna a que parametro del metodo.

Por ahora los metodos devuelven cosas simples, en otro post voy a mostrar como serializar/descerializar objetos java de/a XML y JSON

si lo corremos y vamos con el browser a http://0.0.0.0:9999/ws/book/all vamos a ver el texto "all", si vamos a http://0.0.0.0:9999/ws/book/search/name/bob vamos a ver "name bob"

3 comentarios:

Diego Sarmentero dijo...

Muy Bueno Marianete!!!
Va a ser de mucha utilidad!

xmariachi dijo...

Gracias por el aporte.
Lo he probado y ha sido muy sencillo. Yo estoy mirando ahora la integración Jersey-Guice para dependency injection.

Respecto a la exportación de JSON, has publicado esa "segunda parte"?

Un saludo!

elsurexiste dijo...

Ahí hice andar friggin' Jersey con WASCE. Si les tira el error "The ResourceConfig instance does not contain any root resource classes", hay que cambiar el nombre de "AdressBook" a "AdressBookResource" y sale como piña.

Seguidores

Archivo del Blog