jueves, diciembre 28, 2006

Buscando la validación inteligente

La tarea de validar. No sé a ustedes, pero a mí siempre me ha parecido un trabajo repetitivo y aburrido. Tiene que haber una forma de hacerlo fácil y sin codificar demasiadas cosas (sencillo y rápido, básicamente).
He buscado diferentes alternativas para realizar todo este proceso y llegué a la siguiente conclusión. No importa si es una página web o Swing, Apache siempre tiene algo para ayudarte.
En realidad, a todo este proceso lo resumo en 2 formas de validar: A mano o con Jakarta Commons Validator. Y esto, en forma independiente a si se está realizando una aplicación de escritorio o web.
Pero esperen, momento, no se pongan locos y vayan a creer que ya se solucionaron todos los problemas, no se puede escapar completamente de codificar algunas cosas a mano. Por ejemplo, siempre es conveniente poner una máscara a los JTextField o utilizar el calendario DHTML de DynaArch en una página web.
Lo que me gusta de Jakarta Commons es que muy fácil de configurar (XML basado en JavaBeans), muy completo, intuitivo y fácil de extender, lo que hace que sea declarado como un Framework de validación. Lo recomiendo mucho, además si se está programando para la web y se está utilizando algún framework como Struts, sepan que el framework de validación de Struts, es Jakarta Commons Validator. En este útlimo punto no puedo decirles si es mejor o no al entorno de validación de Spring, ya que no lo he analizado a fondo.
Jakarta Commons Validator tiene además, fuentes de validación JavaScript, así que ni siquiera se hace dependiente de validación realizada en el servidor, tranquilamente podemos incorporar estas librerías a nuestra página web y realizar validación (básica, por supuesto) en el Cliente.

Como adelante de algún próximo post, estoy investigando la posibilidad de incorporar al los JavaBeans, validación por medio de Jakarta, pero sin generar ningún documento XML en forma manual, sino a través de las Java annotations. Esto me suena muy interesante, ya que sólo necesitaríamos (en principio) "marcar" los métodos setters con la validación adecuada.


Actualización de último momento!!!
Siempre sucede, cuando parece que después de tanto esfuerzo cerebral, has tenido una buena idea, te dás cuenta de que alguien te gano de mano y que además, lo ha pensado mejor...
Bueno, resulta que existe un proyecto que intenta realizar validaciones de objetos (no sólo de JavaBeans) a través de annotations.
Se llama OVal y pueden encontrarlo en sourceforge.org Parece muy interesante por lo poco que he visto.


Por último, les dejo algunos links interesantes:
Saludos PF

domingo, diciembre 24, 2006

A votar por Java

La revista SYS-CON, en su sección Java Developer Journal (JDJ) está receptando votos para diferentes categorías de productos relacionados con Java, desde el mejor libro hasta el mejor servidor de aplicaciones, pasando por la mejor librería, herramienta de reportes, artículo técnico, IDE, etc.
Lo recomiendo porque es un buen lugar para ponernos al día y ver que otros productos están siendo utilizados en Java. He visto módulos o librerías de clases muy interesantes, aunque pagos, pero también aparecen varias alternativas open-source.

También pueden ver aquí los resultados de la última votación, que salió en este año (2006 todavía), en ella pueden ver a IntelliJ-IDEA como mejor IDE, Bea Web Logic Server como mejor servidor de aplicaciones y a Eclipse como la mejor herramienta de desarrollo en equipo.

Veremos que resultados se obtienen ahora...

Saludos PF

sábado, diciembre 23, 2006

JDK 1.6: La clase SwingWorker con ejemplos

Lo prometido es deuda, así que desarrollaré un pequeño ejemplo para demostrar cómo se utiliza la clase SwingWorker.
El ejemplo más obvio que se me ocurre es el un JProgressBar que de actualice de forma automática.
Existen dos formas de realizarlo, la tradicional (compartir al hilo el JProgressBar) y la nueva, que es utilizando un modelo de eventos para realizar la actualización. Vamos a usar las dos para marcar diferencias.

