May 13

Tutorial de java ee

Con el tema de JSF, estoy leyendo poco a poco, en las idas y venidas en tren al trabajo, el tutorial de java ee de sun. No, no te asustes, no me estoy leyendo las mil y pico páginas. Sólo el capítulo de JSF.

Las primeras páginas del capítulo me parecieron más o menos bien. No tenía ni idea de JSF y leyendo me he ido enterando. Pero según avanzo en el capítulo, cada vez me gusta menos el tutorial. Me da la impresión de que van repitiendo una y otra vez lo mismo, a base de pinceladas, pero dando en cada repetición alguna pincelada más. Por llevarlo de forma más cómoda, imprimo treinta o cuarenta hojas, sin encuadernar de ninguna forma y voy leyendo. En más de una ocasión me ha dado la impresión de haberme equivocado de hoja al leer, porque lo que leo me suena haberlo leído ya palabra por palabra. Y resulta que no, simplemente vuelven a repetirlo más adelante y le añaden algo más, un poco más de detalle.

En fin, empieza a resultar repetitivo y algo pesado. Creo que voy a ir saltando a aquellas partes que más me interesen o de las que todavía no he leído nada y dedicarme más a jugar con eclipse, tomcat y compañía.

Apr 16

Jugando con javadocx

Javadocx es una librería java que permite generar documentos docx

 La gente de javadocx se puso en contacto conmigo a través de twitter. Querían que publicara una nota de prensa que anunciaba el lanzamiento de la versión 2.0. Así que me decidí primero a probar un poco la librería e incluso hacer algún pequeño tutorial en la Chuwiki si se terciaba.

La librería se baja en forma de fuentes java que necesitamos compilar con ant. Así que me descargué también ant, ya que hace tiempo que reemplacé su uso por maven y no lo tenía instalado. El compilado fue bien a la primera, salvo por unos pequeños warnings relativos a algo de unos caracteres extraños de un idioma extraño. No sé si el warning es importante, pero lo comento más abajo.

Miro la documentación en la página web de javadocx para ver cómo empezar. La documentación me remite a los ejemplos java que vienen con la librería, así que me voy a mirarlos. La verdad es que los ejemplos son muy sencillos y al ejecutarlos se genera el docx sin problemas. Casi nada más verlos y ejecutarlos, decidí que no merecía la pena hacer un tutorial en la Chuwiki. El tutorial, de hacerlo, sería prácticamente copiar y pegar esos ejemplos.

Me llevé una pequeña sorpresa al abrir el docx generado con el word. Nada más abrirlo me salen un par de errores, pero aceptando la ventana de error, el documento se abre correctamente. Comentando el problema con la gente de javadocx, me comentan que es un caso raro que pasa con algunas versiones concretas de sistema operativo/máquina virtual java y se debe a caracteres chinos y japoneses que no reconoce correctamente. Qué casualidad, justo los warnings que me dio al compilar. La verdad es que tengo un Windows Vista muy machacado (lleva casi cuatro años instalado) y yo soy un "culo inquieto", por lo que estoy continuamente instalando y desinstalando programas, librerías, herramientas y todo lo que se me ocurre.

Lo otro que he echado de menos es una documentación con las opciones que se pueden poner en los distintos métodos. Me explico. El siguiente ejemplo que viene con la librería genera un docx con un párrafo

CreateDocx docx = new CreateDocx("docx");
String text = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"
+ " sed do eiusmod tempor incididunt ut labore et dolore magna "
+ "aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
+ "ullamco laboris nisi ut aliquip ex ea commodo consequat. "
+ "Duis aute irure dolor in reprehenderit in voluptate velit "
+ "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
+ "occaecat cupidatat non proident, sunt in culpa qui officia "
+ "deserunt mollit anim id est laborum.";
HashMap paramsText = new HashMap();
paramsText.put("b", "single");
paramsText.put("font", "Arial");

docx.addText(text, paramsText);

docx.createDocx("example_text");
 

 Como se puede ver, al addText() se le pasa un paramsText que es un conjunto de parejas clave-valor. Pues bien, no he encontrado en la documentación un listado de qué claves son posibles ni sus valores posibles. Buscándolo, me puse a mirar dentro del código de la librería y he visto que prácticamente esas claves-valor son las que se escriben directamente en el docx. Eso hace pensar que esas claves-valor son propias del formato docx y no de la librería.

