Andrés Testi Hispano

Saturday, October 21, 2006

JBoss AS 4.0.5 Liberado

Ha sido liberada la versión 4.0.5 del JBoss Application Server, que certifica la implementación de EJB3 al 100%, disponiendo de Hibernate 3.2 (liberado hace sólo una semana) como proveedor de persistencia nativo. Vale decir que hasta ahora, GlassFish era el único servidor de aplicaciones que soportaba EJB3 de manera completa. El sitio de descarga ofrece la posibilidad de realizar una instalación mediante Java Web Start, algo que nos ahorra un considerable trabajo de configuración.

Tuesday, October 10, 2006

Framework PRADO libera versión 3.0.4

Cuando se habla de PHP, se piensa en la programación estructurada, en el código espaguetti, en la falta de convención de nombres, en la baja escalabilidad, y en todos los malos vicios achacables al desarrollo de software amateur. Sin embargo, a partir de PHP 5 la cosa empieza a cambiar, porque han nacido proyectos que ya pasan de ser simples librerías como PEAR o JPgraph, a ser verdaderos frameworks. Tal es el caso de Cake (inspirado en Ruby On Rails), Mojavi (un MVC parecido a Struts), Symfony , BlueShoes, PRADO, y otros tantos. Desde mi punto de vista, PRADO es el más interesante de todos, porque plantea una solución moderna, se basa en el concepto de aplicación (lo contrario de páginas independientes), es totalmente orientado a eventos y a componentes, es fácil de aprender, y tiene una excelente documentación. Según sus creadores, está inspirado en Tapestry, Delphi y Visual Basic. La idea central es que cada página tiene un ciclo de vida y un estado. La manera de implementar una página es mediante un template y una clase asociada (al estilo de Tapestry). Cada página es un componente que a su vez puede estar compuesto por otros componentes. Los componentes tienen una manera de "renderizarse" y pueden responder a eventos. Esta forma de trabajar hace que las aplicaciones sean súmamente reutilizables y que incluso, nos podamos dedicar a desarrollar componentes separados, como podría ser una barra de menúes, y luego embeberlos en cada aplicación en la que los necesitemos. En el foro hay un repositorio de componentes en el que los aficionados suben sus propios desarrollos.
A partir de la versión 3, el framework añade uso transparente de AJAX en los denominados Active Controls cuyo nombre e idea fueron sugeridas por mí en su foro, aunque jamás incluyeron fui mencionado en su documentación. De todos modos no les guardo rencor, aunque nunca más pienso postear nada en su foro ( que se consigan sus propias ideas, je! ).
Hace unos días anunciaron la release 3.0.4 del producto, que es la que ocupa el título de esta nota.
Como detalle interesante, puedo mencionar que unos años antes de PRADO apareció BIF, un framework de concepto y apariencia muy similares a PRADO. Este framework fue desarrollado por Nicolás Cesar, un muchacho de Santa Fe. Lamentablemente no llegó a ser muy popular, pero podríamos considerar que fue pionero en el concepto.

Annotation Processing en JDK6 - Propuesta Final