La imagen de la derecha refleja como se verá el programa andando. Ya pueden intuir que sucederá cuando se haga click en "Start Worker" y en "Cancel Worker". Sin embargo lo importante es cómo se actualizará la barra de progreso y el JLabel de "Completado ...".
Estos dos componentes que se actualizarán tienen aspectos bastante interesantes. El JProgressBar se actualiza en "tiempo real", ya que estará accedido por el SwingWorker directamente (esto es, porque estoy declarando el SwingWorker como "inner class"). En cambio, el JLabel de porcentaje, no será accedido por el SwingWorker, sino que su actualización será parte de un evento. En el siguiente diagrama se puede ver un poco más la interacción de los hilos principales del programa.

Ahora bien, el acceso al JProgressBar no es nada novedoso, de hecho probablemente ya lo hayan hecho antes. Lo novedoso aquí es la aparición del Event Dispatch Thread, quien será el encargado ahora de notificar a un "Listener" que ha cambiado alguna propiedad en el SwingWorker. En nuestro caso, tomaremos una propiedad implícita del SwingWorker llamada progress (de tipo entero, rango 0-100, accedido por setProgress(int) y getProgress()).

Ahora veamos un poco el código fuente de esto. El siguiente fragmento muestra la creación y llamada a ejecución de un SwingWorker (trabajador):



La clase que implementa SwingWorker se llama MiWorker. Es bastante intuitivo, invocando a execute(); se inicia la ejecución del Thread. Pero cuidado, el SwingWorker se ejecutará sólo una vez por más invocaciones que hagamos a execute().
Quiero hacer más hincapié en la inner class PropertyChangeListener. El hilo de manejo de eventos de Java será el encargado de invocar el método propertyChange automáticamente cuando el Worker "dispare" una notificación de que ha cambiado alguna propiedad. Esta propiedad puede ser una designada por nosotros (en cuyo caso deberemos invocar a firePropertyChange() en nuestro código) o podemos usar alguna de las 2 propiedades designadas por defecto (progress y state). En este último caso, el mismo worker dispara la notificación al hilo de eventos para que este notifique (asincrónicamente) a los listeners.




En este fragmento se describe la inner class MiWorker. Es aquí donde se realiza todo el proceso. Es nuestro hilo de ejecución. Sólo 1 método es estrictamente requerido, el doInBackGround() quien será el encargado de realizar todo el procesamiento. Eso que ven en la declaración de la clase () es lo que se conoce como Generics, una muy buena utilidad incorporada en la versión 1.5 del JDK. Les recomiendo leer más acerca de este tema en The Java Tutorial.
Si se fijan, estoy accediendo en forma directa al JProgressBar (ojo, esto es posible porque MiWorker es una inner class), sin embargo, no accedo al JLabel. El cambio de este componente se dará de forma asíncrona cuando se invoca una y otra vez a setProgress. Esto está bueno porque no necesariamente se notificará al Listener una y otra vez. Por ejemplo, si se ejecuta muchas veces se notificará el progreso 1, el 2,3,4 pasarán de largo y se notificará el 5, etc..

Ya no puedo extenderme más, así que espero que les sirva, les dejo los fuentes en el siguiente link: worker.rar (6Kb)

Saludos PF

lunes, diciembre 18, 2006

JDK 1.6: La clase SwingWorker

En principio, esta clase no es completamente nueva (de hecho, estaba creada de manera separada al JDK -aquí pueden ver la antigua versión-). Pero en la última versión del JDK, ya la encontramos como parte integrante del paquete javax.swing. El objetivo de esta clase es la de implementar en un hilo/thread separado, cualquier funcionalidad que pudiera requerir mucho consumo de tiempo. Así por ejemplo, podríamos tener un worker que cargara imágenes para crear una animación dentro de un applet, o un worker que actualizara componentes en pantalla.
Es sumamente útil para crear aplicaciones de escritorio que no se queden "tildadas" mientras el programa realiza alguna operación de larga duración.
Describiré en este post cómo funciona esta clase. En el próximo mostraré un ejemplo andando:

La clase SwingWorker es una clase abstracta, lo que significa que para usarla, deberemos o bien, crear una nueva clase que herede funcionalidad o crear una clase interna (generalmente, el más usado y recomendable por el acceso que nos da al resto de los componentes visuales). La figura nos muestra también, que esta clase no extiende de ninguna otra, sino que implementa 3 interfaces. Evidentemente la interfaz Runnable sirve para que esta clase se comporte como un hilo de ejecución. La interfaz Future sirve para retornar un resultado de alguna computación asincrónica (es decir, esperar hasta que se complete una operación y se pueda retornar el resultado). Por último, la interfaz RunnableFuture sirve para asociar un Future con el método run().

No hay que olvidar que un SwingWorker es un hilo de ejecución. Esto significa que deberemos tener el mismo cuidado que tendríamos al escribir cualquier hilo de ejecución.
Sin embargo, hay ciertas propiedades que hacen de esta clase, un poco más especial. Por ejemplo, un Worker se ejecuta sólo una vez. Por más de que llamemos al método de ejecución una y otra vez, esto no hará que se ejecute como un hilo de ejecución aparte.
Además, el SwingWorker, puede interactuar con el resto de la aplicación por medio de eventos. Esto es importante, porque pasamos responsabilidad al Event Dispatch Thread de Java (este hilo es cargado automáticamente por cualquier aplicación visual de Java y es el encargado de manejar todos loa eventos visuales que se produzcan).

Funcionamiento

Bien, como la clase SwingWorker es abstracta, significa que deberemos sobrescribir algunos de sus métodos.
El principal y más importante de estos métodos es el T doInBackGround() throws Exception Recuerden que la T proviene de Generics y simboliza un tipo de datos. Podrían considerar a este método como el run() de la clase Thread. El objetivo de este método es el de ejecutar todas las operaciones de alto costo de tiempo. En definitiva, aquí deberemos escribir todo el procesamiento.
Existe otro método necesario, void done() Este método será invocado por el Event Dispatch Thread automáticamente cuando doInBackGround() termine su ejecución. No es un método de finalización en sí, pero nos sirve para realizar acciones de completado de nuestro worker.
Por último, existe el método public final void execute() Este método sirve para dar el puntapié inicial a nuestro worker. Si lo comparamos con la clase Thread, sería el start() de nuestro hilo.

En el siguiente gráfico, se ve en líneas generales el contexto de un worker. Los métodos publish() y process() sirven para interactuar en forma asíncrona con el resto de la aplicación (aplicando una versión del patrón publicar-suscribir)
En el próximo post, mostraré un ejemplo concreto.


Saludos PF

viernes, diciembre 15, 2006

JDK 1.6: Ordenando por columnas un JTable

Para los que no se enteraron o los que no recuerdan, cuando queríamos tener un JTable que se pudiera ordenar si el usuario presionaba sobre la cabecera de una columna, teníamos que (en líneas generales):

  • Captar el evento del mouse cuando se hacía click en la cabecera de la columna.
  • Crear un TableModel apropiado que pudiera ordenar los elementos.
  • Sobrescribir los métodos del TableModel para que fuera consecuente con nuestros deseos.
  • Rezar tres oraciones para que lo hubiéramos escrito bien.
El procedimiento para hacerlo todavía lo pueden ver en The Java Tutorial.

Bueno, el sufrimiento para ordenar un JTable ha terminado!!!!
En la última versión de Java, uno de las nuevas cualidades de los JTable, es que se pueden ordenar con muy poco trabajo, tan poco, que se reduce a una sola línea de código para ordenaciones simples. Por ejemplo:

jTable = new JTable(datos, cols);
jTable.setAutoCreateRowSorter(true);


