Logging de los mensajes SOAP con Axis

Cada vez es más común el uso de servicios web para la integración de aplicaciones web de todo tipo con sistemas de backend, que centralizan la autenticación y participación de los usuarios en dichas web. De esa forma, entre otras ventajas obvias, es posible utilizar software de tipo CRM en la parte del backend, y así extraer conclusiones estadísticas o realizar campañas enfocadas a segmentos concretos de usuarios.

Dentro de este contexto, os podéis encontrar en la necesidad de conectar vuestra aplicación con este tipo de servicios web. Como en todo proceso de integración, es vital saber cuándo y dónde se dan los errores. La mayoría de las incidencias se reportarán inicialmente como de la aplicación, puesto que es el frontal que ven los usuarios. Para identificar realmente de dónde vienen y cuál es la causa, lo mejor es hacer logging.

Como sabréis, existen varios motores de servicios web en Java, destacando Axis, Axis2 y CFX (antiguo XFire). Usando Axis y Log4J, obtener un fichero de log diario con todos los mensajes SOAP que la aplicación envía y recibe es tal fácil como configurar Log4J de la siguiente forma:

# Logger for Axis SOAP messages
# Set level DEBUG and point it to soap appender to make a log of all SOAP messages
log4j.logger.org.apache.axis.transport.http.HTTPSender=DEBUG, soap
log4j.additivity.org.apache.axis.transport.http.HTTPSender=false
 
# File roller for SOAP messages
log4j.appender.soap=org.apache.log4j.DailyRollingFileAppender
log4j.appender.soap.File=/var/log/projects/myapp/axis-http-soap.log
log4j.appender.soap.append=true
log4j.appender.soap.DatePattern='.'yyyy-MM-dd
log4j.appender.soap.layout=org.apache.log4j.PatternLayout
log4j.appender.soap.layout.ConversionPattern=%m%n

La clase HTTPSender de Axis hace debug de todos los mensajes SOAP, tanto cabecera como cuerpo, de entrada y de salida. Por lo tanto, configuramos su logger a ese nivel, DEBUG. Además, creamos un appender para el fichero de log que deseamos usar, que se renovará diariamente.
El truco para conseguir que todo este log no acabe también en el appender del logger raíz (que en producción debería estar a nivel INFO, como máximo, y destinado fundamentalmente a capturar errores) es desactivar la aditividad al logger de HTTPSender.

Así, por cada pareja de petición y respuesta SOAP, nos encontraremos algo como esto en el fichero de log:

Enter: HTTPSender::invoke XML sent:
---------------------------------------------------
POST /cfc/login.cfc HTTP/1.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.4 Host: javisjava.com Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 722
 
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:Login
            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
            xmlns:ns1="http://cfc">
            <email xsi:type="xsd:string">usuario@dominio.com</email>
            <contrasena xsi:type="xsd:string">clave</contrasena>
        </ns1:Login>
    </soapenv:Body>
</soapenv:Envelope>
 
HTTP/1.1 200 OK Connection close Date Mon, 01 Sep 2008 10:29:12 GMT
Set-Cookie CFID=5303012;expires=Wed, 25-Aug-2038 10:29:12
GMT;path=/ Set-Cookie JSESSIONID=51851711;expires=Wed, 25-Aug-2018 10:59:21
GMT;path=/ Content-Type text/xml; charset=utf-8
no Content-Length
 
XML received:
-----------------------------------------------
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:LoginResponse
            soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
            xmlns:ns1="http://cfc">
            <LoginReturn xsi:type="xsd:double">112</LoginReturn>
        </ns1:LoginResponse>
    </soapenv:Body>
</soapenv:Envelope>
 
Exit: HTTPDispatchHandler::invoke

Quartz

Quartz es un programador de tareas en Java. Para empezar, hay que decir que J2SE ya viene de serie con soporte para la programación de tareas, gracias a las clases Timer y TimerTask, que son capaces de lanzar un hilo por cada tarea que se ejecuta.
Sin embargo, Quartz va más allá, pues aporta un framework mucho más completo, y con características interesantes, como:

  • Configuración declarativa (ficheros XML o properties), además de programática.
  • Multitud de opciones de programación (por ejemplo, sintaxis tipo cron).
  • Mantenimiento de estado de las tareas.
  • Potente gestión de errores o tareas incompletas recuperables.
  • Disponibilidad de Listeners no intrusivos sobre las tareas, los disparadores o sobre el propio programador.
  • Integración con aplicaciones web vía Servlet o ContextListener.
  • Integración con Spring.
  • Soporte a entorno distribuido (cluster).

