Cambios en en el stack de Amneris (Tiempo de Balances 1)

El stack de Amneris ha sufrido grandes cambios en los últimos meses. Tenemos 3 nuevas incorporaciones, 2 jubilaciones, y un retiro por invalidez :)

En primer lugar damos la bienvenida oficial a Tapestry5 que si bien ya hacia tiempo que estaba dando vueltas por los alrededores, no había sido debidamente presentado. La adopción de Tapestry5 deja a Tapestry4 relegado al mantenimiento de aplicaciones legacy.

De la misma manera que Tapestry4, se retira con honores Trails 1.x, que ya ha cumplido su ciclo, para dejar paso al todavía en desarrollo Trails 2 basado en Tapestry5. Trails 2 está todavía muy lejos de ofrecer todas las prestaciones que ofrece se hermano menor, pero no tiene sentido seguir invirtiendo tiempo en Trails 1 cuando el framework principal en el que se basa está ya completamente obsoleto. Esto conlleva también el esfuerzo de ir migrando de a poco todos nuestros otros frameworks y librerías que se basaban en Trails.

La incorporación de Tapestry5 al stack desplaza también a Spring como framework de IoC por defecto del stack. Spring (a mi parecer) a dejado de innovar en el espacio de la IoC y en estos momentos hay ofertas muchísimo más interesantes como Guice y Tapestry5 IoC. La cantidad de código basado en Spring IoC que tenemos es tal que reemplazarlo no será tarea fácil, pero de ahora en adelante Spring no será la primer alternativa a la hora de implementar IoC en nuestras aplicaciones. Trails2 será completamente independiente de Spring. Completamente compatible SI, pero independiente al fin.

Ya he mencionado la incorporación de Tapestry5 y Trails2 pero el gran fichaje de la temporada es Magnolia CMS. Trails nos estaba quedando un poco chico para según que cosas y necesitábamos incorporar una solución robusta que nos garantizara estabilidad pero con flexibilidad. Magnolia se usa detrás de los sitios de InfoQ y JBoss.org, así que si puede con la carga de esos dos sitios, podrá manejar nuestra carga sin ningún inconveniente. Otra gran característica de Magnolia es la implementación de Java Content Repository (JCR - JSR-170) que nos da una gran tranquilidad respecto de que nuestros datos son almacenados siguiendo un estándar abierto para la gestión de contenido.

Bienvenidos Magnolia, Tapestry5 y Trails 2!

ZTT y Tapestry4

Este es el cuarto en una serie de posts donde hablo de ZTT en mi proceso de desarrollo.

1) Desarrollador ágil JAVA. ¿Oxímoron?
2) ZTT y Tapestry5
3) Matt Raible acerca de ZTT

Live Template Reloading

Tapestry4 tiene un muy promocionado "modo desarrollador" en el cual los cambios en los templates html se reflejan en la aplicación sin necesidad de reiniciar el servidor de aplicaciones.
Basta con agregar -Dorg.apache.tapestry.disable-caching=true al comando de ejecución del servidor de apps.

Si bien esta simple configuración es muy útil, tiene sus inconvenientes. El primero es que recarga todos los templates por cada request, hayan o no sido modificados. Cuando la cantidad de componentes en una página es muy grande (como suele ser mi caso) y cuando la cantidad de requests es mucha (como cuando se utiliza AJAX) la velocidad de respuesta de la aplicación se vuelve intolerable y después de la 5 o 6 recargas de la página suele dar algún que otro problema de memoria.

Una mejor alternativa es habilitar el servicio de reset usando -Dorg.apache.tapestry.enable-reset-service=true. Con este servicio habilitado es posible resetear la caché de templates y el pool de componentes simplemente accediendo a la URL /app?service=reset&page=Home o /reset.svc?page=Home

Existen varias propuestas de mecanismos para facilitarle al programador el acceso al servicio de reset. La opción tradicional es dejar abierto un tab del firefox en esa URL y hacer F5 cada vez que se quiera hacer reset. Andreas Andreu (uno de los commiters de tapestry) propone hacerlo desde un script de greasemonkey. Yo, en cambio, prefiero usar una tarea de ant:


<telnet port="8080" server="localhost" timeout="20">
<read>
<write>GET /reset.svc?page=Home HTTP/1.0</write>
<write></write>
</read>
</telnet>


El servicio de reset está desabilitado por defecto porque en producción podría ser muy fácilmente explotado para obtener una denegación de servicio.
Para habilitar reloading de templates en producción fui un paso más allá de lo documentado y expuse el servicio de reset via JMX (gracias a HiveMind) de tal manera de poder automatizar el reset de la cache tomando las mayores precauciones de seguridad (y así evitar un posible DoS).

hivemodule.xml


<contribution configuration-id="hivemind.EagerLoad">
<load service-id="hivemind.management.MBeanRegistry"/>
</contribution>

<contribution configuration-id="hivemind.management.MBeans">
<mbean service-id="TapestryMBean"/>
</contribution>

<service-point id="TapestryMBean" interface="
org.amneris.tapiz4.jmx.TapestryMBean">
<invoke-factory>
<construct class="org.amneris.tapiz4.jmx.TapestryMBeanImpl">
<set-object property="resetEventHub" value="infrastructure:resetEventHub"/>
</construct>
</invoke-factory>
</service-point>

<contribution style="font-weight: bold; font-style: italic;" id="hivemind.EagerLoad"><load id="hivemind.management.MBeanRegistry"></load></contribution><contribution style="font-weight: bold; font-style: italic;" id="hivemind.management.MBeans"><mbean id="TapestryMBean"></mbean></contribution><service-point style="font-weight: bold; font-style: italic;" id="TapestryMBean" interface="com.amneris.muba.jmx.TapestryMBean"><invoke-factory><construct class="com.amneris.muba.jmx.TapestryMBeanImpl"><set-object property="resetEventHub" value="infrastructure:resetEventHub"></set-object></construct></invoke-factory></service-point>java
import org.apache.tapestry.services.ResetEventHub;

public class TapestryMBeanImpl implements TapestryMBean
{

ResetEventHub resetEventHub;

public void resetTapestryCache()
{
resetEventHub.fireResetEvent();
}

public void setResetEventHub(ResetEventHub resetEventHub)
{
this.resetEventHub = resetEventHub;
}
}


Live Class Reloading

En cuanto a class reloading en Tapestry4, ya comenté en el post anterior que solo conozco 2 alternativas (si alguien de alguna más por favor que me lo comente).

1) Sysdeo tomcat launcher plugin (open source)
2) JavaRebel de ZeroTurnaround (software de pago, altamente recomendado)