domingo, 11 de noviembre de 2012

Comparación de Implementaciones de JPA

Desde República Checa nos llega esta interesante tesis de Lukáš Šember, cuyo objetivo es comparar las tres implementaciones Open Source más populares de JPA:
Comienza con una breve introducción histórica a las bases de datos (relaciones, orientadas a objetos y NoSQL) y a las soluciones de persistencia provistas por la plataforma Java (JDBC, EJB 2, JDO, myBatis, para terminar en JPA).

Luego la tesis se divide en tres partes. En la primera, Šember se dedica a comparar los tres proveedores de JPA elegidos, exponiendo las fortalezas y debilidades de cada uno en distintos aspectos:
  • Generación de IDs
  • Performance
  • Conversión de Tipos
  • Soporte de Caché
  • Eventos
  • Generación de Esquemas
  • Soporte a Stored Procedures
  • Integración con Otros Frameworks
  • Licencias
  • Calidad de la Documentación
  • Sistemas de Build
La competencia es pareja. Es interesante leer el detalle de cada ítem, pero si vamos a la tabla comparativa de las conclusiones de la página 31, tenemos que la implementación de referencia, EclipseLink, el núcleo de TopLink donado a la Eclipse Foundation por Oracle, resulta el más performante en su configuración por defecto y el que mejor soporte provee para stored procedures (es lógico viniendo de Oracle). El veterano de JBoss nos brinda más funcionalidades a la hora de manejar eventos e integrarnos con frameworks existentes (es lógico considerando su historia y su cercana relación con Spring). OpenJPA se posiciona como el candidato más poderoso para generar el esquema automáticamente.

La segunda parte trata sobre distintos intentos del autor de migrar manualmente de un proveedor a otro, a partir de distintos proyectos Open Source descargados de Internet. Šember toma tres proyectos escritos con las tres distintas implementaciones, intenta migrar cada uno a los otros dos, y termina testeando con tres bases de datos diferentes: Oracle, PostgreSQL y MySQL. La conclusión a la que llega es que la migración no es para nada sencilla cuando la aplicación está haciendo un fuerte uso de las funcionalidades nativas, no estándares, que provee la implementación de JPA.

La última parte es más práctica. El objetivo final de la tesis es construir una herramienta que ejecute la migración automática de proyectos existentes que usan OpenJPA o EclipseLink, a Hibernate. La herramienta se llama JPA Migration y está escrita en Scala.

Como ven, el tema de la tesis es bastante interesante. A mí, en particular, la parte que más me interesó fue la primera, donde compara distintos aspectos de los tres proveedores que hay puestos sobre la mesa. En la práctica yo no veo tan útil un migrador. Es muy extraño que una empresa migre de una implementación de JPA a otra, y menos de una Open Source a otra Open Source, a menos que cambie de servidor de aplicaciones, que tampoco es algo tan común.

Quizá el escenario más probable podría ser el de un área de sistemas que desee deshacerse de su software privativo y le de la espalda a Oracle, migrando su servidor de aplicaciones Weblogic a uno comunitario y con gran soporte, como puede ser JBoss AS o TomEE. En ese caso, teniendo aplicaciones Java EE que usan EclipseLink o TopLink, quizá se justifique una migración a Hibernate (en el primer caso) o a OpenJPA (en el segundo). Pero siempre hay otras opciones menos dolorosas, como instalar EclipseLink en JBoss, o usar Glassfish en lugar de JBoss que también utiliza EclipseLink.

La tesis se puede descargar de:
http://is.muni.cz/th/365414/fi_m/thesis.pdf

El material me llegó vía el Twitter de @myfear.
¡Muchas gracias por compartirlo!

lunes, 29 de octubre de 2012

La Fábula del Diseñador Centrado en el Usuario

Diseño Centrado en el Usuario
Éste es un libro pequeño, libre, traducido al español, escrito por David Travis, que se puede descargar desde el sitio de OpenLibra.

La verdad es que se lee rápido y es muy ameno. Apenas 40 páginas con letra muy grande, ideal para leer en un e-reader.

Cuenta la historia de un diseñador que quiere volverse experto, un diseñador que quiere conocer el arte de construir interfaces de usuario centradas en el Usuario, algo que los desarrolladores de aplicaciones siempre queremos hacer pero pocas veces logramos.

A lo largo del libro, el protagonista va entrevistando a distintos clientes de un diseñador de gran renombre. Y cada uno de ellos le revela un secreto. A modo de resumen los copio en este post, así que ¡OJO! ¡Se vienen los SPOILERS!

Primer Secreto del Diseño Centrado en el Usuario:
Foco Temprano y Continuo en el Usuario y sus Tareas.

Segundo Secreto del Diseñador Centrado en el Usuario:
La Medición Empírica del Comportamiento del Usuario

Tercer Secreto del Diseñador Centrado en el Usuario:
Diseño Iterativo

Así, a través de estas entrevistas, se revelan conceptos interesantes como el de "medir la usabilidad", por ejemplo:

Usabilidad = Efectividad + Eficiencia + Satisfacción

Simplemente juntando algunos usuarios, poniéndolos a usar el producto y midiendo cuánta gente logra completar rutas críticas de forma exitosa (efectividad), cuánto tiempo les toma completar las tareas (eficiencia) y cómo se siente la gente respecto al diseño (satisfacción).

Mediante la observación del día a día del trabajo del usuario, las jornadas de mediciones empíricas y los prototipos iterativos (primero varias veces en papel o pizarrón, luego con algún programa de dibujo), el autor asegura conseguir un diseño centrado en el usuario, concluyendo en el siguiente flujo de trabajo:

Los Pasos del Diseño Centrado en el Usuario
Descárguenlo, léanlo y distribúyanlo. Es libre. Y está bueno.

domingo, 7 de octubre de 2012

Class Loader de JBoss AS 7

Entre una de las enormes mejoras y grandes cambios que tuvo la nueva versión del JBoss Application Server (JBoss AS 7), podemos encontrar un nuevo núcleo modular, basado en un proyecto llamado JBoss Modules, que ofrece verdadero aislamiento de las aplicaciones.

Los que hemos usado versiones anteriores de JBoss AS, sabemos que el sistema de classloading siempre ha sido un dolor de cabeza. Es que compartir librerías en runtime entre aplicaciones (uno de los sueños dorados de la modularización) nunca fue fácil ni bien implementado.

JBoss Modules es el proyecto base para el nuevo sistema de classloading de JBoss AS 7. Con él, toda aplicación o librería desplegada en el servidor de aplicaciones es tratada como un módulo.

JBoss Modules resuelve los clásicos problemas de classloading de versiones anteriores de JBoss AS, ya que por defecto todo módulo vive en forma aislada. Este nuevo Class Loader es más performante y más sencillo de usar gracias a su diseño minimalista. Además, se dice por ahí que es más rápido que OSGi. Los módulos JBoss Modules y OSGi pueden verse entre sí sin problemas; OSGi viene soportado por JBoss AS 7 out-of-the-box.

Les dejo un link muy interesante del maravilloso sitio Java Code Geeks (que es un extracto del capítulo 6 del libro JBoss AS 7 Configuration, Deployment and Administrator de Francesco Marchioni), donde se explica en detalle el funcionamiento del nuevo Class Loader de JBoss AS 7 y sobre cómo configurarlo:

martes, 2 de octubre de 2012

Curso de Hibernate en Español


Hace poco menos de un mes, el sitio de javaHispano publicó un muy interesante curso de Hibernate en español en formato wiki. En el curso se explican temas de JPA y temas específicos de Hibernate, la popular implementación de JBoss Community. Está muy bueno realmente y, como referencia, complementa muy bien este otro WikiBook de JPA que había compartido en este mismo blog a principios de año.

Enlace directo al curso (estimado por su autor en 40 horas):

domingo, 30 de septiembre de 2012

E-Books Gratuitos sobre Ágiles

Kleer, empresa dedicada al coaching, capacitación, entrenamiento y aprendizaje de metodologías ágiles, tiene su sección de libros electrónicos gratuitos para descargar en formato PDF. Libros en castellano, concisos, más bien guías prácticas.

Vale la pena echarles una mirada:

Ya se pueden descargar tres libros: uno de introducción a Ágiles y Scrum, otro de Planificación y Estimación en Entornos Ágiles y un tercero, publicado la semana pasada, enfocado en Técnicas para reuniones de Retrospectivas, escrito por Juan Gabardini.

domingo, 15 de julio de 2012

Spring V.S. Java EE

En Epidata Consulting, empresa especializada en Arquitectura de Software, donde yo trabajo, cada tanto realizamos charlas internas, externas (para universidades o clientes) y charlas-debate a los que solemos llamar "On The Rocks". En un ambiente relajado, con cerveza y snacks, debatimos sobre algún tema en particular. El viernes hicimos una "On The Rocks" llamada "Spring V.S. Java EE", y salieron algunas ideas interesantes.