Es muy común la necesidad de dar de alta procesos periódicos asociados a una aplicación web. Quartz es especialmente útil precisamente porque elimina la obligación de tener crones de Linux o tareas programadas de Windows, de forma que toda nuestra aplicación, con la funcionalidad completa, reside en el WAR.
Estos son los pasos para dar de alta una tarea en una aplicación web de la forma más sencilla.

  1. Se descarga Quartz, y se introducen en el WEB-INF/lib de la aplicación el JAR del propio Quartz y todos de los que depende (están incluidos en la distribución).
  2. En el fichero web.xml se da de alta un listener, QuartzInitializerListener. Se trata de un ContextListener, que ejecuta automáticamente un método en el arranque de la aplicación (arranca el programador de tareas) y otro en la parada (obviamente, para el programador).

    <web-app ... >
        <display-name>QuartzExample</display-name>
        <listener>
            <listener-class>org.quartz.ee.servlet.QuartzInitializerListener</listener-class>
        </listener>
    </web-app>

     
  3. Una vez arrancado, el programador buscará su configuración. Por defecto, deberá estar en un fichero de nombre quartz.properties en el raíz del classpath (WEB-INF/classes). El contenido de este fichero para una tarea simple, sin gestión del estado, soporte para cluster, etc, sería:

    # Programador #
    org.quartz.scheduler.instanceName = DefaultQuartzScheduler
    org.quartz.scheduler.rmi.export = false
    org.quartz.scheduler.rmi.proxy = false
    org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
    # Hilos #
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount = 10
    org.quartz.threadPool.threadPriority = 5
    org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
    # Almacenamiento #
    org.quartz.jobStore.misfireThreshold = 60000
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
    # Plugins #
    org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.JobInitializationPlugin
    org.quartz.plugin.jobInitializer.overWriteExistingJobs = true
    org.quartz.plugin.jobInitializer.failOnFileNotFound = true
    org.quartz.plugin.jobInitializer.validating=false

     
  4. Las últimas líneas del quartz.properties están configurando un plugin capaz de incorporar las tareas y disparadores de un fichero XML. De nuevo, usaremos convención sobre configuración, de modo que llamaremos a ese fichero quartz_jobs.xml, y también lo situaremos en WEB-INF/classes, con el siguiente contenido:

    <quartz ... >
        <job>
            <job-detail>
                <name>QuartzExampleJob</name>
                <group>ExampleGroup</group>
                <description>ExampleJob</description>
                <job-class>com.javisjava.quartz.jobs.QuartzExampleJob</job-class>
                <job-data-map allows-transient-data="false">
                    <entry>
                        <key>nombre</key>
                        <value>Javier</value>
                    </entry>
                </job-data-map>
            </job-detail>
            <trigger>
                <cron>
                    <name>QuartzExampleTrigger</name>
                    <group>ExampleTriggerGroup</group>
                    <job-name>QuartzExampleJob</job-name>
                    <job-group>ExampleGroup</job-group>
                    <!-- Se dispara cada 10 segundos -->
                    <cron-expression>0/10 * * * * ?</cron-expression>
                </cron>
            </trigger>
        </job>
    </quartz>

    Este XML indica que debe ejecutarse la tarea definida en la clase QuartzExampleJob, con un parámetro de configuración de clave nombre y valor Javier. La tarea se ejecutará según el calendario definido en el disparador de tipo cron QuartzExampleTrigger (cada 10 segundos).

  5. Las clases que contienen las tareas deben implementar la interfaz org.quartz.Job, que sólo contiene el método execute. Éste es nuestro ejemplo, que lanza un mensaje en la consola, apoyado en el parámetro que se le pasa en el XML (pueden ser múltiples parámetros, mientras su clave sea distinta).

    package com.javisjava.quartz.jobs;
     
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
     
    public class QuartzExampleJob implements Job {
     
        public void execute(JobExecutionContext context) throws JobExecutionException {
            System.out.println("Hola "
                + context.getJobDetail().getJobDataMap().getString("nombre"));
        }
     
    }

     
  6. Al arrancar la aplicación web, aparecerá “Hola Javier” en la consola del contenedor cada 10 segundos.