En mi primer post tengo el agrado de comunicarles que fue recientemente liberada la proposición final de la especificación del Pluggable Annotation Processing. Para quienes jamás oyeron hablar de esta funcionalidad del JDK, voy a hacer un breve resúmen. Resulta que es posible hacer un preprocesamiento de annotations en tiempo de compilación, es decir, algo parecido a lo que hacemos con las macross de C, pero en una manera súmamente typesafe. Esta característica, nos brinda la posibilidad de generar clases auxiliares que luego serán utilizadas en tiempo de ejecución, a la vez que también nos permite realizar chequeos de consistencia sobre las annotations y lanzar warnings y/o errores de compilación. Con este nuevo artilugio, java podría posicionarse en el top de la metaprogramación, incluso por encima de lenguajes que hoy son venerados por los autodenominados programadores pragmáticos, como pueden ser Ruby y Python (es una pena que estos dos buenos lenguajes de script hayan engendrado toda esta generación de trolls).
La historia nos dice que el concepto de preprocesamiento en java comenzó con la misma aparición de las annotations, es decir en el JDK5, por medio del API denominado Annotation Processing Tool o APT (nombre muy mal elegido porque se presta a confusiones con el famoso comando Debian). Este API consiste en una serie de clases que nos permiten registrar "listeners" de procesamiento y, por medio del patrón Visitor (muy utilizado en los procesadores de XML), recorrer las declaraciones asociadas a cada annotation que queremos procesar. Las declaraciones nos llegan en la forma de metadatos, pero al ser estas analizadas en tiempo de compilación, no se utiliza la API Reflection, porque la misma supone la existencia de un entorno de ejecución. En cambio se utilizan unos objetos denominados Declarations, que representan declaraciones "textuales". Una vez que se tienen implementados y compilados estos procesadores, se utiliza el comando apt que preprocesa las clases objetivo con los procesadores de annotation que implementamos anteriormente. Hasta aquí he comentado lo que ocurre con APT en el JDK5, sin embargo en la documentación pertinente, SUN nos aconseja no encariñarnos con la actual especificación porque está sujeta a cambios. Y aquí es en donde entra en acción el JDK6, mejor conocido como Mustang. Por suerte, nuestros amigos se dieron cuenta de que no tenia sentido tener el comando apt por un lado y el javac por otro, y decidieron fundirlos en un único comando javac. Además, reordenaron el API que anteriormente se encontraba dentro de un paquete propietario, de los nunca bien ponderados com.sun, y lo introdujeron dentro de un subpaquete del javax. Con ésta nueva especificación, para registrar un procesador de annotations, simplemente debemos incluir una implementación de la clase AbstractProcessor dentro del classpath que utilizamos para compilar.
Para que mi explicación sea un poco más concreta, les muestro cómo se vería un procesador de annotations en JDK6:

import javax.annotation.processing.*;
import static  javax.lang.model.SourceVersion.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import java.util.Set;


// Indicamos que annotation queremos preprocesar.
// El '*' significa 'todas', como no podia ser de otra manera
@SupportedAnnotationTypes("*")

// Que version del JDK utilizamos?
@SupportedSourceVersion(RELEASE_6)

// Implementamos un nuevo procesador de annotations
public class HelloWorldProcessor extends AbstractProcessor {

// Este metodo es invocado cuando el compilador esta procesando
// una declaracion. RoundEnvironment contiene los metadatos asociados
// a la declaracion, ademas de un gestor de mensajes que nos permite
// emitir warnings y/o errores de compilacion
public boolean process(Set annotations,
RoundEnvironment roundEnv) {
if (!roundEnv.processingOver()){
// hacemos que el compilador imprima un mensaje
processingEnv.getMessager().printNotice("Procesando una annotation");
}
return false;
}
}


El código anterior no tiene intenciones de abarcar el tema en profundidad, pero sirve para tener una idea de lo que estamos hablando.
Para variar, el concepto del preprocesamiento me parece fantástico, pero para mi gusto el API deja bastante que desear, sobre todo porque sólo permite evaluar declaraciones, y no expresiones o secuencias de código, que son los lugares en los que realmente sería útil.
Reconozco que sé poco del tema, pero creo que ésta capacidad permitiría extender el lenguaje de maneras nunca antes vistas. Por ejemplo, se podrían diseñar verdaderos frameworks de AOP autocontenidos, sin la necesidad de utilizar contenedores externos como el JBoss ni precompiladores como el AspectJ.
Sólo espero que perfeccionen el API para el JDK7, porque aún lo veo muy verde.

Más información:

- JSR-000269
- Blog del encargado del API
- Javadoc
- Minitutorial de APT en JDK5

Propuesta para Consultas Implícitas en EJB3