Spring y Java EE son dos potentes soluciones para Middleware. Ambas presentan las mismas funcionalidades, ambas llenan los mismos huecos. Si tuvieras que empezar un nuevo proyecto Java Enterprise, ¿usarías Spring o Java EE? ¿Cuáles son las variables que pueden condicionar tu decisión? ¿Cuál es el estado de arte de ambas tecnologías? ¿Son realmente antagonistas?

Contexto


En el comienzo nació la especificación J2EE (versión 1.2 en 1999, versión 1.3 en 2001 y versión 1.4 en 2003) y Rod Johnson vio que era malo. Las implementaciones eran lentas, pesadas; el estilo de programación era verboso, lleno de tareas repetitivas, tedioso; un "hola mundo" en EJB 1.1 requería una cantidad de clases, interfaces y archivos XML desproporcionada. Recordemos que el lenguaje Java se había publicado apenas tres años atrás.

En 2002, Rod Johnson publicó un framework que servía como alternativa a los lentos y pesados EJB 2.0 de la época, un contenedor "liviano" (noten que ya de por sí el insidioso término "liviano" sugería una rivalidad; como dicen los ágiles: ¿quién no quiere ser liviano?). El framework básicamente hacía lo mismo que los EJBs (los EJB se reemplazarían por Spring Beans) y proveería también distintos módulos para facilitar el acceso a datos usando Java EE (en ese entonces la especificación JDBC) o frameworks de persistencia populares como Hibernate y más adelante iBatis. En 2004 se lanza la versión 1.0 de Spring, que viene a sacar del "invierno" a los programadores J2EE, ofreciendo una alternativa, una salvación: su contenedor "liviano" y los conceptos de Inversión de Control e Inyección de Dependencia.

En mayo de 2006 llega el contraataque del lado de la JCP (Java Community Process). Después de tres años sin publicar una nueva versión, J2EE 1.4 (JSR-151) pasa a llamarse Java EE 5 (JSR-244) y muchos de los productos que venían pegando en la comunidad Open Source (Hibernate y Spring, entre otros) pasan a ser especificaciones. Hacía dos años que el lenguaje Java SE se había renovado, metiendo las anotaciones, esa nueva y controvertida forma de configurar, y la plataforma enterprise tomó ventaja absorbiendo las anotaciones para su configuración, rivalizando contra los verbosos y molestos descriptores XML de configuración de Spring y J2EE. Nacen JPA 1.0, EJB 3.0, JSF 1.2 y JAX-WS (para hacer servicios SOAP) como las sub-especificaciones que hacen la diferencia. Las implementaciones se van mejorando (Glassfish, JBoss, Weblogic, Websphere). Por primera vez el estándar saca ventaja y deja atrás a Spring.

En 2005, un año antes de la salida de Java EE 5, Rod Johnson funda la empresa SpringSource. Más adelante, Spring Framework incorpora las anotaciones a su inyector de dependencias, pero lo hace mucho tiempo después; recién en la versión 2.5 podemos hacer un uso full de ellas. Aunque EJB 3.0 y JPA presentan una mejora considerable, siguen perdiendo frente a Spring en funcionalidades como Orientación a Aspectos e Inyección de Dependencia, que sigue siendo mucho más potente (en Java EE 5 sólo podemos tener inyección de dependencia dentro de un EJB).

El 10 de diciembre de 2009, la JCP pone en jaque verdaderamente a Spring con su nueva versión de la especificación: Java EE 6. Una nueva sub-especificación viene a llenar los huecos de Java EE 5, la JSR-299, más conocida como CDI (Contextos e Inyección de Dependencia para Java). CDI puede correr sin un contenedor de EJB (como Spring, puede correr en un Tomcat, un Jetty o standalone), ofrece inyección de dependencia omnipresente, una capa de presentación stateful y declarativa, manejo de eventos avanzados e interceptores mucho más potentes que los que proveía EJB 3.0, con los que puede rivalizar en el mundo de la Orientación a Aspectos. Como si fuera poco, Java EE 6 trae JAX-RS (para hacer servicios REST), JPA 2.0 (con muchas mejoras) y EJB 3.1, que, entre otras ventajas, permite empaquetar EJBs en un paquete WAR.

Java EE y Spring en un Vistazo de Águila

Así está la cosa hoy en día. Java EE 6 es la última especificación de la JCP, contando con 17 implementaciones certificadas a la fecha y Spring Framework, la única implementación, se encuentra por la versión 3.1.0. En 2009, VMWare adquirió SpringSource y hace unos días, Rod Johnson, CEO de SpringSource, anunció su inminente renuncia de VMWare.

Algunas Comparaciones


La competencia es muy buena para el consumidor, en este caso los programadores. Spring y Java EE fueron copiándose mutuamente a lo largo de los años, mejorándose en función de lo que su rival todavía no hacía o hacía mal. Así como entre 1957 y 1975 hubo una carrera espacial entre la URSS y EEUU, se puede decir que SpringSource y la JCP libraron su propia carrera hacia la solución de Middleware perfecta. La carrera todavía no está terminada. Algunos dicen que sí, algunos dicen que la era de los frameworks está terminando. Yo no creo que todavía esté dicha la última palabra.

I. Estado de Arte


A la hora de hacer comparaciones es justo tomar las últimas versiones, evaluar el estado de arte de ambos lados de la balanza. Es ilógico comparar Spring 3 con EJB 2, una tecnología de hace once años. Estamos en la segunda década del siglo XXI y la especificación vigente es Java EE 6, comparemos entonces CDI 1.0 y EJB 3.1 contra Spring 3.1.

Todos nosotros, en general, usamos versiones antiguas en el trabajo. Es perfectamente normal, ya que no se comienzan proyectos con la velocidad con la que salen frameworks y especificaciones Open Source. A menudo mantenemos software heredado que cuenta con versiones viejas de Spring o de J2EE. Pero si tenemos que comenzar un nuevo proyecto, para que nuestra evaluación de tecnologías sea válida, tenemos que actualizar las versiones, e incluso mirar más allá, mirar hacia el futuro, hacia las versiones beta, las funcionalidades futuras que se discuten en las comunidades y las especificaciones draft.

II. Funcionalidades


A la hora de evaluar, no creo que sea importante en sí las funcionalidades o servicios que uno provee y el otro no, ya que mañana los dos la proveerán. Esta es la "carrera" por la solución de Middleware a la que antes me refería.

Últimamente los IDEs están viniendo con súper wizards para generar aplicaciones de forma instantánea. Simples CRUDs se pueden escribir de forma automática con Spring Roo, en el mundo de Spring, o con JBoss Forge, en el mundo de Java EE. Hay plugins para Eclipse, NetBeans, JDeveloper, que pueden acelerar la escritura de código y el aprendizaje; en Spring tenemos por ejemplo SpringSource Tool Suite, en Java EE podemos contar con JBoss Tools, o el mismo JDeveloper de Oracle si programamos para Weblogic, por ejemplo, o el mismo NetBeans que ya trae plugins out-of-the-box muy potentes para Glassfish.

Ninguno de los dos mundos tiene soluciones perfectas. Cuando uno sigue un tutorial puede encontrar errores. Los quick-starts tienen errores o se van desactualizando muy rápidamente. Las documentaciones están incompletas. Pero es el precio de la innovación, el precio del Open Source. Los tiempos se aceleran en los negocios, y deben acelerarse en el desarrollo de software para no morir ahogado por los requerimientos. A la hora de capacitarse, un programador debe ser cauteloso y tener criterio para entender los conceptos, más allá de la cantidad de botones "Siguiente" que debe presionar.

III. La Era de los Frameworks ha Terminado


La diferencia más grande entre Spring y Java EE es que el primero es un framework y la segunda una especificación. Spring tuvo un creador, Rod Johnson, que fundó una comunidad y una empresa alrededor de su framework y hoy en día no es más que eso: un conjunto de librerías, que uno puede descargar por la página oficial del proyecto o de los repositorios centrales de Maven, y utilizar; son un conjunto de JARs. En cambio, Java EE es un conjunto de especificaciones estándares, escritas, revisadas y aprobadas por una comunidad de expertos, que en su conjunto definen qué servicios debería proveer y cómo se debería programar en una plataforma para aplicaciones empresariales.

Para que una especificación sea terminada, tiene que pasar por un largo proceso en el que la misma nace en Draft Version, pasa a diferentes estados de Review, y por último llega a una Final Version. Las especificaciones pueden deprecarse o cancelarse. Para que la especificación llegue a Final Version, el comité de expertos de la JCP debe revisarla, puede corregir errores, aportar modificaciones y en una última instancia votar. Los expertos de la JCP son empleados de distintas empresas interesadas, entre ellas Apache, Oracle, Red Hat, IBM. O sea que, cuando usamos alguna interfaz que pertenece a una especificación, estamos usando un contrato que fue pensado y aprobado por grandes mentes humanas.