Os dejo un WAR totalmente funcional que incluye el código para poder modificar la tarea fácilmente.

Como os he dicho, Quartz se puede integrar también en la configuración de Spring, que es el modo recomendado si estáis usando este framework. Hay una sección de la referencia de Spring que cubre cómo hacerlo.

Para profundizar en el manejo de Quartz, acudid a la documentación, o al libro monográfico sobre este framework que ha escrito Chuck Cavaness.

Cómo trabajar con Appfuse Light

Appfuse es una aplicación web base donde el trabajo de conectar todos los frameworks ya está hecho (por Matt Raible, lo que es garantía de bastante calidad). Es muy útil para ciertos proyectos, sobre todo aquellos que tienen gran cantidad de reglas de negocio asociadas a los usuarios y a sus permisos en la aplicación. Sin embargo, para lograr esto, el “pegamento” usado es demasiado fuerte, y es difícil modificar el comportamiento de lo que se conoce como el “core” de Appfuse.
Para aplicaciones más simples, o para controlar más el proceso de desarrollo, existe Appfuse Light. Siempre en torno a Spring como implementación de inyección de dependencias, es posible elegir entre 60 combinaciones de frameworks MVC y de persistencia. Mi preferida actualmente es Struts2 + Spring + iBATIS, aunque espero que se incorpore alguna con JPA (la de Hibernate aún usa la implementación propietaria). A partir de ahí, no es difícil incorporar otras piezas, como URLs amigables con el filtro de tuckey.org, o generación y consumo de formatos de sindicación (como RSS o Atom) con ROME.

Appfuse usa Maven para toda la automatización, desde la compilación y generación del WAR, hasta la ejecución de las pruebas unitarias o de la propia aplicación en un contenedor Jetty. Los pasos a seguir para configurarlo todo con Eclipse son:

  • Descarga la distribución que te interese de todas las combinaciones posibles. En el momento de escribir estas líneas yo uso appfuse-light-struts2-ibatis-1.8.2.zip.
  • Descarga e instala Maven. Necesitarás ciertas variables de entorno:

    • JAVA_HOME apuntando al raíz de la instalación de tu JVM (recomendado 1.5+)
    • M2_HOME apuntando al directorio donde hayas descomprimido / instalado Maven
    • Incluir JAVA_HOME/bin y M2_HOME/bin en la variable ya existente PATH.
  • Descomprime Appfuse Light. Lo mejor es hacerlo dentro de la carpeta workspace de tu Eclipse y luego cambiar el nombre del directorio appfuse-light-struts2-ibatis-1.8.2 al nombre de tu proyecto.
  • Desde la línea de comandos, situado dentro del directorio de tu proyecto, ejecuta:

    mvn eclipse:eclipse

    Maven descargará automáticamente todas las dependencias y configurará un proyecto Eclipse.

  • Arranca Eclipse y haz:
    Import -> Existing projects into workspace
    Selecciona la carpeta de tu proyecto y podrás importarlo.
  • Para que funcione, dentro de Eclipse:
    Window -> Preferences -> Java -> Build path -> Classpath variables
    y añade una de nombre M2_REPO que apunte al repositorio Maven local. Si no has cambaido la configuración por defecto, éste se encuentra en
    C:\Documents and Settings\[nombre usuario Windows]\.m2\repository
    en Windows, y
    /home/[nombre usuario Linux]/.m2/repository
    en Linux.
    Eclipse te dirá que debe recontruir todo el workspace. Acéptalo y ya tienes tu proyecto funcionando en Eclipse.
    [Este último paso también se puede realizar con Maven, pero así se puede ver más claramente cómo está funcionando todo.]

La forma más fácil de ejecutar el proyecto en local es con Jetty. En la línea de comandos, desde la carpeta de proyecto

mvn jetty:run

En la configuración por defecto, la aplicación estará disponible en
http://localhost:8080

Si prefieres darle un nombre no vacío al contexto, id a la configuración del plugin de Jetty en el fichero pom.xml y cambiad la barra en

<contextPath>/</contextPath>

por el nombre que quieras (comenzando por barra, claro).

Para hacer debug con Jetty dentro del Eclipse (que es una pasada, porque va mucho mejor que con Tomcat), sigue este artículo.