La primera línea es conocida por todos, con ella creamos un nuevo objeto "Grilla". La novedad viene en la seguna línea, este método fue agregado en esta nueva versión de Java y permite que se cree automáticamente un objeto (interno) para la ordenación de la grilla.

Si se necesitara hacer algo más personalizado, Java nos brinda nuevos objetos para la ordenación, entre ellos: RowSorter (abstracta) y TableRowSorter (implementación de RowSorter).
Lo único que deberemos tener en cuenta es en el proceso de selección de filas. Debido a que el índice de una fila seleccionada se basa en el índice "visual" y no en el índice del modelo, se necesita realizar una "conversión" de índices. Pero no se pongan nerviosos, ya que esta conversión la lleva a cabo el mismo objeto JTable, simplemente invocando al método convertoRowIndexToModel(int index).

Seguramente muchos vamos a disfrutar esta nueva opción del JDK 1.6. Seguiré investigando un poco más acerca de la nuevas funcionalidades de esta versión y después les cuento.

Saludos PF

martes, diciembre 12, 2006

Sun se calza el traje de Papá Noel y te regala...

Ayer finalmente ha salido la nueva versión del JDK (1.6) de Java (Mustang). Si han estado visitando los últimos meses la página oficial de Java (www.java.sun.com), ya habrán visto varios artículos relacionados con esta nueva versión. De todos modos, voy a listar algunas de las novedades que se trae esta nueva versión. En posteriores artículos (cuando me ponga a estudiarlo a fondo), detallaré más sobre las nuevas cualidades.

Integración con Servicios Web:
  • Ahora tendremos una nueva API para firmas digitales XML.
  • APIs para JAX-WS integrada.
  • Nuevo soporte para JAXB 2.0 (Java Architecture for XML Binding).
Soporte para lenguajes de scripting:

Esta parte es una de las más interesantes, básicamente, esta API nos permitirá acceder y controlar objetos de Java desde un lenguaje de scripting, crear contenido web y embeber un ambiente de scripting. Esto no significa que vamos a poder escribir código JavaScript dentro de Java en forma nativa, pero sí tendremos objetos que nos harán este trabajo un poco más fácil, por ejemplo, vamos a poder registrar un objeto de Java contra un objeto que nos permitirá ejecutar una porción de código Javascript. Este código podrá acceder entonces al objeto de Java y manipularlo. Sobre este tema detallaré en el próximo artículo.

En cuanto a Bases de Datos:
  • Soporte para JDBC 4.0. Esto implica soporte para XML, SQL 2003, mejora en el manejo de pooling de conexiones, mejora en el manejo de excepciones y varias mejoras adicionales.
En cuanto al desarrollo para aplicaciones de escritorio:
  • Mejoras en el Look & Feel.
  • (Dicen en el sitio oficial) Mejoras en el desempeño y performance.
  • Mejoras con respecto a la internacionalización.
  • POR FIN!!!: Los JTable ahora se pueden filtrar y ordenar.
  • ("emulado" de .NET) SwingWorker: bueno, eso de "emulado=copiado" es relativo, si bien se encuentra ya implementado en .NET hace rato, todo viene de un artículo publicado en 1998 "Threads and Swing".

Saludos PF

viernes, diciembre 08, 2006

Bienvenidos los videos tutoriales

¿Cansado de los tutoriales interminables? ¿Sientes que no tienes la voluntad necesaria para ponerte a leer páginas y páginas de información y ejemplos de Java? ¿Necesitado de un poco más de dinamismo?

Bien, entonces quizá te sirva lo siguiente. Creo que la mayoría ya conoce a YouTube (considerado el mejor invento del 2005).
Aquí van a poder encontrar varios tutoriales de Java, realizados por una empresa española llamada Consultoría Java, con complejidades que varían desde cómo realizar el "Hola mundo" hasta conexión a Bases de Datos.

Aquí van algunos video tutoriales:
Para los interesados en otros lenguajes, hay también tutoriales de PHP y Delphi.

Saludos PF