En la práctica, una especificación se traduce en un conjunto de interfaces Java. Luego, distintas comunidades Open Source y/o empresas pueden codificar las clases que implementen esas interfaces. A menudo, los mismos que están escribiendo la especificación codifican una implementación para corroborar que las interfaces tienen sentido. Ésas pasan a ser las implementaciones de referencia, las primeras Open Source que se publican. Luego, las distintas empresas pueden desarrollar sus propias implementaciones, respetando la especificación e incluso proveyendo más servicios que enriquezcan la especificación pero que, por supuesto, no sean estándares. Ejemplos hay muchos. Por mencionar algunos de los más conocidos: la implementación de referencia de JPA 2 es EclipseLink, otras implementaciones pueden ser Hibernate de Red Hat, TopLink de Oracle o OpenJPA de Apache; la implementación de referencia de EJB 3.1 es el contenedor de EJBs de Glassfish, otras implementaciones pueden ser JBoss de Red Hat, Weblogic de Oracle, Websphere de IBM o TomEE de Apache; la implementación de referencia de CDI 1.0 es Weld de Red Hat (pueden leer más de CDI en este post y en este otro).

IV. Portabilidad


La filosofía del lenguaje Java siempre fue: Write Once, Run Anywhere, y la forma en que se aseguró de lograr esto fue mediante especificaciones y estándares. Java SE define cómo debe ser el lenguaje, qué debería entender un compilador Java y qué debería ejecutar una máquina virtual (JVM). Así, cada fabricante de celular, electrodoméstico, sistema operativo para PC, servidores, etc, sólo debía escribir su propia máquina virtual, que corriera sobre su propia plataforma, y que implementara las especificaciones, para que los programadores pudieran escribir sus programas una sola vez y lo ejecutaran en cualquier plataforma que implementara una JVM.

Java EE es el conjunto de especificaciones que define los servicios que debe proveer una plataforma de software Java empresarial, en la práctica: un servidor de aplicaciones. Los servidores de aplicaciones son aquellos que implementan los estándares de Java EE. Cada proveedor (Red Hat, Oracle, IBM, Apache, etc) está obligado a respetar cierta funcionalidad y configuración para poder certificar con Oracle (el dueño legal del lenguaje Java), para poder ser aceptado dentro de un perfil válido y aparecer en esta lista oficial. Los perfiles no son más que distintos subconjuntos de sub-especificaciones Java EE. Además, cada proveedor puede implementar funcionalidad no estándar para mejorar algún aspecto de su implementación. Por eso es que si programamos contra el estándar, tenemos libertad para elegir el proveedor. Un EJB se usa y configura de la misma forma en un JBoss, Weblogic, TomEE o Glassfish. Si tenemos problemas con un servidor de aplicaciones y queremos pasarnos a otro que luce más estable, podemos hacerlo sin modificar el código de nuestra aplicación. En cambio, si el contenedor de Spring funciona mal, no tenemos ninguna otra alternativa.

Spring tiene una definición distinta de portabilidad que Java EE. Mientras que un servidor Java EE es una plataforma, que ya provee todas las implementaciones de las especificaciones en forma de librerías, Spring es un conjunto de JARs que deben ir dentro de tu empaquetado, generalmente un WAR. Cuando armamos un paquete de Java EE, no incluimos las librerías dentro de nuestra aplicación, porque ya existen en la plataforma en la que se ejecuta. Para asegurarnos la portabilidad en Java EE, a la hora de cambiar de servidor, tendremos que fijarnos que el servidor de destino implemente la misma versión de la especificación que el servidor de origen, y que nuestras aplicaciones no estén usando librerías y configuración fuera del estándar. En cambio, cuando usamos Spring, como en cada aplicación metemos todo el contenedor dentro del empaquetado, no habría problema de desplegar en cualquier servidor, así sea un JBoss 4, un JBoss 7, un Weblogic 12 o un Tomcat.

Claro que, la desventaja que tenemos con Spring, nada menor, es el tamaño de nuestros entregables. Para hacer un WAR que contenga una página con un CRUD simple o un Hola Mundo, ya tenemos que incluir un montón de librerías cuyo peso suma en varios megas.

V. Vendor Locking


Por todo lo que vengo explicando en los puntos anteriores, algunos dicen que Spring hoy es "legacy", un sistema heredado de aplicaciones que se construyeron cuando Spring sí era necesario y J2EE no podía competir. La libertad para elegir los contenedores de Java EE inclina mucho la balanza. Hay servidores de aplicaciones Open Source como Glassfish, hay otros como JBoss que también son comunitarios pero se pueden comprar suscripciones a través de Red Hat para obtener versiones más estables y soporte, hay otros como Weblogic y Websphere que se venden por licencias.

Spring tiene la desventaja de ser "vendor locking". Cuando en un proyecto se elige trabajar con Spring automáticamente se casa con SpringSource, hoy propiedad de VMWare. El proyecto queda atado de pies y manos al futuro de SpringSource y VMWare. Si el día de mañana la comunidad de Spring se disuelve, si a VMWare ya no le interesa el proyecto, tus proyectos basados en Spring van a quedar en una situación delicada (y sino pregúntenle a los miles de proyectos que están hechos con Flex).

Si a Red Hat dejara de interesarle JBoss, si Glassfish se discontinúa, no sería tan grave, ya que hay otra decena de servidores de aplicaciones Java EE que se pueden utilizar, y se programa para ellos de la misma manera.

VI. Estabilidad de la Plataforma


Los servidores de aplicaciones Java EE son testeados en una amplia variedad de sistemas operativos y plataformas mientras que, con Spring, los mismos desarrolladores de las aplicaciones son los responsables de probar con diferentes máquinas virtuales, sistemas operativos, releases, parches, etc. Al no ser estándar, Spring no puede asegurarte que funcionará bien en cualquier servidor que lo despliegues.

Cuando una empresa necesita estabilidad, confiabilidad y alta disponibilidad, no le importa pagar por ello. Por eso hay muchos proveedores que venden esa tranquilidad a las empresas, por ejemplo Red Hat, por ejemplo Oracle. Cuando un cliente compra una suscripción para JBoss (una EAP, por ejemplo), no sólo está comprando el testing sobre el servidor en sí, sino también el testing de la integración de todas las tecnologías que provee la plataforma, la armonía entre todas las implementaciones de especificaciones y librerías propias que están allí dentro (JBoss no sólo trae implementaciones de Red Hat, también hay algunas que son de Apache y otras tantas también de Spring). Si una aplicación hecha a medida corre en un JBoss con suscripción y usa alguna librería del mismo servidor, por ejemplo Hibernate (la implementación de JPA) y tiene problemas, puede recibir soporte. Si en cambio nuestra aplicación está basada en Spring y se despliega en un JBoss certificado, como Spring no es parte del servidor, ¿a quién vamos a quejarnos? VMWare nos puede decir que el problema es de Red Hat, y Red Hat puede decirnos que el problema es de VMWare. Probablemente estés probando la integración de las dos tecnologías por primera vez.

VII. Unit Test


Se dice por ahí, por la gran red de redes, que Spring sigue siendo más potente para realizar pruebas unitarias con JUnit, Test NG u otras herramientas. Con Java EE 6 tenemos Arquillian, una librería de JBoss de la cual ya he escrito en este post. Arquillian facilita el Unit Test de EJBs y de servicios que se ejecutan en el mismo servidor de aplicaciones. La filosofía más grande de Arquillian es: no mockeés tus objetos, probalos rápido en su entorno real. Atractivo, ¿no? En lugar de trabajar con Mocks o Dummies, Arquillian permite inyectar EJBs, o Managed Beans de CDI, u otros servicios, dentro de los JUnit Test, empaquetando rápido, desplegando y ejecutando del lado del servidor.

Arquillian no es estándar, pero no me extrañaría que en un futuro cercano sí lo fuera, quizá en Java EE 7 o Java EE 8.

VIII. Ecosistemas


Por último, para ir cerrando con estas comparaciones, quisiera aclarar que Spring es hoy un proyecto modular. Spring no existe por sí solo sino que corre usando en general la plataforma Java EE. Hay módulos de Spring que facilitan el uso de JPA, otros el uso de JMS, etc. Los módulos se pueden usar justamente de forma modular. Podemos tener una aplicación Java EE y usar algún módulo independiente de Spring. Los Spring Beans pueden inyectarse dentro de Managed Beans de JSF, Spring 3 soporta bidireccionalidad con EJBs, un proyecto de JBoss, Snowdrop, permite inyectar beans de Spring en EJBs. O sea que no siempre los dos mundos son antagonistas.