Funcionan las fases del ciclo de vida por defecto de Maven, como:

mvn test

que ejecuta las pruebas JUnit
o

mvn package

que genera el WAR de la aplicación en el directorio target.

En el fichero jdbc.properties se encuentra la configuración del acceso a base de datos, y existen scripts de creación del esquema dentro de la distribución.

Struts y el visionario de iBATIS

Hay que decir que cuando Craig McClanahan liberó Struts en el año 2000, había mejores opciones en cuanto a frameworks MVC open source. A mí me encantó el hecho de que alguien le viese salida al tema de los custom tags de JSP, que llevaba ya tiempo, y prueba de ello es que los dos becarios que trabajaban conmigo en aquel momento realizaron su proyecto de fin de carrera precisamente con esa tecnología.

JSP, que era la presentación soportada, era un estándar, y era fácil encontrar desarrolladores que lo conocieran. Además, el que se constituyera como proyecto Apache garantizaba una comunidad y una seriedad en el soporte y en el roadmap. Por eso triunfó, hasta convertirse en un estándar de facto, y ser el framework web MVC más usado en Java.

Pero hay que decirlo, Struts tenía defectos muy importantes, sobre todo dos. Primero, cada acción solía implicar la creación de dos clases (la acción y el bean de formulario). Segundo, el desarrollo era muy acoplado al framework con acciones que heredaban de sus clases y con métodos que recibían objetos propios de Struts, además de objetos request, response,… Para evitar el acoplamiento, había que usar algún patrón J2EE, como Business Delegate, para llevar el negocio a zonas de código neutras que pudieran ser reutilizables, y de esa forma poder, por ejemplo, publicar la funcionalidad como servicio web o cambiar la presentación por un GUI Swing o SWT.

Como digo, existían opciones mejores, tales como ActionFramework, que basaba su presentación en plantillas (primero WebMacro y luego también Velocity) y permitía usar componentes Java tipo POJO, reutilizables para varias acciones, cada una asociada a un método distinto. Pero estas opciones tenían una comunidad muy escasa y a menudo estaban desarrolladas por una sola persona.

El creador de iBATIS, Clinton Begin, percibió estas carencias de Struts y las intentó subsanar, con una contribución llamada BeanAction, que no llegó a incorporarse oficialmente al proyecto, pero que él sí utilizó en la aplicación JPetStore que sirve de demo a su framework de persistencia. BeanAction, como su nombre ya sugiere, permite usar una sola clase para hacer de bean de formulario y de acción. Las acciones también se mapean a métodos, de forma que podemos tener una misma clase que gestione el login, el registro, el logout,… todo lo relacionado con los usuarios. El código que queda usando esta capa extra es bastante potable y es de tipo POJO, pues los métodos de acción no reciben argumentos y devuelven un String, que servirá para indicar qué presentar o a qué otra acción redirigir.

He usado BeanAction ya en varias ocasiones, con buenos resultados. Pero también he recibido críticas, de compañeros que no lo veían como “auténtico Struts”. Precisamente yo pensaba que ésa había sido la filosofía de Struts desde el principio, pero que se había perdido en el camino.

Hace menos de un año, los proyectos Struts y Webwork unieron fuerzas, algo que es digno de admiración, pues en el mundo open source muchas veces las vanidades pesan demasiado y es difícil dejarlas a un lado y trabajar por la comunidad. Resultado de ese esfuerzo es Struts 2, un framework más pesado pero también más potente, con una mejor integración con Spring, característica que es básica en la actualidad.
Me alegró mucho ver que Struts 2 presenta exactamente el mismo modelo de acciones que Struts + BeanAction, aunque con más servicios y mayor potencia, como es lógico.
Al final, sí que era “auténtico Struts”.

Independencia