Me pongo a investigar el formato docx y veo que un docx no es más que un fichero zip que podemos desempaquetar con winzip, winrar o cualquiera de esas herramientas. Una vez desempaquetado, tenemos un montón de ficheros xml y efectivamente, esas parejas clave-valor forman más o menos parte de los xml.

Resumiendo, una librería muy sencilla de usar y a tener en cuenta si queremos generar desde java este tipo de documentos. La pequeña pega es que necesitaremos conocer o tener una referencia al formato docx para saber exactamente cómo hacer algo que no aparezca tal cual en los ejemplos que vienen.

 

Mar 10

Malditas variables estáticas

En una aplicación más o menos grande y seria de java es normal leer algún fichero con propiedades de configuración para nuestro programa. Esas propiedades suelen ser múltiples y variadas, para módulos de todos los niveles que no tienen nada que ver unos con otros.

Una opción es leer ese fichero de propiedades desde un sitio cercano al main() de nuestra aplicación e ir pasando estas propiedades a los distintos módulos. Si hay módulos en varios niveles, estos deberán ir pasándose las propiedades de unos a otros, ya que el main() posiblemente no pueda acceder directamente a los módulos de bajo nivel.

Para evitar este trasiego de propiedades por todo el código, tiendo a hacer un código java de este estilo

public class FicheroPropiedades {

   private static String pathFicheroPropiedades = "path/fichero.properties";

   private static Properties propiedades = null;

   static {
      propiedades = cargaFichero();
   }

   public static String getProperty (String key) {
      return properties.getProperty(key);
   }
}

Es decir, una clase con todo estático a la que pedir los valores de las propiedades y un inicializador estático de forma que el fichero de propiedades se cargará en cuanto alguien "mencione" esta clase.

Pues bien, esto son todo problemas para los test de JUnit.

Por un lado, posiblemente tengamos o queramos un fichero de propiedades específico para nuestros test. O queramos cambiar alguna propiedad en algún test. Al leer nuestro código bajo test las propiedades de esta clase, es necesario hacerle cosas a esta clase para poder modificarla a gusto. Por ejemplo, poner public el path del fichero para poder cargar un fichero distinto en los test, o poner un cargaFichero(path), o añadir un setProperty() para modificar alguna propiedad concreta, o cualquier otra modificación que se os ocurra. Pero eso no es bonito. No es bonito tener que modificar una clase de nuestro código real para poder manejarla desde los test.

Por otro lado, si tenemos alguna herramienta que ejecuta automáticamente todos los test, es posible que esta clase sólo se inicialice en la ejecución del primer test, manteniendo sus valores para el resto de test. O que al pasar algún test que modifica propiedades, las deje modificadas para el siguiente. En fin, que podemos tener problemas en función de qué test se ejecuten primero, o si añadimos un test nuevo que modifique estas propiedades, puede alterar el resultado de los que van detrás.

Este es otro motivo, además de la mantenibilidad del código, para no usar/acceder a atributos estáticos desde todo el código  si no es realmente necesario. Los test de JUnit pueden hacerse dependientes del orden en que se ejecutan, ya que unos pueden cambiar o no los valores de estas variables estáticas según sus necesidades, incordiando a los que vienen detrás.

Aunque sea un poco rollo a la hora de codificar, suele ser mejor pasar las cosas a cada módulo a traves de métodos set() o en el constructor, aunque sea todo de golpe con un setProperties(Properties), que andar inicializando automáticamente variables estáticas y acceder a ellas desde todos sitios.

Nov 28

La maldición de las herramientas

web services internet Es bastante habitual que la gente que empieza a aprender java (o cualquier otro lenguaje de programación) coja el IDE correspondiente (eclipse, netbeans o el que sea)  y se ponga a aprender. Esos novatos van programando y con el tiempo van cogiendo ciertos conocimientos y experiencia en java. Pero desgraciadamente, el IDE les hace no aprender ciertas cosas básicas. No es raro encontrarse gente que lleva programando algún tiempo pero que sería incapaz de compilar o ejecutar un programa java desde línea de comandos, usando los comandos java, el compilador javac, o generar su jar con el comando jar.