Ecosistema de Spring

Mientras que el ecosistema de Spring son módulos de librerías lanzados por SpringSource, el ecosistema de Java EE está comprendido por especificaciones de la JCP e implementaciones y extensiones de muchos proveedores.

Ecosistema CDI (Java EE 6)

Conclusión


Como se habrán dado cuenta si llegaron hasta aquí, la pelea no es pareja. De un lado del ring está SpringSource, propiedad de VMWare, solito, del otro hay muchos pesos pesados: Oracle, Red Hat, Apache, IBM, entre otros. Por unos años más, Spring va a seguir teniendo la antorcha de la innovación. Java EE, al ser estándar y requerir la aprobación de expertos y seguir un proceso, puede ser más lento a la hora de innovar. Pero Java EE lleva la antorcha del aplomo, la madurez y la libertad de elección. No olviden que casi todas las especificaciones surgieron de meter en una licuadora muchos productos que ya venían funcionando y tomar lo mejor de varios mundos. El ejemplo más claro es CDI, que surgió de las lecciones aprendidas de Spring, Google Guice y Seam. CDI cierra la brecha que todavía separaba a Java EE de Spring. Arquillian es otro peso fuerte, camino a hacerse estándar.

Aunque Spring y Java EE pueden funcionar de forma integrada, el costo de esa integración no es gratis y casi siempre lo paga el programador de aplicaciones cuando las cosas no funcionan. Por otra parte, siempre hay que ser imparciales a la hora de elegir; recordemos que la pelea es desproporcionada, van a encontrar muchos más sitios que defiendan a Java EE que a Spring, sitios de Oracle, de IBM, de Red Hat, etc.

Por otro lado, ni las tecnologías viejas eran tan malas, ni las nuevas son tan buenas. Siempre hay programadores que pueden desarrollar más rápido y mejor con tecnologías viejas que otros con tecnologías nuevas. Esto significa que, casi siempre, quienes hacen la diferencia son los profesionales y no los frameworks. Los frameworks por sí solos no pueden hacer nada.

Sin embargo, el software evoluciona, y la forma de hacer software también. Si no lo hiciera, nuestra disciplina (que todavía está en pañales) se estancaría. Debido a que el desarrollo de software es imperfecto y propenso a errores humanos, es necesario que evolucionemos constantemente, que adoptemos una posición de cambio y mejora continua. ¡No podemos darnos el lujo de quedarnos estancados en nuestras tecnologías de confort!

Hay una afirmación que me atrevo a declamar a los cuatro vientos y es que, hoy en día, no comenzaría una aplicación enterprise Java que no use ninguna de las dos soluciones de Middleware más importantes. Tanto Spring como Java EE son absolutamente necesarios; uno, la otra, o las dos. Y casi diría que si el cliente en el cual tendré que desplegar la aplicación ya cuenta con un servidor de aplicaciones Java EE, seguramente utilizaré CDI y EJB y JPA, más las sub-especificaciones que necesite. No hacerlo, sería como tener una Ferrari para manejar por las callecitas de microcentro.

Referencias


Java SE version history:
http://en.wikipedia.org/wiki/Java_version_history

Java EE version history:
http://en.wikipedia.org/wiki/Java_version_history

Spring Framework:
http://en.wikipedia.org/wiki/Spring_Framework

Entrevista a Rod Johnson, creador de Spring, después de anunciar su partida de VMWare:
http://www.infoq.com/news/2012/07/johnson-leaves-vmware

"Por qué Java EE 6 es mejor que Spring": Post del blog de Arun Grupta de Oracle:
https://blogs.oracle.com/arungupta/entry/why_java_ee_6_is

JBoss Developer Framework:
http://www.jboss.org/jdf/

Ejemplo de TicketMonster: Aplicación Java EE que usa JPA, JAX-RS, HTML5, JSF2, RichFaces 4 y jQuery, Mobile y otras yerbas más:
http://www.jboss.org/jdf/examples/get-started/

Excelentes Diapositivas sobre Java EE 6 V.S. Spring 3, de las cuales robé algunas imágenes:
http://www.slideshare.net/kelapure/java-e-evsspringshootout

Usando JSR-250 @PostConstruct, @PreDestroy y @Resource con Spring y con Java EE:
http://www.captaindebug.com/2011/11/using-jsr-250s-postconstruct-annotation.html

Spring V.S. Guice: Inyección por nombre (objeto) V.S. Inyección por tipo (clase):
http://www.javacodegeeks.com/2012/06/spring-vs-guice-one-critical-difference.html

Otro post a favor de Java EE contra Spring:
http://www.javacodegeeks.com/2012/03/why-i-will-use-java-ee-instead-of.html

Un post inclinando un poco la balanza a favor de Spring:
http://www.javacodegeeks.com/2012/07/java-ee-6-vs-spring-3-java-ee-has.html

Reference Cards de DZone sobre CDI y Spring:
http://refcardz.dzone.com/refcardz/contexts-and-depencency
http://refcardz.dzone.com/refcardz/spring-annotations

Epidata Consulting: On The Rocks: Spring V.S. Java EE
http://www.epidataconsulting.com/tikiwiki/tiki-index.php?page=On+The+Rocks%3A+Spring+V.S.+Java+EE

domingo, 8 de julio de 2012

¿Ha Muerto el Diseño?

Es increíble cómo este artículo de Martin Fowler, escrito hace 12 años, todavía sigue teniendo tanta vigencia. Aquí pueden leer una traducción en español, si lo desean. Lectura obligada para todo arquitecto, diseñador y/o desarrollador de software.

Corría el año 2000. Con el fin del siglo XX empezaron a surgir las críticas hacia RUP y hacia las metodologías orientadas al plan. La (mala) experiencia había demostrado que construir software no era lo mismo que construir edificios. En una emergente economía de conocimiento, el cambio era una constante en todos los proyectos. Todavía no se hablaba de Scrum pero sí de XP, y el siglo XXI nació con el manifiesto ágil, firmado por los grandes diseñadores de software del mundo, entre ellos Martin Fowler.

En este histórico artículo, Fowler se pregunta cuál es el rol del inmaculado arquitecto de software en el desarrollo ágil. Viniendo del mundo del diseño planeado, enfrenta al plan contra el diseño evolutivo, concluyendo que XP no es "codificar y corregir", ni mucho menos una involución para la Ingeniería de Software.

Hoy, 12 años después, siguen rondando las mismas dudas. ¿Existe la Arquitectura de Software? ¿Es la construcción de software una Ingeniería? Los aspectos blandos que el desarrollo implica nos acercan más a disciplinas sociales de lo que a las empresas y a los gerentes de proyecto les gustaría. El software es un intangible y, como tal, completamente maleable. A pesar de todas las técnicas, patrones, estándares, frameworks, librerías, la programación sigue siendo un trabajo creativo, más cercano al de un artesano que al de un técnico. El hardware podrá evolucionar según la exponencial de la Ley de Moore, pero el software no se puede poner en una cadena de montaje; siempre que escribir la lógica dependa de humanos, el progreso será de forma escalonada y a los trompicones.

La revolución que comenzó a inicios del nuevo siglo todavía sigue madurando, enarbolando las banderas de Scrum y otras metodologías ágiles. Todavía no encontramos el balance perfecto entre las relaciones humanas y el lenguaje de máquina. Pero estamos mucho más cerca.

Sitio oficial de Martin Fowler:

sábado, 30 de junio de 2012

Auditoría con JPA

Auditoría es uno de los pedidos que más suena cuando tenemos una base de datos.  Los requerimientos de auditoría pueden ser bien simples (como agregar cuatro columnas a todos los registros que indiquen usuario de creación, fecha de creación, usuario de modificación y fecha de modificación) o bien complejos (como clonar absolutamente todos los datos con cada modificación de un registro en tablas de historiales).

Para esto, la especificación de JPA provee anotaciones para marcar ciertos métodos que queremos que se invoquen dado determinado evento. Los eventos pueden ser:
  • @PostLoad
  • @PrePersist
  • @PostPersist
  • @PreUpdate
  • @PostUpdate
  • @PreRemove
  • @PostRemove
Podemos leer más sobre los eventos de JPA aquí.

Este link de la documentación de EclipseLink es también muy interesante. Explica distintas formas de auditar utilizando EclipseLink, la implementación de referencia de JPA 2. La que más me ha gustado a mí es la de la clase AuditedObject, que muestro a continuación:


La idea es bien simple. Todas las entidades que extiendan de AuditedObject van a heredar los atributos auditUser y auditTimestamp. Mediante el método updateAuditInfo que es disparado por los eventos @PrePersist y @PreUpdate, estos atributos se mantendrán actualizados de forma transparente. Lo único que tiene de malo es que hay que acordarse de setear el currentUser en la variable ThreadLocal. En una aplicación web esto tiene que hacerse en cada request. Yo, por ejemplo, resolví esto de forma sencilla usando un Filter de Servlets.

Cuando los requerimientos de auditoría son mucho más complejos, como en el caso de mantener tablas de historiales y repetir cada una de las columnas cada vez que hay un cambio sobre un registro, quizá necesitemos una solución más compleja como la que provee JBoss Envers para Hibernate.

sábado, 9 de junio de 2012

JBoss Developer Framework

Esta semana JBoss ha anunciado el proyecto JBoss Developer Framework (noticia aquí y aquí). Para los que venimos siguiendo a JBoss nos puede sorprender: ¿JBoss Developer Framework? ¿De qué hablan? ¿De Seam? ¿De las plataformas certificadas?

Más que un framework, JDF se trata de un portal cuyo propósito es proporcionar documentación y ejemplos para que la gente comience a trabajar con Java EE 6 usando a JBoss como servidor de aplicaciones y stack de implementaciones.

¿Qué ofrece JDF? Más de 50 Quickstarts, ejemplos (como el de TicketMonster, una aplicación completa subida a GitHub, que usa JPA2, Bean Validation, servicios REST expuestos con JAX-RS, HTML 5 en el cliente, Seam Forge, y GWT a través de Errai, tomá!!), tutoriales de migración (de Spring a Java EE 6, de Java EE 5 a Java EE 6, etc) , BOMs (una serie de archivos BOMs de Maven para facilitar el despliegue y test de aplicaciones Java EE 6) y Roadmap (en el que planean ir agregando nuevas tecnologías al stack como Detaspike, que ya mencioné en este post, y Aerogear).

En el mundo del conocimiento, JDF está enfocado a la educación y la difusión de Java EE 6, mostrando de una forma práctica y ágil cómo utilizar los productos y las implementaciones del universo JBoss. Todo un ejemplo del Open Source. Un proyecto ambicioso. Esperemos que con el tiempo no caiga en vía muerta como sucedió en el pasado con tantos otros proyectos educativos, incluso del mismo JBoss.

sábado, 26 de mayo de 2012

Armando una Plataforma SOA con Apache

http://www.apache.org/
Hoy me voy a desviar del tópico Java EE 6 de los post anteriores para meterme un poco en el mundo SOA (arquitecturas orientadas a servicios). Me desvío pero no demasiado porque me quedo en el mundo Java. Y si hablamos de Java, uno de los líderes indiscutidos del open source es la Apache Software Foundation.

SOA fue un estilo de arquitectura muy popular hace unos años, uno de los términos en boga como hasta hace nada Twitter, las bases de datos NoSQL o la nube. Como pasó y sigue pasando con muchos conceptos fue malinterpretado por gerentes, líderes de proyecto, arquitectos y programadores. Tras muchos proyectos fracasados, tras muchas empresas que dejaron a sus ESBs abandonados en algún servidor perdido con cuatro o cinco servicios desplegados (poco tiempo después de que se anunciaban los marketineros casos de éxito), nos paramos un segundo a pensar y nos preguntamos: ¿Sirve SOA?

No voy a discutir sobre eso ahora, pero hay varios debates muy buenos que pueden leer si les interesa: SOA is Dead?, Debate: Is SOA Dead?,  Is SOA Dead as a Term but Alive as a Concept?Does BPM-in-the-Cloud Require RESTful Services?

SOA sí sirve, pero no como un producto de moda y sí como lo que es: un estilo de arquitectura. El software sufre hoy el aceleramiento exponencial que sufre el ser humano del siglo XXI y que la misma industria de software potenció (pero más la industria del hardware). SOA como un concepto necesitaba un tiempo de maduración. Entender SOA como una filosofía, como un nuevo paradigma, como una nueva forma de concebir el desarrollo de software, lleva tiempo. Por eso, cuando SOA se lanzó la década pasada, a toda velocidad, se mezcló demasiado con Web Services.

Por todos lados se dice que SOA no es un producto. SOA no es los productos que voy a mencionar en breve de Apache, SOA no es la SOA Platform de JBoss, SOA no es una suite costosa de Oracle. Y es verdad. Vuelvo a repetir: SOA es un estilo de arquitectura. Pero así como a nadie se le ocurriría desarrollar un ERP o un CRM con Assembler, hoy en día nadie pensaría implementar SOA con tan sólo un lenguaje de propósito general (GPL) como es Java, C o Python.

Para cerrar con este extenso preámbulo, imaginemos que decidimos implementar SOA en una empresa y que vamos a usar todos productos Open Source. Una opción podría ser la de JBoss, que mencioné en el párrafo anterior, con su HornetQ, su JBoss ESB, una cucharada de Smooks por aquí, otra de Drools por allá; todo esto vendido por Red Hat como la SOA Platform. Otra opción es la que me da la excusa para escribir este post: la Apache SOA Platform (este nombre lo acabo de inventar).

Apache ActiveMQ

http://activemq.apache.org/
ActiveMQ es la plataforma de mensajería de Apache, un broker de mensajería, orientado al intercambio de mensajes asincrónicos (MOM: Message-Oriented Middleware). Un broker de mensajería permite que distintas aplicaciones y componentes se comuniquen entre sí en tiempo real, desacopladamente, mediante el envío y recepción de mensajes, sin conocer previamente quiénes participan en el proceso.

ActiveMQ provee una implementación de la especificación JMS y un conjunto de funcionalidades adicionales como destinos dinámicos, consumidores retroactivos, grupos de mensajería, políticas de entrega repetitiva y mucho más. Provee APIs clientes para una variedad bien grande de lenguajes y tecnologías (Ajax, C++, Python, PHP, WebSockets y un largo etcétera) y también de protocolos de transporte, como HTTP, UDP, SSL, Multicast, etc.

Una tecnología de este tipo provee alta escabilidad. Los productores y consumidores no necesitan conocerse entre sí, los participantes pueden conectarse y desconectarse dinámicamente y hasta se puede armar una red de brokers capaces de autodescubrirse entre sí, formando distintas topologías.

Apache Camel

http://camel.apache.org/

Apache Camel es un framework para construir soluciones de integración y enrutamiento. Con él se pueden definir flujos de integración en múltiples lenguajes como XML, Java, Scala, etc. Básicamente implementa los patrones de integración propuestos en el excelente libro de Gregor Hohpe y Bobby Woolf de la serie de Martin Fowler: Enterprise Integration Patterns. El catálogo de patrones se puede revisar en la página oficial del libro. Estos patrones proveen un marco teórico para la comprensión y uso de Apache Camel.

Entre los patrones más conocidos tenemos: Content-Based Router, Message Filter, Dead Letter Channel o Guaranteed Delivery.

Si les interesa conocer más de Apache Camel, la página de Adictos al Trabajo tiene un excelente tutorial sobre cómo dar los primeros pasos en este framework.

Apache CFX

http://cxf.apache.org/
Apache CXF sirve para construir, exponer y consumir Web Services. Implementa las especificaciones JAX-WS y JAX-RS de Java EE; la primera para exponer fácilmente una funcionalidad hecha en Java como un Web Service SOAP mediante un conjunto de anotaciones, la segunda, idem pero para un servicio REST. En el mundo de JBoss se usa Apache CXF para JAX-WS y en algunos casos se suele usar RESTEasy para lo que es JAX-RS.

Inicialmente este proyecto se llamaba Celtrix y era propietario, hasta que lo adquirió Apache, lo combinó con XFire y allí salió CXF.

CXF se puede desplegar en casi cualquier servidor: un contenedor de Servlet como Tomcat o Jetty, un servidor de aplicaciones como Glassfish, un ESB como ServiceMix, un contenedor OSGi como hoy en día es JBoss 7 o una aplicación standalone con su propia JVM.

Al que le interese ver Apache CXF en acción, le recomiendo este post del blog Enterprise Development Ideas, donde se combina Maven 3, Apache CXF 2.6 y Spring 3.1.1 para armar un servicio SOAP con JAX-WS.

Apache ServiceMix

http://servicemix.apache.org/
Apache ServiceMix es un contenedor flexible que unifica las funcionalidades de ActiveMQ, Camel, CXF, ODE (motor de orquestación de servicios WS-BPEL) y Karaf. Se podría decir que el core de ServiceMix es Apache Karaf, un ESB (Enterprise Service Bus) basado en OSGi. ServiceMix combina las tecnologías antes vistas para proveer la plataforma SOA por excelencia, la que siempre prometió ser la columna vertebral de la empresa, el ESB.

OSGi presenta una gran evolución frente a los ya arcaicos y siempre problemáticos classloaders.