No os asustéis, esto no va de política. Pero sí os recomiendo que seáis lo más independientes posible en los despliegues de las aplicaciones web, sobre todo en producción. Cuanto menos dependas de sistemas externos, mejor. Ahí van algunas recomendaciones:

  • Usad rutas relativas cuando podáis, de manera que los parámetros de configuración sean los absolutamente necesarios.
  • Podéis evitar tener que usar crones o tareas programadas para esos procesos periódicos o batch tan comunes. Utilizad un programador J2EE como Quartz, que hasta soporta entornos distribuidos y de alta disponibilidad.
  • ¿Necesitáis las tan de moda URLs amigables? No llaméis al de sistemas para que configure el mod_rewrite del Apache, usad este filtro en vuestra webapp, que soporta una configuración basada en expresiones regulares (¿Todavía no las manejáis?).
  • Tenéis un montón de entornos distintos, con diferentes configuraciones. Usad los placeholders de la tarea de Ant <replace> (@) en los properties y XMLs, y los sustituís por los valores de cada entorno (local, desarrollo, producción) en la generación automática del war.

En general, a mí lo que me gusta es desplegar un war y que todo funcione sin tener que hacer nada más en los servidores.

Hay un montón de cosas que se pueden hacer para que vuestra vida sea más fácil en los despliegues. Os aseguro que merece la pena invertir tiempo en ellas al principio del desarrollo.

DoubleYou y Anaya

Efectivamente, como muchos ya sabéis, me voy a DoubleYou. Qué puede hacer alguien de Java Enterprise en una agencia interactiva es algo que yo también voy a averiguar. Lo que tenía claro desde hace algún tiempo es que esta gente hace cosas que me gustan y quiero participar. Ya tengo piso en Barcelona y empiezo en semana y media.

Por otra parte, voy a escribir una pequeña guía práctica de JSP para Anaya, en castellano, y que entregaré a finales de enero. El encargo viene gracias a Esteban, que fue autor de la anterior versión y me recomendó para la actualización. Va a ser curioso eso de escribir un libro.

Bueno, procuraré que los próximos artículos vuelvan a ser sobre tecnología.

Cambio de ciudad… y de jefes

Ha sido poco más de un año el que he trabajado en Cómo, pero muy intenso. Las circunstancias de mi marcha de la empresa, voluntaria como lo han sido todas hasta ahora en mi carrera, son muy comentadas. A ello supongo que contribuye la salida casi simultánea de varios compañeros del departamento. No me voy a rebajar a discutir aquí el tema.

La gran aportación a mi vida de este año ha sido el grupo de gente excepcional que he conocido.

El primero es Esteban Trigos, con el que trabajé codo con codo en un proyecto para el Real Madrid. Según se acercaba la fecha de entrega, la hora de salida se retrasaba: 12 de la noche, 3 de la madrugada, 5 de la mañana,… hasta que llegó un día en el que ambos nos quedamos sin dormir, non-stop. Esteban se puso a picar Java con el resto del equipo y consiguió la cohesión que permitió que el proyecto llegara a tiempo. Su recompensa fue el descrédito, y su salida no tardó en llegar, como era lógico. Aunque posteriormente hubo momentos con ciertas dosis de esperanza, siempre supe que acabaría igual que él.
Esteban es ahora el director de tecnología de Territorio Creativo.

Luego estuvo Antonio Rivera, el “diseñador molón”, que sabe un montón de tecnología. En ese mismo proyecto, una vez acabada su parte, el tío se quedaba con nosotros hasta las tantas, haciendo gracias y manteniendo la moral del equipo. La verdad es que nos echamos unas buenas risas. Es una persona con unas capacidades enormes para todo lo interactivo. Tan pronto te hace una línea gráfica, como un funcional, o te monta el negocio, o va donde el cliente a vender. Actualmente es el director creativo de Cómo, y su aportación en los proyectos clave ha sido crucial.

Mis compañeros Alicia Trigos y Juande Santaella son dos auténticos currantes del código, siempre interesados en aprender y en hacer las cosas bien. Si de algo puedo estar orgulloso de mi paso por Cómo, es de que ellos consideren que han aprendido algunas cosas conmigo. Se marchan a Indra, donde estoy seguro que su aportación será grande, y espero que sea valorada.

Luis Pabón, el hombre tranquilo, es todo un señor, una persona digna de ser admirada, no sólo por su talento y conocimientos, que son grandes, sino por su forma de ser y su manera de comportarse. Ha sido un auténtico privilegio haber podido trabajar con él. Se establece de forma autónoma (con otros compañeros), como Metagrama. Una opción a tener muy en cuenta en desarrollos servidor PHP, J2EE y .NET (argh).