Y esto no solo pasa con las cosas básicas ni sólo con los novatos. Cuanto más complejo sea el tema y más nos resuelva un IDE o una herramienta/framework cualquiera, menos cosas aprendemos de ese tema y más dependemos del IDE/herramienta/framework. Cuento mi caso de hace un par de días.

Llevo ya unos días trabajando con Web Services con jax-ws. Cuando empecé con ello, no me leí la documentación completa (soy un impaciente) y en seguida me puse a buscar ejemplos de aquí y de allí para ir haciendo mi propio código. Leí en la documentación que para hacer un Web Services bastaba con ponerle unas anotaciones a la clase (@WebService, @WebMethod, etc), compilarla de forma normal, pasarle la herramienta wsgen que viene con jax-ws y listo. Pues bien, eso hice, montando todo desde el principio con maven y plugins de maven. Y desde luego, pasando ese wsgen automáticamente en la fase posterior al compilado.

Hace un par de días me decidí a hacer un tutorial sobre la aprendido y quise hacerlo más de forma manual, dependiendo lo menos posible de herramientas (eclipse, maven, etc). Así que me puse a ello … y empezaron las dudas y a ponerse de manifiesto las grandes lagunas en mi conocimiento.

El problema desencadenante de todo es que hice todos los pasos para el tutorial sin usar la herramienta wsgen y el web service me funciona. Una clase con las anotaciones correspondientes, un main() que arranca un EndPoint, no se pasa el wsgen y funciona, arrancado desde línea de comandos.

Bueno, según la documentación, después de pasar el wsgen se hace el war para desplegarlo en Tomcat o similar. Será entonces que si usas EndPoint no necesitas pasar wsgen, quizás EndPoint hace todo eso que hace wsgen de forma automática. Pero lo grave de todo es que sí, se supone que hay que pasar wsgen, pero realmente no sé qué hace wsgen (sí lo sé, genera unos fuentes java que no sé exactamente para qué sirven).

Así que nada, seguiré de forma manual, intentaré montar el "hola mundo" en un tomcat y veré si ahí es necesario o no el wsgen… Y luego a pelearse con la parte del cliente, que aunque también la se hacer con herramientas, tampoco entiendo el fondo de todo.

Nov 24

Winpcap, jpcap y java

 En uno de los proyectos (java) tenía necesidad de tocar uno de los campos que hay en las cabeceras IP de los mensajes, en concreto, el campo de tipo de servicio, que de alguna forma establece prioridades para el mensaje.

Mirando la API de java, veo que la clase Socket tiene un método setTrafficClass() que de alguna manera sirve para cambiar este campo, pero fíjate tú que cosas, hago mis pruebas, arranco un sniffer (Wireshark gratuito) y de todos los bits de ese campo sólo consigo cambiar el segundo. Todos los demás bits siempre se captura con ceros. No es de extrañar, la misma API de java indica que ese método puede o no funcionar dependiendo del "underlying network implementation", así que empiezo a buscar librerías que me faciliten esto.

Al final, el conjunto de librerías a usar es Winpcap + jpcap. La primera es un instalable windows que nos proporciona unas librerías de base (dll) para programar sockets a bajo nivel. La segunda es una librería java que nos facilita las llamadas a la librería Winpcap. Con ambas juntas, podemos programar sockets a bajo nivel desde java con comodidad. Eso sí, hay JNI entre medias aunque no lo veamos al programar.