OSGi V.S. Classloaders de Java EE

Mientras que los classloaders de un servidor de aplicaciones típico JavaEE (como JBoss 6 o inferior) se organizan de forma jerárquica, OSGi trata a las librerías Java como si fueran módulos que dependen unos de otros. Este grafo de dependencias que OSGi propone viene a resolver los problemas típicos de classloaders que podemos tener a la hora de actualizar una versión de un framework que usan N aplicaciones desplegadas en un mismo servidor.

El nuevo JBoss 7 viene con OSGi, el nuevo Weblogic 12 también. Lo mismo que el ESB de Apache.

Algunos de los beneficios de usar OSGi frente a una jerarquía de classloaders pueden ser:
  • Control absoluto sobre versiones y dependencias: múltiples versiones de una librería conviven felizmente en el mismo contenedor
  • Desacoplamiento entre módulos: mediante una Arquitectura Orientada a Servicios interna (dentro del servidor)
  • Las clases y dependencias se comparten: para una gestión más eficiente de la memoria
  • Agilidad en el desarrollo, testeo y actualización de versiones (hot deploy)
  • Olvídese del "si funciona, no lo toques": entienda e inspeccione exactamente qué librerías se están usando en cada parte de su aplicación... ¡en tiempo de ejecución!
  • Aísle los cambios en sus componentes: de manera que no impacten al resto del sistema
  • Ponga su servidor a dieta: OSGi = modularidad, también en el servidor. ¡Basta de dolorosos slimmings! Utilice sólo las funciones que necesite en su servidor. Cargue a demanda.
OSGi suena ideal para un ESB, ¿no? Y además, todos los que tuvimos que pelearnos alguna vez con una estructura jerárquica de classloaders, sabemos que no escalan; a duras penas logran satisfacer los inmensos y heterogéneos entornos empresariales de hoy.

FuseSource


Antes de terminar, es mi obligación revelar la fuente principal de la que saqué el 90% del material que presenté en este post. FuseSource se trata de una empresa dedicada al arduo trabajo de la integración, utilizando estos productos open source de Apache. Al igual que Red Hat vende suscripciones de productos de JBoss, FuseSource vende suscripciones para una plataforma de Middleware basada en ActiveMQ, Camel, CXF y ServiceMix a la que llama Fuse ESB Enterprise y Fuse MQ Enterprise. La info la saqué del webinar de Raúl Kripalani llamado "Integración potente con tecnología Open Source Apache, allá donde lo necesite", el primero realizado en español. Si les interesó este post, probablemente les interese mucho este webinar.

sábado, 5 de mayo de 2012

Charla Java EE 6 in Action en CAECE

Introducción a las Principales Tecnologías de Java EE 6

Epidata Consulting los invita a participar de la charla "Java EE 6 in Action", que tendrá lugar el próximo Martes 15 de Mayo, de 19.00 a 20.30hs en la Universidad CAECE, en Av. de Mayo 866, Ciudad Autónoma de Buenos Aires.

El objetivo de la actividad será presentar una introducción a la plataforma actual de Java Enterprise, a través de sus tres especificaciones fundamentales: JPA, como Mapper de objetos a tablas relaciones, EJB, como proveedor de servicios de infraestructura, y CDI, como un ágil y moderno modelo de programación. Montada sobre el lenguaje Java estándar, la plataforma Java EE provee un entorno de desarrollo y ejecución para aplicaciones empresariales. Las nuevas versiones de los servidores de aplicaciones (Glassfish, JBoss, Weblogic) ya implementan esta especificación y las empresas, cada vez más atraídas por los estándares, comienzan a migrar hacia esta nueva plataforma.

La charla será dictada por Adrián Paredes, arquitecto de software de Epidata Consulting.

Temario

  • Introducción a Aplicaciones Enterprise y Java EE
  • Java Persistence API 2.0 (JPA)
  • Enterprise JavaBeans 3.1 (EJB)
  • Contexts and Dependency Injection 1.0 (CDI) 
Público destinatario: estudiantes y profesionales interesados en aplicaciones empresariales construidas con Java.

Capacitación gratuita y abierta al público!

Orador


Adrián Paredes es Ingeniero en Informática de la Facultad de Ingeniería de la UBA. Se desempeña como consultor, arquitecto y desarrollador en Epidata Consulting. Cuenta con 4 años de experiencia en proyectos Java EE y actualmente trabaja en proyectos con productos de JBoss y de Oracle.

Detalles


Martes 15 de Mayo de 2012 
19.00 a 20.30hs
Universidad CAECE - Av. de Mayo 866 (CABA)

martes, 1 de mayo de 2012

Reference Card de Weld

Siguiendo con el tópico del post pasado: CDI (JSR-299), el Contenedor de Contextos e Inyección de Dependencia (Java Contexts and Dependency Injection for the Java EE platform), comparto en esta entrada dos referencias excelentes para aprender CDI y Weld, la implementación de referencia de CDI:
Una de las cosas que sorprende de Weld es que puede funcionar standalone, sin necesidad de ningún tipo de servidor. Esto es fascinante, ya que en una aplicación Java SE podemos contar con un inyector de dependencias. La documentación aclara que hay contextos que no estarán disponibles, como Session o Request, algo que es lógico. También puede funcionar en un contenedor de Servlets, como Tomcat o Jetty.

La reference card hace referencia a tres arquetipos Maven (ninguno es el que usamos en el post anterior):
  • weld-jsf-servlet-minimal: crea una aplicación web que usa Weld y JSF 2.0 (JSR-314)
  • weld-jsf-jee-minimal: crea una aplicación web que usa Weld, EJB 3.1 (JSR-318) y JSF 2.0 (JSR-314), pero sin persistencia
  • weld-jsf-jee: crea una aplicación web que usa Weld, EJB 3.1 (JSR-318), JSF 2.0 (JSR-314) y JPA 2.0 (JSR-317) para la persistencia
Comparado con el arquetipo jboss-javaee6-webapp que habíamos visto, la aplicación que crea weld-jsf-jee es un poco más pequeña. Claro, el primero muestra un ejemplo más completo, incluso exponiendo un servicio REST con JAX-RS 1.1 (JSR-311).

Otra de las cosas que sorprende, por lo menos a mí que vengo de trabajar bastante con Seam 2, es que no hace falta ninguna anotación ni configuración extra para que una clase Java normal sea considerada como un Bean para el CDI. La única condición de Weld es que exista un archivo beans.xml en el META-INF del EAR o en el WEB-INF del WAR. En este xml se pueden declarar interceptores, decoradores e implementaciones alternativas de interfaces para cambiar en tiempo de despliegue. El archivo puede estar vacío.


Como en Seam, dependiendo del tipo de componente Java EE que sea (Entidad, EJB, Managed Bean de JSF, Spring Bean), tomara un scope u otro por defecto (si no se le especifica).

Los scopes que CDI provee son:
  • @RequestScoped
  • @ConversationScoped
  • @SessionScoped
  • @ApplicationScoped
  • @Dependent
Voy a echar en falta el contexto PAGE (o VIEW como se llama en JSF 2.0). Yo lo usaba bastante. No sé si lo provee Seam 3. De todas formas, todo apunta a que se use bastante el scope Conversation, que parece mucho más sencillo de utilizar que en Seam 2.

Es claro que habrá un antes y un después de CDI en el mundo de Java EE. El @Inject es demasiado simple de usar y, como dicen los españoles: mola demasiado.

Para cerrar, les cuento que estaré dando una charla de Java EE 6 que se llamará justamente Java EE 6 In Action. La charla será en la Universidad CAECE el 15 de mayo a las 19hs, con duración estimada de una hora y media. Todavía no fue lanzada la propaganda oficial. Cuando lo esté, supongo que durante esta semana o la próxima, la linkearé en este blog.

domingo, 15 de abril de 2012

Weld y Arquetipo de Maven para JBoss 7

Con este post voy a dar comienzo a una serie de entradas que en este blog etiquetaré como Java EE 6 in Action, y que espejaré, como vengo haciendo últimamente en mi otro blog Tecnologías Java, para facilitar las búsquedas.

Mi objetivo es que juntos nos vayamos adentrando en el mundo de Java EE 6 (JSR-316) de la forma más ágil posible. La especificación de la nueva plataforma empresarial de Java se lanzó en diciembre de 2009. Si bien hace tiempo que ya está disponible la implementación de referencia, Glassfish 3, las empresas todavía no han adoptado completamente este estándar (por lo menos acá en Argentina), y es lógico, ya que sería una pésima estrategia migrar todo el software construido cada vez que hay una nueva actualización.

Pero es razonable esperar que los nuevos desarrollos comiencen a construirse sobre esta plataforma.

I - CDI y Weld