En esta etapa he tenido la oportunidad de conocer a muchas otras personas, como Borja Delgado, Ruth Benito, Carolina Vigara o la gente de Constela Networks (Miguel, Fernando y Álex) y de GOA (David, Rafa y Jose Manuel). Aunque parezca raro, puedo decir que he hecho auténticos amigos gracias al trabajo.

Ahora me marcho, y aunque he tenido muchas opciones en Madrid, me voy a Barcelona, a trabajar en una (la) agencia de publicidad interactiva. Estoy seguro de que será una experiencia muy interesante.

Balance de Webelopers

A petición popular…

Tenía unas ganas locas de oír hablar a Borja Delgado, en su ponencia sobre “Estándares web, integración de tecnologías y accesibilidad”. Le conozco desde hace más de un año, y como he trabajado con él, sé bien de sus opiniones, pero me encantó poder escuchar por fin una presentación como la que hizo. Soy un auténtico fan de este tío, como profesional y como persona.

A día de hoy, lo complicado del AJAX accesible, sobre todo en lo que se refiere a la actualización parcial de una página, es la replicación de acciones en servidor (una AJAX que recargue la zona y una normal que actualice toda la página). Borja no se hace una idea del esfuerzo y tedio que supone eso ahora mismo. Pero hay que darle la razón; la pelota está en el tejado del lado servidor y de los frameworks AJAX que funcionan a través de etiquetas JSP.
También es verdad, no obstante, que la gente que desarrolla los lectores de pantalla igual tiene que ponerse un poco las pilas, y trabajar junto con los desarrolladores web para estandarizar mecanismos de notificación y localización de actualizaciones del contenido de las páginas.

Por lo que contó Sergio Gil, en Rails ya tienen solucionado el problema, y una misma pieza de software gestiona las peticiones AJAX de actualización parcial, y las normales. Otro punto para Rails.
Pero lo que más me gustó de lo que nos contó Sergio sobre el framework fue el hecho de que se recompense por seguir las convenciones establecidas. Muy interesante su ponencia.

Después de ver las dos anteriores, me di cuenta de que yo no había puesto referencias de ningún tipo. Supongo que la sensación habrá sido de “esto es así porque lo digo yo”. Como ya me imaginaba, el tiempo se me quedó corto, y eso que me había concentrado en sólo citar una serie de recomendaciones y productos. Quizás a alguien le pueda ser útil (eso espero) para profundizar a partir de la presentación, que estará disponible en breve en Webelopers, con algún extra que voy a añadir sobre integración de aplicaciones. Por cierto, si la presentación era gráficamente potable, se lo debo a mi amigo Antonio Rivera. No os creeríais que es diseñador si le oís hablar de tecnología.
Lo que está claro es que como proselitista soy un fracaso, por lo menos a raíz del título del artículo de Webelopers que comenta mi ponencia: “J2EE, una alternativa más a tener en cuenta”.
J2EE es la opción, las alternativas son las demás. ;-P

La charla de Nacho Rapallo fue genial. Supo gestionar uno de los peores horarios y nos regaló un muy buen rato con sus ideas, sus anécdotas,… Sólo llevó unas pocas diapositivas con los conceptos clave, y a partir de ahí fue capaz de hilvanar toda una hora de reflexiones interesantes y divertidas. Yo de mayor quiero ser como tú, Nacho.
Ahora que la línea de tiempo de Flash es tan criticada por los programadores ActionScript que se apoyan en desarrollo orientado a objetos y MVC, Nacho la defendió usando como argumento el hecho de que el tiempo pasa en la web, que es una magnitud que debería estar presente. Simplemente brillante.

Las mesas redondas fueron interesantes, sobre todo la primera, donde los directores generales de cuatro empresas del mundo interactivo dieron sus opiniones acerca de los temas que les iba proponiendo el moderador, nada menos que Mariano Klein. Cómo el nombre Web 2.0™ ayuda a vender, cuál es el nivel de conocimiento tecnológico de los clientes y su evolución, etc. Algunos de los participantes creo que se dejaron llevar por la dificultad actual para encontrar a profesionales (yo también la he vivido) y dijeron cosas que no sentaron bien a los desarrolladores allí presentes. Borja, como siempre un tío de profundas convicciones, intervino en el turno de preguntas y les repartió un poco de cera. Bravo por él.