La aplicación típica que muestra en los ejemplos de esta librería jpcap es la captura de paquetes de red, para hacerse uno su propio sniffer. También permite el envío de paquetes IP, dando valores a todos los campos de la cabecera IP a nuestro gusto. Tras pelearme con ella un par de días, todo parece funcionar bien. Sin embargo, en esos días encontré pegas que ¿cómo no?, pongo aquí. No son pegas de la librería, sino del entorno. Allá van:

  1. Posiblemente se necesitan permisos de administrador para ejecutar nuestro programa si anda manejando las tarjetas de red con la librería jpcap.
  2. En Windows XP hay una variable de registro que debe tener un valor concreto para que nuestro programa tenga permisos para modificar el campo traffic class: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters : "DisableUserTOSSetting"=dword:00000000
  3. Cuando se envía un paquete IP, en el ejemplo pone unas direcciones mac "aleatorias". Para que funcione bien es importante poner direcciones mac correctas. La de origen puede tener o no importancia, dependiendo de si por debajo se nos permite o no enviar cabeceras IP con una mac propia falsa. La de destino debe ser correcta o el mensaje nunca llegará. Se puede poner 255:255:255:255:255:255 si la mac de destino es desconocida.
  4. La mayoría de los routers/switch de la red están configurados por defecto para poner a cero los campos del traffic class de la cabecera IP, por lo que aunque cambiemos esos campos, es muy posible que a destino lleguen como ceros. No es que no funcione la librería, sino que hay que configurar bien los routers/switches.
  5. Así que el sniffer que usemos para ver si todo va como debe, debemos arrancarlo tanto en el PC que envía como en el que recibe. En el que envía podemos ver si hemos rellenado todos los campos como queremos. En el que recibe veremos si ningún router malvado lo ha modificado por el camino.

En fin, que he estado entretenido un par de días.

 

Oct 20

Jugando con Proguard

Candado de código ofuscado Estos días estoy jugando con Proguard, una herramienta que coge nuestro jar en java y realiza básicamente tres tareas: ofuscarlo, optimizarlo y eliminar sobrantes. Por supuesto, estas tareas son independientes y podemos realizar unas sí y otras no a nuestro gusto. Tiene plugin para maven, por lo que si usamos maven, podemos realizar cualquiera de estas tres tareas automáticamente al generar nuestro jar.

Ofuscado

La parte de ofuscado es sencilla, símplemente coge los paquetes, las clases y los métodos y les cambia el nombre por a, b, c, etc. Así, en vez de persona.setId(7), si descompilamos veríamos a.b(7). Es decir, se puede seguir descompilando pero el código es mucho menos claro.