Vamos a comenzar con la especificación estrella, la nueva niña mimada de Java EE: CDI (JSR-299), el Contenedor de Contextos e Inyección de Dependencia (Java Contexts and Dependency Injection for the Java EE platform).

Wallpaper de Weld hecho por la comunidad de JBoss.
CDI fue influenciado por varios frameworks Java de inyección de dependencia como Seam, Guice y Spring. Con tantas herramientas dando vuelta era necesaria una especificación y la JCP se encargó de que CDI fuera más typesafe que Seam, más stateful y menos XML-centric que Spring, y mejor preparado para aplicaciones enterprise que Google Guice.

CDI es un contenedor liviano (aunque el adjetivo "liviano" está empezando a deprecarse) que provee servicios para:
  • Manejar el ciclo de vida de objetos stateful, asociados a contextos bien definidos
  • Inyección de dependencia typesafe
  • Interacción entre objetos mediante notificación de eventos
  • Interceptores de objetos para implementar orientación a aspectos (mucho mejor diseñado que los interceptores de EJB 3.0)
  • una SPI (service provider interface) para desarrollar extensiones portables
Weld es la implementación de referencia de CDI y, a la vez, el core de Seam 3. Seam 3, de JBoss, pasó a ser un conjunto de módulos que extienden las funcionalidades de CDI a través de la SPI provista por el estándar. No es el único. Hay otras extensiones menos conocidas como CODI, de Apache MyFaces, o CDI Source. Y la buena noticia es que la historia se repite. Las extensiones de CDI van camino a la unificación (probablemente para que el día de mañana formen parte de nuevas especificaciones). La semana pasada, InfoQ publicó una entrevista a Pete Muir, donde cuenta que se está incubando un nuevo proyecto en Apache que ya va por su release 0.1. DeltaSpike, como se llama el proyecto, es una fusión entre Seam 3 y CODI con el fin de tomar lo mejor de ambos mundos. Muir tiene la esperanza de que en el futuro otras extensiones del CDI se quieran unir a la fiesta.

II - Arquetipo de Maven para Weld

Para comenzar, qué mejor que tener a mano un código de ejemplo y que además lo podamos ejecutar.

Si descargamos Weld de la página de Seam, la última versión Final publicada a la fecha en la página es la 1.1.6 (aunque ya existe la 1.1.7, con fixes menores, que se subirá a la página en los próximos días), tendremos un zip con las librerías, más varios ejemplos ubicados en la carpeta "examples". Estos ejemplos se pueden seguir con la excelente documentación oficial de Weld. Si usamos Maven podemos usar las librerías que están subidas en los repositorios públicos.

En lo que queda del post, vamos a utilizar un arquetipo para crear todo un proyecto Weld que ya en sí mismo es un ejemplo que incluye un código bastante lindo para comenzar a inspeccionar. Las instrucciones para usar el arquetipo se pueden revisar aquí. El proyecto que genera funciona perfecto para la versión 6.1.0.Final de JBoss AS, pero yo lo voy a aggiornar un poco para que funcione para la versión 7.1.1.Final, la última publicada a la fecha.

El comando que usé para generar el proyecto fue:

mvn archetype:generate -DarchetypeArtifactId=jboss-javaee6-webapp -DarchetypeGroupId=org.jboss.weld.archetypes -DarchetypeVersion=1.0.1.CR2 -DarchetypeRepository=central

La versión de Maven que usé fue la 3.0.3, simplemente porque ya la tenía instalada en mi máquina.

III - Modificando el Proyecto para que Funcione en JBoss 7.1.1.Final


Paso 1: Descargar el JBoss AS 7.7.1.Final:


El JBoss AS se puede descargar de su página oficial. Se puede decir que JBoss AS 7 tiene cambios radicales con respecto a las versiones anteriores. A partir de la versión 7.1.0 implementa todos los perfiles de la especificación de Java EE 6.

Si quieren conocer más de JBoss AS 7 pueden leer el bloque de conocimiento de Epidata Consulting creado por Marcos Reynoso.

Paso 2: Configurar la variable jboss.home:


Si uno configura la variable de entorno JBOSS_HOME en el sistema operativo este cambio no hay que hacerlo. Como en mi rutina diaria utilizo varias versiones de JBoss, yo prefiero no configurar esta variable, ya que me trae problemas. La alternativa es hardcodear la ruta directamente en el mismo pom.xml.

<!-- To specify the JBoss AS directory the "Maven way", set the jboss.home 
property in an active profile in $HOME/.m2/settings.xml -->
<!-- By default, we assign it to the value of the JBOSS_HOME envrionment 
variable -->
<jboss.home>/opt/jboss/jboss-as-7.1.1.Final</jboss.home>

Paso 3: Nuevo Perfil Maven para JBoss 7:


El proyecto viene con cuatro perfiles Maven:

  • default: activo por defecto; funciona para JBoss 6.1.0.Final; por defecto no ejecuta los unit test
  • arq-glassfish-embedded: funciona con un Glassfish 3.1 embebido (standalone); sirve para correr los tests hechos con Arquillian
  • arq-jbossas-remote: sirve para correr los test hecho con Arquillian en un JBoss 6.1.0.Final remoto
  • arq-weld-ee-embedded: funciona con un contenedor Weld embebido; también para correr los tests hechos con Arquillian
Nosotros agregaremos un perfil nuevo llamado jboss7 que, tras aplicarle los siguientes pasos, quedará de la siguiente forma:

<profile>
 <!-- The default profile skips all tests, though you can tune it to run 
  just unit tests based on a custom pattern -->
 <!-- Seperate profiles are provided for running all tests, including Arquillian 
  tests that execute in the specified container -->
 <id>jboss7</id>
 <dependencies>
  <!-- Java EE 6 API dependency -->
  <!-- This one dependency imports all APIs available for a Java EE 6.0 
   application -->
  <dependency>
   <groupId>org.jboss.spec</groupId>
   <artifactId>jboss-javaee-6.0</artifactId>
   <version>${jboss-javaee6-spec.version}</version>
   <type>pom</type>
   <scope>provided</scope>
  </dependency>
 </dependencies>
 <build>
  <plugins>
   <plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.4.3</version>
    <configuration>
     <skip>true</skip>
    </configuration>
   </plugin>
   <!-- Optional plugin deploys your war to a local JBoss AS container -->
   <!-- To use, set the JBOSS_HOME environment variable (or jboss.home 
    in $HOME/.m2/settings.xml) and run: mvn package jboss:hard-deploy -->
   <plugin>
    <groupId>org.jboss.as.plugins</groupId>
    <artifactId>jboss-as-maven-plugin</artifactId>
    <version>7.1.1.Final</version>
    <executions>
     <execution>
      <id>add-datasource</id>
      <phase>package</phase>
      <goals>
       <goal>add-resource</goal>
      </goals>
      <configuration>
       <address>subsystem=datasources,data-source=java:jboss/myDs</address>
       <resource>
        <enable-resource>true</enable-resource>
        <properties>
         <jndi-name>java:/jdbc/__default</jndi-name>
         <enabled>true</enabled>
         <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
         <driver-class>org.h2.Driver</driver-class>
         <driver-name>h2</driver-name>
         <user-name>sa</user-name>
         <password>sa</password>
         <pool-name>mypool</pool-name>
         <use-java-context>false</use-java-context>
        </properties>
       </resource>
      </configuration>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>
</profile>

Paso 4: Plugin de JBoss 7 para Maven


Lo primero que le hice al perfil fue agregarle el plugin Maven para JBoss 7: jboss-as-maven-plugin, para poder desplegar la aplicación usando el comando jboss-as:deploy.

Paso 5: Aggiornamiento del DataSource


Todo cambió en JBoss AS 7, incluso la forma de escribir un datasource. El datasource para Hypersonic que viene con el proyecto, ubicado en src/main/resources-jbossas/default-ds.xml sirve para JBoss 6 pero no para JBoss 7. Ya que el jboss-as-maven-plugin permite agregar un recurso (como un datasource) en la misma configuración, no vamos a usar el default-ds.xml. Por eso verán que le agregué el goal add-resource a la configuración del plugin.

Paso 6: Deploy


Simplemente ejecutando:

mvn clean install jboss-as:deploy -Pjboss7

Problema con el Nuevo Classloader


Esto realmente no es un problema. Al desplegar, la aplicación tira una excepción de ClassNotFound:

Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority from [Module "org.jboss.logging:main" from local module loader @199836ed (roots: /jboss-as-7.1.1.Final/modules)]

Esta excepción no impide el correcto funcionamiento de la aplicación. Pero resulta visualmente molesto que en el log aparezca este error. Según este thread del foro de JBoss, esto se debe a un bug en el módulo de JBoss Logger y se arregla agregando manualmente los siguientes módulos al archivos $JBOSS_HOME/modules/org/jboss/logging/main/module.xml:

<!-- added these 2 dependencies -->
<module name="org.apache.log4j"/>
<module name="org.slf4j"/>

Si les interesa conocer más del nuevo manejo de classloader de JBoss 7 pueden leer estos artículos:


Paso 7: Ir a la Aplicación


Para terminar y ver la aplicación de ejemplo funcionando, abrimos un navegador web y vamos a la URL: http://localhost:8080/jboss-javaee6-webapp/. Si todo salió bien, deberíamos ver nuestro formulario de registración de miembros hecho con JSF 2.

http://localhost:8080/jboss-javaee6-webapp/

jueves, 5 de abril de 2012

Un Vistazo Rápido a Arquillian

A través de la cuenta de twitter de Dan Allen @mojavelinux, me he enterado la excelente noticia de que esta excelente Guía de Introducción de Arquillian está disponible a partir de ahora en español. Por ahí se dice que no se puede empezar a escribir pruebas unitarias con Arquillian sin haber leído antes este tutorial. Y es cierto. Así que ya no tenía excusa para probar el flamante framework de JBoss para pruebas de componentes de contenedores.


Como muy bien explica Pablo Felitti en su blog Enterprise Development Ideas, una de las mayores desventajas de usar componentes que se despliegan en contenedores (como EJB, por ejemplo) es que necesitamos levantar el contenedor mismo para probar, ya que el contenedor maneja el ciclo de vida de sus componentes. Levantar un contenedor de EJB, por ejemplo, nos puede consumir mucho tiempo. Esto hace que las pruebas unitarias resulten tediosas para el programador. Muchas veces esto se soluciona de mala manera clasificando las pruebas unitarias que usan EJBs como pruebas de integración y ejecutándolas en una etapa posterior en el ciclo de vida del desarrollo.

Arquillian puede ser una solución para esto. Arquillian nos permite olvidarnos de los mocks, olvidarnos de las chanchadas que hacemos para probar un componente de forma standalone, fuera de su contenedor, y ejecutar pruebas en el ambiente real. Con Arquillian podemos probar un EJB tal cual es, con sus inyecciones de servicios, con su ciclo de vida, en el mismo contenedor, inyectando el componente en el mismo Unit Test, ya que el Unit Test mismo se ejecutará dentro del contenedor.

Seguí el tutorial paso a paso y todo me funcionó de maravilla. El mismo te enseña a crear un proyecto JavaEE 6 de cero usando:
  • Maven (yo en particular usé la versión 3.0.3, que es la que tenía)
  • JavaSE 6
  • JavaEE 6
  • JUnit 4
  • CDI como modelo de programación (contenedor de contexto e inyección de dependencia)
  • Eclipse (opcional; dado que todo el tutorial se puede seguir con otro IDE y usando Maven si se tiene experiencia)
El tutorial comienza de cero, así que no se preocupen si no tienen estas cosas. Lo único que necesitan tener instalado es Apache Maven y conexión a Internet. Hay una parte de la guía en que configura el proyecto Maven usando una herramienta de configuración de proyectos llamada JBoss Forge. Por mi parte tomé el camino más estándar y manual y usé Maven directamente.

A la hora de ejecutar la prueba unitaria, utiliza contenedores embebidos. Esto es una excelente opción para ejecutar rápidamente el test, aunque es mentira que estamos probando en el ambiente real: el ambiente real es el contenedor mismo. La versión embebida del contenedor puede tener distintos bugs o funcionar de forma diferente en algunos casos. De todas formas, repito, es una opción excelente para empezar y probar rápido. Arquillian también permite configurar otros contenedores no embebidos sin cambiar una sola línea de código. La única diferencia es que hay que tenerlos levantados para poder ejecutar los tests.

Los contenedores embebidos con los que la guía prueba son:
  • Weld, la implementación de referencia de CDI
  • JBoss 7 (managed)
  • Glassfish 3 (embedded)
Los tres se configuran en el pom.xml del proyecto mediante perfiles y Maven solito se encarga de descargarlos y Arquillian de activarlos al ejecutar las pruebas, a través de un adaptador para cada contenedor. Arquillian selecciona el contenedor basándose en el adaptador que está disponible en el classpath. Una prueba con Arquillian debe ser ejecutada en cualquier contenedor que es compatible con el modelo de programación utilizado en la prueba (siempre y cuando exista un adaptador de Arquillian para dicho contenedor). Esto significa que el ejemplo del tutorial sólo puede ser corrido en un contenedor CDI como JBoss 6 (o superior), Weld o Glassfish 3 (o superior).

La buena noticia es que en solo diez minutos, siguiendo los pasos, la prueba me ha salido funcionando para los contenedores embebidos. Aquí copio cómo me ha quedado el pom.xml final:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>org.arquillian.example</groupId>
 <artifactId>arquilian-tutorial</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>arquilian-tutorial</name>
 <url>http://maven.apache.org</url>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </plugin>
  </plugins>
 </build>

 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.jboss.arquillian</groupId>
    <artifactId>arquillian-bom</artifactId>
    <version>1.0.0.CR7</version>
    <scope>import</scope>
    <type>pom</type>
   </dependency>
  </dependencies>
 </dependencyManagement>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.8.1</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.jboss.arquillian.junit</groupId>
   <artifactId>arquillian-junit-container</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <profiles>
  <profile>
   <id>arquillian-weld-ee-embedded</id>
   <activation>
    <activeByDefault>true</activeByDefault>
   </activation>
   <dependencies>
    <dependency>
     <groupId>org.jboss.spec</groupId>
     <artifactId>jboss-javaee-6.0</artifactId>
     <version>1.0.0.Final</version>
     <type>pom</type>
     <scope>provided</scope>
    </dependency>
    <dependency>
     <groupId>org.jboss.arquillian.container</groupId>
     <artifactId>arquillian-weld-ee-embedded-1.1</artifactId>
     <version>1.0.0.CR2</version>
     <scope>test</scope>
    </dependency>
    <dependency>
     <groupId>org.jboss.weld</groupId>
     <artifactId>weld-core</artifactId>
     <version>1.1.5.Final</version>
     <scope>test</scope>
    </dependency>
    <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-simple</artifactId>
     <version>1.6.4</version>
     <scope>test</scope>
    </dependency>
   </dependencies>
  </profile>

  <profile>
   <id>arquillian-glassfish-embedded</id>
   <dependencies>
    <dependency>
     <groupId>org.jboss.arquillian.container</groupId>
     <artifactId>arquillian-glassfish-embedded-3.1</artifactId>
     <version>1.0.0.CR2</version>
     <scope>test</scope>
    </dependency>
    <dependency>
     <groupId>org.glassfish.main.extras</groupId>
     <artifactId>glassfish-embedded-all</artifactId>
     <version>3.1.2</version>
     <scope>provided</scope>
    </dependency>
   </dependencies>
  </profile>

  <profile>
   <id>arquillian-jbossas-managed</id>
   <dependencies>
    <dependency>
     <groupId>org.jboss.spec</groupId>
     <artifactId>jboss-javaee-6.0</artifactId>
     <version>1.0.0.Final</version>
     <type>pom</type>
     <scope>provided</scope>
    </dependency>
    <dependency>
     <groupId>org.jboss.as</groupId>
     <artifactId>jboss-as-arquillian-container-managed</artifactId>
     <version>7.0.2.Final</version>
     <scope>test</scope>
    </dependency>
   </dependencies>
  </profile>

 </profiles>

</project>

Si usáramos EJB 3.0, Arquillian podría usarse con un JBoss 5.1 o superior. La configuración es un poco más trabajosa, pero puede funcionar. Si usamos EJB 3.1, con un JBoss 6 o JBoss 7 la configuración es más sencilla.

Otra opción a Arquillian es la que propone Pablo Felitti en este post, donde usa un contenedor embebido de EJB y en la prueba unitaria utiliza la interfaz remota del EJB. En el post, Pablo usa Apache OpenEJB, pero podría usar JBoss Embedded o cualquier otro. Ésta es una excelente opción para cuando se está trabajando con EJB 3.0 (JavaEE 5). Las ventajas que brinda Arquillian frente a este enfoque son:
  • No tener que declarar una interfaz remota para el EJB (si no es necesario)
  • Poder inyectar el EJB en el test de la misma forma en que se haría desde algún otro componente dentro del mismo contenedor (usando la interfaz local)
  • Correr el test dentro del contenedor (en el mismo ambiente) y no en otra máquina virtual standalone remota
Para cerrar y ponerle un poco de humor al post, les comparto este gracioso video, compartido originalmente por Dan Allen en Vimeo, donde Hitler se pone loco porque Arquillian deja al descubierto los bugs de su contenedor.