La organización de Webelopers fue muy buena. Hubo problemas técnicos, como en todos los eventos de este tipo (los hubo mayores en el Google Developer Day y en el MadInSpain), pero con la ayuda de la gente de la Escuela, y con la adaptación de las ponencias, todo salió bastante bien. Hubo cafés y zumos con bollos. A los ponentes nos trataron de fábula y toda la gente que asistió coincidía en señalarlo como un éxito.

Ahora entonces viene mi sorpresa y cierta indignación. ¿Cómo se puede entender que haya sitios vacíos en un evento así, y que además era gratuito? ¿Qué narices pasa con la comunidad de desarrolladores y con los estudiantes? Había mil razones para asistir: el nivel de las ponencias, la mera presencia de los directores de las agencias y de Mariano, hasta los créditos que se otorgaban por asistir. La verdad es que me parece inconcebible que no se llenara ya con personal de las propias empresas del mundillo. Y no vale la excusa de que la gente no se había enterado de que se celebraba porque no es verdad. La promoción que realizaron los organizadores fue más que suficiente.
En realidad no es nada nuevo, la JavaExpo ya murió el año pasado, y llevaba años con un número de visitantes decreciente. Supongo que seguiré envidiando cómo en el mundo del grafismo, la publicidad, etc. sí que saben entender el valor que tienen estos eventos.

Lo único que puedo decir es que la gente de Territorio Creativo, en especial Juan Luis y Esteban, han realizado un esfuerzo enorme en la organización, y sólo puedo felicitarles por el éxito, agradecerles que quisieran contar conmigo, y ofrecerles mi ayuda para cualquier iniciativa futura (aunque sea para cargar con cajas, ahora que ya conocen mi capacidad para aburrir a la gente cuando hablo).
¡Ánimo!

Web 2.0™ es una marca registrada de O’Reilly Media, Inc. Todos los derechos reservados.

Webelopers, encuentro de desarrolladores

El día 17 de octubre, la gente de Territorio Creativo organiza Webelopers, un encuentro tecnológico con una serie de ponencias por la mañana, y una mesa redonda después de comer.

Tengo el honor de haber sido invitado como ponente, y me han pedido que hable de desarrollo web con J2EE durante una hora. Eso haré, pero también opinaré sobre cuál es el perfil del programador Java que más aporta hoy en día.

Será en la Universidad Politécnica en Madrid y os podéis apuntar sin problemas, es gratuito.

iBATIS vs Hibernate

La mayor parte las diferencias entre Hibernate e iBATIS provienen del hecho de que el último basa su funcionamiento en el mapeo de sentencias SQL que se incluyen en ficheros XML. Eso significa que, al contrario que Hibernate, requiere conocimiento de SQL por parte del programador. Por otra parte, permite la optimización de las consultas, ya sea con lenguaje estándar o con SQL propietario del motor de base de datos utilizado. Con iBATIS, siempre se sabe lo que se está ejecutando en la base de datos, y tiene herramientas para evitar el problema de las “N + 1 consultas” y para generar consultas dinámicas muy potentes.

Cuando el modelo de datos es muy cambiante o es preexistente al desarrollo de la aplicación (y compartido con otras), iBATIS es un claro caso de uso. También lo es cuando las relaciones entre las entidades del modelo son muy complicadas, porque con algo de trabajo se puede conseguir que el número de consultas que se pasan a la base de datos no sea excesivo, sobre todo en los listados descriptivos.

iBATIS ha ganado peso en la comunidad, hasta llegar a incorporarse al proyecto Apache, y su autor ha publicado un libro monográfico del producto en la serie “in action” de Manning.

Uno de los puntos fuertes de iBATIS es la estabilidad y la facilidad para encontrar dónde está el problema. Las transacciones y las cachés funcionan sin dar dolores de cabeza.

Un colega que trabajaba con Hibernate vino a hacer un proyecto con nosotros. No conocía iBATIS, y al principio estaba receloso, porque veía que tenía que bajar siempre hasta la SQL. Ahora lo usan en su empresa y cuando le pregunté por ello me dijo:

Tronco… he sufrido mucho con Hibernate desde que nos conocimos… demasiado poltergeist, demasiado problema con las transacciones y con las sesiones muertas… demasiado trabajo para optimizar.

Como dijo aquel: ¡que razón tenías¡ :D

Soy más feliz ahora… aunque se curre más… por lo menos cuando hay un problema se ve claro donde está.