blog de ezamudio

Transformación de clases al vuelo con Javassist

En esta ocasión quiero describir un proceso un tanto complicado, que puede servirle a alguien tal vez, si se encuentran en la necesidad de hacer algo locochón como lo que tuve que hacer yo.

En términos generales, me encontré en la necesidad de agregar anotaciones a clases, en tiempo de ejecución. Es decir, una clase que no tiene ciertas anotaciones, porque no fue compilada así, necesita que se las agreguemos a la hora de correr una aplicación. Esto fue posible gracias a Javassist, una biblioteca de software libre que sirve precisamente para transformar clases en tiempo de ejecución, pero aún así el código y la manera de hacerlo es algo complejo.

Primero que nada, necesitamos el JAR donde se encuentra la clase que queremos modificar. Dependiendo del tipo de aplicación, la manera de obtener el JAR va a variar, pero lo importante aquí es que tengamos al final un InputStream del cual vamos a leer la clase. Una vez que tenemos el InputStream, debemos ir leyendo del JAR hasta obtener el archivo que queremos (un .class).

Actualizando de Spring 2.5 a 3.0

Recientemente actualicé una aplicación que utiliza Spring 2.5, para que utilice Spring 3.0 y quiero compartir algunos detalles de esta experiencia. No quiero decir que esta es la manera de actualizar pero pues espero le sirva a alguien y si hay mejores maneras también las puedan poner aquí como comentarios.

Primero que nada, quiero mencionar que los proyectos que actualicé no utilizan Maven ni Ivy ni nada por el estilo; de ahí la complejidad y la mención en mi blog; si fuera con Maven sería más sencillo y no habría tanto problema.

El primer cambio que noté con Spring 3.0 es que ya no existe un JAR grande (como era spring-2.5.6.jar por ejemplo) sino que ahora hay varios JARs, uno por módulo, y la nomenclatura se complicó un poco, por ejemplo org.springframework.core-3.0.0.RELEASE.jar.

Introducción a SLF4J

Escribo esto porque hace poco hice unas pruebas para comparar el performance de SLF4J contra Jakarta Commons Logging.

Llevaba ya tiempo usando JCL, un framework para logging que tiene la ventaja de ser una capa de abstracción sobre otros frameworks; es decir, se puede programar usando el API de JCL y en deployment se utiliza Log4J por ejemplo para hacer realmente el trabajo de los logs, o bien usar java.util.logging sin tener que cambiar una sola línea de código (JCL auto-detecta Log4J y si no está, se usa java.util.logging). Se pueden hacer interfaces para usar otros frameworks de logging.

SLF4J (Simple Logging Framework for Java) es muy similar: es simplemente una API que en tiempo de ejecución se apoya en algún framework de logging como Log4J, java.util.logging, etc. Su arquitectura interna es distinta en la manera que usa el framework real para logging: debe tenerse en el classpath el JAR que define el API junto con una sola implementación de backend, por ejemplo para Log4J.

Tapestry 5, parte 5 - Sesiones, validaciones, AJAX

Una parte importante de cualquier aplicación web seria, es la manera en que se almacenan variables de sesión. Por ejemplo, una aplicación que requiere login y se crea una sesión para el usuario; se requiere validar el usuario/password y cuando es un usuario válido, guardar sus datos en la sesión y las páginas que solamente son para usuarios válidos necesitan redirigir al usuario al login para que solamente usuarios registrados puedan ver la página.

Otro ejemplo es un simple blog como éste, en el que solamente los usuarios registrados pueden dejar comentarios. Vamos ver este ejemplo. Primero, supongamos que ya tenemos la página que muestra el blog y los comentarios, y tenemos un componente para dejar un nuevo comentario pero solamente a los usuarios ya registrados.

Tapestry 5, parte 4 – Integración con Spring

Al principio de esta serie, mencioné que Tapestry trae su propio manejador para inyección de dependencias. Sin embargo, muchos de nosotros ya estamos familiarizados con Spring, y en el caso de integración adicional con Hibernate y cosas así, ya tenemos configuraciones algo complejas en un ApplicationContext y queremos conservarlas. Así que es importante poder usar Spring con Tapestry.

Pues bien, es muy sencillo. Primero que nada, integramos la parte de Spring como en cualquier aplicación web. Suponiendo que tenemos un solo archivo de configuración spring.xml dentro de WEB-INF:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring.xml</param-value>
</context-param>
...
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Tapestry 5, parte 3 - Componentes, inyección, internacionalización

