29 dic 2008

Tapestry corriendo en Jetty embebido

Hace unos dias que estoy realizando algunas pruebas para correr una aplicacion Tapestry 5 en Jetty 6 embebido, y me he encontrado con ciertas dificultades, principalmente con la clase que utiliza Tapestry 5 para realizar el log de sus operaciones, mas precisamente slf4j. 

Hacia un tiempo que no trabajaba con tecnologías web con Java, y el volver me costo un poco, principalmente por los grandes cambios que fuerón realizados en Tapestry 5 (yo venía trabajando con la versión 3 y la 4 recién estaba por salir). Hoy en día la versión 5 de Tapestry ya es estable y me alegra mucho por el crecimiento que ha tenido. Muchas cosas han cambiado, ya no se necesitan archivos de configuración o de enlace entre java y la página web (aunque me gustaban esos archivos, o ya me había acostumbrado a ellos, no lo se).

Bueno, mejor vuelvo al post para poder dejar plasmado en algún lugar el problema principal que tuve al intentar lanzar Tapestry desde una aplicación Java (por medio de embeber Jetty 6 en la aplicación).

No fué un problema encontrar la forma de correr jetty embebido, simplemente tuve que mirar los ejemplos que hay por internet. Aquí pongo el código que utlice para este fin:

 

public static void main(String[] args) {
 Server server = new Server(81); 
    Context root = new Context(server,"/tapestry",Context.SESSIONS); 
    WebAppContext webContext = new WebAppContext(); 
    webContext.setWar("src/main/webapp"); 
    server.setHandler(webContext); 
    try { 
     server.start(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
}

Explicare rapidamente que es lo que hace dicho código:
1. Crea un servidor que recibirá los pedidos en el puerto 80 de la computadora en la cual se esta corriendo.
2. Crea un contexto en el cual los pedidos serán recibidos en http://<url del servidor>/tapestry
3. Indica donde ir a buscar la aplicación web (en este caso en src/main/webapp)
4. Inicia el servidor

Como verán no detalló demasiado sobre esto porque hay muchos ejemplos en Internet, y sería simplemente copiar lo que por allí anda.

Hasta ahora todo bien, y el problema?

El problema se presentó cuando intente usar el componente beaneditform de Tapestry 5, el mismo comenzó a lanzar un error que había una excepción no capturada que correspondía a que la clase slf4j ya había sido inicializada. Esto no me permitía usar el componente ese, ni otros componentes como el form.

 

La solución?

Sencilla, ahora que busque bastante por internet, agregar el siguiente parámetro a la VM:
-Dorg.mortbay.jetty.webapp.parentLoaderPriority=true

Con ese sencillo parámetro se solucionan todos los problemas.

Me costo ubicar la solución porque, aparentemente, no hay muchas personas que esten utilizando Tapestry con Jetty embebido. Por suerte para mi este mismo inconveniente se presentaba con el Jetty Launcher de Eclipse (y la solución es la misma).

Otra consideración

En la carpeta WEB-INF/lib debe aparecer la siguiente librería:
+ slf4j-api-1.5.2.jar

Sino Tapestry no encontrará las clases necesarias para poder realizar el log y lanzará la tan común excepción: ClassNotFoundException

 

Conclusión

Siempre que comenzamos con algo que no esta tan difundido nos encontramos con algunas dificultades que se hacen un poco más dificiles de resolver que cuando el camino ya esta mucho más transitado. Pero siempre alguién tiene que hacer las pruebas y ver como le va, sino nunca terminamos avanzando. Seguiré probando con Tapestry y posiblemente con otros frameworks web, embebiendolos en Jetty.

Para seguir leyendo sobre Tapestry y Jetty aquí dejo un enlace para buscar mas información en Google