Al trabajar con tecnología ORM, normalmente se sugiere dividir la lógica de negocios en dos componentes arquitectónicos. Por un lado tenemos la capa de persistencia, que agrupa a los objetos que son representados por entidades en la base de datos. Estos objetos, en principio, sirven como contenedores de información, pero tienen poca funcionalidad asociada, ya que no tienen acceso directo al API de consultas. Para realizar las consultas y el movimiento de la lógica de negocios, exíste la capa de DAO (Data Access Object), que se encarga de gestionar las transacciones, consultas, inserciones, actualizaciones, etc.. Generalmente, se sugiere que exista un DAO por cada clase persistente del modelo. El DAO puede visualizar la capa de persistencia, pero la capa de persistencia no está enterada de la existencia del DAO. Hasta aquí, no pareciera complicarse el trabajo con esta arquitectura. El problema surge con los objetos que tienen relaciones mandatorias sobre otros objetos, es decir, los objetos que mantienen relaciones de padres e hijos (en el sentido de la navegación, no de la herencia). Si tengo que actualizar un objeto hijo ¿Utilizo el DAO asociado al padre, o el DAO asociado al hijo? ¿Y si borro un objeto padre que debe borrar en cascada a sus hijos? ¿Primero invoco el DAO del hijo para borrar a cada instancia por separado?. La respuesta no es simple ni única, pero pareciera coherente, centralizar la mayor cantidad posible de lógica en la capa de persistencia, para aliviar a la capa de DAO y así minimizar las inconsistencias generadas por este patrón de diseño. En este sentido, EJB3 nos ha brindado algunas soluciones, de la mano de los denominados Entity Listeners. Los Entity Listeners nos permiten acceder de manera ortogonal al ciclo de vida de las entidades (CRUD), de una manera centralizada, quitando muchas responsabilidades de la capa de DAO. Por otro lado, la API de Hibernate Validator, también contribuye en este sentido, al agregar capacidades de validación al modelo persistente. Por último, la lógica de consultas que realiza el DAO, se ve también alivianada por las relaciones de las Entidades, que hacen consultas de manera transparente para descongelar los objetos relacionados con el objeto de interés. Pero hasta el momento, sólo existe esa única contribución al mundo de las consultas transparentes, no hay nada más que lo inherente a las relaciones. Todo el tiempo se nos presentan problemas. Por ejemplo, si el sueldo de un vendedor se calcula sumando el total de las comisiones de sus ventas, debemos realizar una consulta explícita. Para colaborar con la centralización de responsabilidades, podríamos definir la consulta dentro de un Named Query asociado a la clase Vendedor. De todos modos, la única capa de la arquitectura con la responsabilidad y capacidad de ejecutar esa consulta es el DAO:

@Entity
@NamedQuery(
name=”Vendedor.calcularSueldo”,
query=

SELECT SUM(venta.comision) “ +
FROM Vendedor v JOIN v.ventas venta ” +
WHERE v = :vendedor “
)

public class Empleado{
....
@OneToMany(fetch=LAZY, cascade={ALL}, mappedBy=”vendedor”)
private List ventas;
.....
}

public class Venta{
.....
@ManyToOne(fetch=LAZY, optional=false)
@JoinColumn(name=”VENDEDOR_ID”)
private Vendedor vendedor;

private Integer comision;
....
}

@Stateless
public class DaoVendedorBean implements DaoVendedorLocal{

@PersistenceContext
private EntityManager em;

public Long calcularSueldo(Vendedor v){
return (Long)em.createNamedQuery(“Vendedor.calcularSueldo”)
.setParameter(“vendedor”, v)
.getSingleResult();
}

}

Aquí algo parece no estar funcionando del todo bien. Supuestamente, los objetos en OOP tienen métodos propios que nos informan de su estado ¿Por qué debe ser otro objeto el que nos informe del sueldo del vendedor? Podríamos entonces, pensar en un nuevo tipo de inyección denominado Implicit Query. Supongamos que contamos con la siguiente annotation:

@Retention(RUNTIME)
@Target(METHOD)
public @interface ImplicitQuery{

String value();
String parameter() default “this”;
FetchType fetch() default EAGER;

}


En donde

value: es el nombre de alguna NamedQuery de la entidad.
parameter: es el nombre del único parametro por el que se inyecta la entidad analizada. Por default es “this”
fetch: determina en qué momento se realiza la consulta.

Entonces podríamos agregar el siguiente campo en la clase vendedor:

@ImplicitQuery(
name=”Vendedor.calcularSaldo”,
parameter=”vendedor”
)

private Long saldo;

De esta manera podríamos eliminar el método calcularSueldo del DaoVendedor, aliviando aún más la responsabilidad del Dao!!!


Adicionalmente, las Implicit Queries traerían otras ventajas:

  • Anidamiento de consultas transparente:

Supongamos que un vendedor pide adelantos de sueldo, y queremos conocer qué adelantos de sueldo han superado el total de comisiones por ventas que tiene. Esto, en la implementación actual, se haría de la manera siguiente:


SELECT v.adelanto
FROM Vendedor v
WHERE v = :vendedor AND v.adelanto > ALL(
SELECT SUM(venta.comision)
FROM Ventas venta
WHERE venta.vendedor = :vendedor
)


Si tuvieramos Implicit Query, sólo tendríamos que hacer esto:

SELECT v.adelanto
FROM Vendedor v
WHERE v = :vendedor AND v.adelanto > v.sueldo

  • Typesafe:

Si asociamos una Implicit Query a un campo o getter, el contenedor puede detectar en fase de deployment, si la propiedad soporta el tipo de dato retornado por la consulta. Esto ayudaría a detectar tempranamente los errores de tipo, reduciendo la posibilidad de que ocurran en tiempo de ejecución.

  • Polimorfismo:

Si además de Vendedores, nuestra empresa cuenta con Administrativos que ganan sus sueldos en función de las horas trabajadas, sería interesante generalizar ambas clases en una superclase Empleado. Las declaraciones quedarían asi:

public class Empleado{...}

@Entity
@NamedQuery(
name=”Administrativo.calcularSueldo”,
query=
”SELECT SUM(ht.cantidad) ” +
“FROM Administrativo a JOIN a.horasTrabajadas ht“ +
“WHERE a = :administrativo”
)

public class Administrativo extends Empleado{...}

@Entity
@NamedQuery(
name=”Vendedor.calcularSueldo”,
query=
”SELECT SUM(venta.comision) “ +
“FROM Vendedor v JOIN v.ventas venta ” +
“WHERE v = :vendedor “
)

public class Vendedor extends Empleado{....}

Entonces en la especificación actual, el DaoEmpleado, se deberia hacer esto para conocer el sueldo de un empleado:

public Long calcularSueldo(Empleado e){
if(e instanceof Administrativo){

return(Long)em
.createNamedQuery(“Administrativo.calcularSueldo”)
.setParameter(“administrativo”, e)
.getSingleResult();

}else{
return(Long)em
.createNamedQuery(“Vendedor.calcularSueldo”)
.setParameter(“vendedor”, e)
.getSingleResult();
}
}

Nada más lejos de la OOP. Además, el diseño se complicaría mucho más si hay más subclases de Empleado. Con implicit queries, éste metodo no sería necesario, simplemente definiríamos una implicit query por cada subclase de empleado, y la obtención del resultado sería de la siguiente manera:

empleado.getSueldo();

Si trasladamos esta característica al ámbito de EJBQL, la cantidad de consultas anidadas que nos ahorramos es enorme. Por ejemplo, si quisiéramos hallar todos los empleados que tengan un sueldo menor a 3000, tendríamos que anidar una consulta por cada subclase de empleado:

SELECT DISTINCT(e)
FROM Administrativo a, Vendedores v
WHERE (
a = :empleado AND 3000 > (
SELECT SUM(ht.cantidad)
FROM Administrativo a JOIN a.horasTrabajadas ht
WHERE a = :empleado
)
)OR(
v = :empleado AND 3000 > (
SELECT SUM(venta.comision)
FROM Vendedor v JOIN v.ventas venta
WHERE v = :vendedor
)

)

Utilizando Implicit Query, lo anterior se reduce a:

SELECT e
FROM Empleado e
WHERE e.sueldo < 3000

  • Simplificación de expresiones en contextos de Bean:

Las implicit queries, al evitar depender de otro objeto para su obtención, simplificarían el acceso a consultas dentro del contexto del Expression Language, porque se podría acceder al resultado navegando por el propio bean.