Continuando con la cátedra de Tapestry 5, vamos a ver ahora tres cosas sencillas pero bastante ilustrativas del poder de este framework: cómo funcionan los componentes (unidades funcionales que pueden ir contenidas en páginas o dentro de otros componentes); inyección de objetos en páginas y componentes, y cómo internacionalizar una página o componente.

Los componentes son fragmentos de páginas que van dentro de otros componentes o dentro de páginas. Un ejemplo muy típico es este: queremos dar a nuestro sitio una apariencia uniforme, con hojas de estilos, una serie de ligas en la parte superior, algunos datos de copyright y demás en la parte inferior, etc. Todas las páginas deben salir igual. Esto en Tapestry se resuelve muy fácil con un solo componente que podemos llamar Marco, que además va a tener la peculiaridad de que va a envolver a su componente o página padre:

<!-- Marco.tml -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"

Tapestry 5, parte 2 - Introducción Funcional

Pues bien, después de un largo recorrido histórico por el nacimiento de las herramientas para desarrollo de aplicaciones web, finalmente aquí pongo una introducción a mi framework favorito para web, Tapestry.

Cabe mencionar que voy a enfocarme solamente en la versión 5, que cambió radicalmente de la 3 y la 4. Reescribieron el framework por completo y se perdió toda compatibilidad con versiones anteriores, lo cual puede ser muy problemático para quienes tengan desarrollos en producción en esas versiones, pero para comenzar aplicaciones nuevas, hay muchísimas ventajas. No voy a mencionar las diferencias con versiones anteriores, solamente detallaré las características de esta nueva versión.

Tapestry 5, parte 1 - Introducción Histórica

Este es un primer intento de explicar las diferencias entre Tapestry y JSP. De hecho no solamente con JSP sino con los otros frameworks que son basados en el esquema de JSP. Esta vez voy a empezar con algo de historia, para ponernos en contexto de por qué Tapestry funciona como funciona (aunque tal vez no llegue a esa parte en este post).

En tiempos inmemoriales, a mediados de los 90's, cuando empiezan a popularizarse los web servers, solamente sirven contenido estático. Los primeros contenidos dinámicos fueron por medio de programas llamados CGI's, Common Gateway Interface, que consistía en que el web server le pasaba la URL y datos de la petición HTTP a un programa en UNIX, que lo leía del STDIN, y podía imprimir a STDOUT cualquier salida; ésta era devuelva por el web server al navegador. Esto es muy ineficiente porque cada petición ejecuta un programa y un programa medio complejo puede tardar bastante en ejecutarse, utilizar recursos, etc (por ejemplo cuando el CGI ya hacía conexiones a base de datos, etc).

java.nio y java.io

Veo que no hay prácticamente nada información acerca de este tema en el sitio, así que decidí escribir esto esperando que a alguien le resulte útil.

Desde la versión 1.4 de Java apareció un paquete nuevo, java.nio, similar a java.io; esa n es de non-blocking. Los que hayan usado InputStream y OutputStream para leer por ejemplo de un socket, sabrán que los métodos de lectura y escritura bloquean el thread que los invoca, hasta que terminen su operación. Por lo tanto, en ambientes donde se tienen un alto volumen de intercambio de datos por medio de sockets, normalmente se tiene maneja una cola de mensajes que se deben enviar, junto con un thread dedicado a tomar mensajes de dicha cola y escribirlos al socket; y por otra parte se tiene un thread dedicado a leer del socket continuamente, poniendo en una cola los mensajes que van llegando (ojo: aquí cuando digo "mensajes" me refiero a tramas de datos que llegan por el socket que vienen delimitadas de alguna forma, pero aun sin parsear).

Ejemplo Cross-Site Scripting

El tercer y último ejemplo que vimos en la plática de Seguridad en Aplicaciones Java, fue el de Cross-Site Scripting, conocido por su abreviatura como XSS.

Este ataque puede ser bastante complejo en cuanto al daño que se pueda hacer y los lugares por donde se puede realizar (vectores de ataque). Sin embargo, el fundamento es muy similar al de la inyección de SQL: usar datos que capturan los usuarios, sin validarlos apropiadamente.

La inyección de SQL permite que un usuario malicioso pueda enviar a una aplicación ciertos datos que incluyan sentencias de SQL que se ejecutarán en el servidor de base de datos. Los ataques de XSS usan ese mismo principio pero los datos que se envian, pueden incluir código HTML y/o Javascript; la principal diferencia es que dicho Javascript es inocuo en el servidor pero al ser incluido en páginas que se envían a otros usuarios, sus navegadores posiblemente ejecutarán dicho Javascript.

Distribuir contenido