Tiene opciones para decirle qué clases o métodos no debe ofuscar. Son candidatos claros a no ofuscar el método main() de la clase principal e incluso el nombre de esa clase, para que luego la máquina virtual java sepa qué debe ejecutar. Los métodos write() y read(9 de serialización, etc. También, en el caso de que estemos intentando ofuscar una librería, se deben no ofuscar las clases que se usen desde el programa principal.

Curiosamente, proguard es bastante inteligente y tiene en cuenta la relexión de java. Si ve que usamos cosas como Class.forname(), o Class.getDeclaredMethod()…., nos avisa con un error si intentamos ofuscar las clases a las que hace referencia esa reflexión.

Optimizado

Con esto no me he metido a fondo, porque no hay muchas posibilidades de ver qué es lo que hace. Entiendo que limpia nuestro código ineficiente, borrando variables locales no usadas o arreglando cualquier cosa que tenga que ver con la efectividad de nuestro código.

Eliminar sobrantes

Esta es la funcionalidad que no esperaba de la herramienta y que más me ha llamado la atención. Elimina de nuestro jar todas las clases que no usamos y borra todos los métodos que no se usan en el resto de clases. ¿Y cómo sabe si lo usamos o no?. Pues por la clase que le hemos dicho que contiene el main(). Empieza a tirar de ahí y borra todo lo que no se use. El resultado es que en muchas ocasiones obtendremos un jar mucho más pequeño si llevamos tiempo trabajando en el proyecto y somos reacios a borrar clases y métodos que no se usan "por si acaso me hacen falta más adelante".

Y ya lo máximo, al integralo en maven, el proceso queda totalmente automático, por lo que una vez configurado en nuestro pom.xml, podemos olvidarnos de que usamos esa herramienta y seguir con nuestros comandos de maven típico mvn package, mvn install, mvn deploy, etc. Eso sí, ojo al hacer el javadoc.

Sep 29

jax-ws y maven

 Siguiendo con los web services y yo, he estado probando herramientas como axis2 y jax-ws. Por supuesto, nada me ha funcionado a la primera y llevo casi dos días peleándome con esto para arrancar un "hola mundo"

Con axis2 el problema es que se me ocurrió hacerme mi propia clase de ejemplo, sin copiar la de los tutoriales. Al final descubro que no soporta enumerados de java y qué casualidad, a mí se me había ocurrido poner uno de los métodos con un parámetro enumerado. Una vez conseguido arrancar un servidor y hacerme un cliente, el servidor me da error cuando intento acceder al web service desde el ciente. Ante las pocas pistas que daba el error, decidí dejar axis-2 de momento y probar con jax-ws.

Con jax-ws me cree un proyecto maven y me puse a ello. Pues bien, las dependencias maven teóricas según la documentación son estas https://jax-ws.dev.java.net/guide/Using_JAX_WS_from_Maven.html . Creo el proyecto, arranco el servidor y todo aparentemente correcto. Accedo desde un navegador a http://localhost:8080/MiServicio?WDSL con el que teóricamente debería obtener el fichero WSDL del servicio… y el servidor da error. Buscando el error por google, me encuentro con esto http://forums.java.net/jive/message.jspa?messageID=222799 Parece que la librería sjsxp de la que depende según maven el jax-ws no es correcta y hay que coger la versión 1.0.1 en vez de la 1.0. Así que me toca "tunear" el pom.xml y hacer esta ñapa

 

<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.1.1</version>
<exclusions>
<exclusion>
<groupId>com.sun.xml.stream</groupId>
<artifactId>sjsxp</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.xml.stream</groupId>
<artifactId>sjsxp</artifactId>
<version>1.0.1</version>
</dependency>
Dicho de otra forma, poner la dependencia de jaxws-rt, decirle que no me traiga su sjsxp y luego poner la dependencia del que yo quiero. Esto ha funcionado bien y ya tengo el servidor arrancado. Ahora toca pelearse con el cliente…. espero no tener demasiados problemas. Luego volveré con axis2.
 
Y aunque todavía tengo que probar más, de momento me gusta mucho más jax-ws que axis2. Los scripts de axis2 generan montones de clases que luego tampoco facilitan tanto la creación de un cliente. jax-ws también genera clases, pero parece que son menos y además quedan "ocultas", ya que genera los .class que luego se empaquetan en el war o jar.
 
Lo segundo que no me ha gustado de axis2 es que aparentemente no tiene posibilidad de hacer un main() que arranque un servidor web con los webservices, dependemos de un Tomcat ajeno con una webapp axis2 instalada sobre la que desplegamos nuestros web services. Bueno, sí tiene un servidor, pero según la documentación puede usarse sin garantías, ya que no está soportado. jax-ws permite hacerse un main y publicar el servicio de una forma tan fácil como esta
public static void main(String [] args) {
   Endpoint.publish("http//localhost:8080/MiServicio", new MiWebService());
   // Aqui puedes seguir haciendo cosas.
}
Bueno, no es nada grave si quieres publicar webservices en internet. Pero en mi caso, necesito que el servidor aparte de publicar los webservices, haga más cosas.

Aug 20

Los Web Services y yo

web services Sí, se que ando de vacaciones, pero por suerte para mí, soy de los que todavía les gusta su trabajo y, aunque no estoy trabajando, sí ando "revolviendo" en cosillas que me resultarán útiles más adelante. En concreto, en varios proyectos en los que es posible que participe se usan o se van a usar Web Services. A aprender me toca, sobre todo teniendo en cuenta que es posible que en uno de ellos sea yo el que tome la decisión de qué herramientas/tecnologías usar. Y en ello ando estos días, entre playa y terrazita, leyendo y jugueteando con los Web Services.

Aunque en el proyecto se nos aconseja el uso de .NET, yo soy más partidario de Java, básicamente por tres motivos:

  • Es el lenguaje que conocemos todos los desarrolladores del grupo. De usar .NET, tendríamos un tiempo de aprendizaje mayor: los Web Services y el lenguaje.
  • En Java casi todo es gratis, con el consiguiente ahorro de licencias, tanto de desarrollo como de los servidores.
  • .NET nos limitaría a servidores Windows, mientras que Java nos permitiría desplegar en cualquier servidor, Windows, linux, solaris, …. Sé que está el proyecto MONO, pero no veo la necesidad de meter más complejidad al asunto.

En cualquier caso, no dudo que con .NET se puedan hacer perfectamente Web Services igual que en java, posiblemente más fácilmente integrados con otras cosas de Microsoft, pero no veo ninguna ventaja clara en lo que es estrictamente el lenguaje de uno sobre otro.

El siguiente tema es si SOAP o REST. En principio, por lo que he ido leyendo, me inclino por REST. Aparentemente es más simple y parece ser que es la nueva tendencia. Posiblemente me decida por REST, pero le veo/tengo un par de pegas/dudas.

  • Al ser más nuevo, me da la impresión de que está menos soportado por los servidores/herramientas actuales. Muchas de las herramientas traen como coletilla "soporte para REST". Siempre es un riesgo meterse en algo reciente.
  • De la misma forma, me da la impresión de que toca codificar más. En SOAP creas tu WSDL y aunque no he buscado con detalle, me da la impresión de que hay miles de herramientas que te generan el código tanto de la parte cliente como de la parte servidor para el uso del Web Service definido por ese WSDL. En REST posiblemente haya equivalentes, pero al ser más nuevo, seguro que hay menos o están menos desarrollados. Insisto, no he mirado en serio, es sólo la impresión que me ha dado en una búsqueda superficial.

Otra gran duda es el tipo de librerías a usar para el Web Service. He visto herramientas como Restlet, (es con la que estoy jugando), pero da la impresión de ser algo muy simple para aprendizaje, no tengo muy claro si puede servir para un servidor en producción con fuertes requisitos de seguridad. También hay cosas como JAX-WS o como Jersey, pero el verlos debajo de GlassFish y sobre todo el primero, debajo de Java EE, me da la impresión de que sería matar moscas a cañonazos. Nuestro proyecto sólo tendría unos pocos Web Services y con datos no muy complejos, aunque sí bastante trasiego.

Finalmente, está el tema de elegir servidor, hay cosas como Spring Web Services, Apache Axis 2 o cosas más tradicionales como Jetty, Tomcat o servidores más "bestias" como Glassfish o JBoss. Por un lado, las ganas de aprender me tiran a Spring, pero el irme a algo conocido me tira por Tomcat. Como he comentado, Glassfish o JBoss me parecen excesivos para lo que pretendemos.

En fin, sigo investigando y haciendo pruebas, pero cualquier sugerencia de gente con experiencia por estos lares, es bienvenida.

Jun 30

Curiosidad en java

auto-boxing en javaDe este post del foro, sale un ejemplo curioso de java. Fíjate en el siguiente código

public static void main (String [] args) {
   Integer a = 100;
   Integer b = 100;

   System.out.println(a == b);
}

Pues bien, este ejemplo da como resultado "true". Si cambias los valores de a y b (pero manteniéndolos iguales), verás una cosa curiosa. Para valores entre -128 y 127, el resultado es "true". Para valores fuera de ese rango, el resultado es "false".

El motivo podemos encontrarlo en este post sobre Auto-Boxing del Weblog de Victor Ramirez. Teóricamente las instancias de Integer que se crean de forma más o menos automáticamente en esas asignaciones deberían ser distintas y el == debería dar siempre "false". Pero por eficiencia, el compilador reaprovecha instancias de estas clases, de forma que cuando se hace este tipo de conversión (de un tipo primitivo a un objeto Integer, Boolean, o lo que sea), se tiene que == da "true" en los siguientes casos:

  • Siempre en los Boolean y en los Byte
  • Entre -128 y 127 en los Short e Integer
  • Entre u0000 y u007F en los Character.

Una curiosidad que puede dar muchos quebraderos de cabeza a un programador novato que no tiene muy controlada la diferencia entre el método equals() y el ==.

Jun 21

Mis dudas con Spring para aplicaciones de escritorio

Logo spring frameworkTodos nuestros sistemas se parecen, unos llevan determinados módulos, otros no. Por eso, siempre he estado pensando la forma de hacerlos modulares de forma que sea fácil quitar o poner módulos de un sistema a otro, cada uno con su configuración. Cuando me puse a pensar en ello llegué a la conclusión de que sería buena idea hacer que cada módulo fuera un jar, independiente de los otros. Luego, en un sistema, es cuestión de instanciar y configurar aquellos módulos que nos interesen, trayendo sólo los jar necesarios.

Puesto que los módulos interaccionan entre ellos y cuando uno de ellos quiere hacer algo normalmente necesita datos de otro módulo, o a veces cuando un módulo genera algo necesita avisar a los otros para que sigan el proceso, también me puse a pensar en ello. Una especie de mecanismo de suscripción de eventos, de forma que en algún sitio cerca del main, donde se instancian y configuran módulos, también se hicieran suscripciones a determinados eventos de un módulo y se avisara de ellos a los otros módulos.

Afortunadamente, antes de ponerme a codificar algo como esto, se me ocurrió investigar por internet y me encontré con los contenedores de inversión de control y en concreto con Spring Framework. Aunque el framework está muy pensado para aplicaciones web, está bien diseñado y puedo bajarme y usar sólo el núcleo, lo que me permite a través de ficheros XML instanciar los distintos módulos, configurarlos y hacer que se vean unos a otros. También me proporciona un sistema de publicación y suscripción de eventos entre módulos. Justo lo que quería.

Así que como suelo hacer en estos casos, cogí a un grupo de gente afín a mis ideas peregrinas, les conté lo fácil y bien que podiamos usar Spring Framework en nuestras aplicaciones y lo usamos en uno de los proyectos que empezaban. La experiencia fue buena y todos quedamos bastante contentos en general, así que decidimos ir aplicándolo a más proyectos.

Pero al empezar a usarlo en más proyectos e involucrar a más gente, empecé también a encontrar más oposición y otros puntos de vista. Un compañero mío más crítico que yo con las innovaciones comentó que "Spring no es más que una forma "friky" de hacer news". No obstante, él también andaba buscando una forma de configurar con ficheros sus módulos, ya que se ve repitiendo código de configuración prácticamente igual de un proyecto a otro.

Y el otro día sucedió algo que me ha hecho empezar a dudar de la utilidad de Spring Framework, al menos usando sólo el núcleo y en aplicaciones de escritorio. Este compañero en uno de los proyectos en los que tiene cierta responsabilidad me dijo que se estaban instanciando en Spring dos módulos iguales con configuración distinta, pero que habían cambiado los requisitos y debíamos eliminar uno de ellos y cambiar el otro por un tercero distinto. Nos pusimos a ello.

Borrar uno de los módulos es fácil, sólo hay que ir borrando las referencias en los ficheros XML y en algunos sitios muy concretos del código. Cambiar el otro fue algo más complejo, buscarlo para reemplazarlo, cambiar nombre de clases, parámetros a inicializar, buscar referencias para ver si son compatibles, etc, etc. Una vez que creímos todo estaba hecho, arrancamos la aplicación y nos saltan un par de errores, nos habíamos equivocado en el paquete de una de las clases de un bean de Srping Framework. Más cambios, nueva prueba y nuevo fallo. Esta vez, a la tercera fue la vencida y todo funcionando. Pero mi compañero hizo el comentario que me metió la duda en el cuerpo: "Si en vez de hacer los news y la configuración en ficheros XML los hubieramos hecho en código, todo esto habría cantado en el mismo IDE. Prefiero ver los errores mientras escribo que verlos después arrancando la aplicación".

Y tiene razón, hacer news y configurar en XML tiene la pega de que errores que se verían inmediatamente mientras escribes en el IDE (un new de una clase que no existe por ejemplo, o la llamada a un set para configurar algo) no los vemos hasta que arrancamos la aplicación.

Hay un plugin para eclipse que permite ver si lo que escribes en el XML de Spring es correcto (las clases existen, los métodos existen, etc), pero no lo tenía instalado y lo de que hayan cogido Spring los de SpringSource, me da "mal rollo", parece que se quieren dedicar a cobrar por dar cursos y que este tipo de plugins o incluso las descargas están cada vez más escondidas previo registro.

Instalaré el plugin, miraré la posibilidad de hacer un test de JUnit que verifique que un XML de Spring es correcto y a ver qué pasa. De todas formas, empiezo a pensar que sólo para hacer news no merece la pena. Me queda el tema de los eventos al que sí sacamos partido….