jueves, 5 de diciembre de 2013

¡Adios viejo mundo!

Blogger
Esta es la última entrada que publicaré en el elblogdepicodev.blogspot.com.es o la primera de picodotdev.github.io/blog-bitix dependiendo del blog al que hayas accedido, es decir, seguiré teniendo un blog y escribiendo sobre la temática alrededor de la tecnología como hasta ahora pero a partir de este momento todo el nuevo contenido que publique lo haré en el nuevo blog picodotdev.github.io/blog-bitix, por lo que si estás suscrito al feed de elblogdepicodev te recomiendo que te suscribas al feed de bitix para no perderte ninguna de las nuevas entradas que publique.

Que está por venir en Bitix

Tengo bastante cotenido por publicar en el futuro más o menos inmediato empezando por continuar con la serie de artículos sobre criptografía, GPG y DNI electrónico, instalar la Raspberry Pi en una memoria USB o disco duro externo para ganar velocidad en vez de en la tarjeta SD como he explicado en la guía de instalación con Arch Linux para la RPi, como usar la Raspberry Pi como «media center» con GeeXboX, explicar como usar Octopress y GitHub Pages para bloggear y como personalizarlo, programas para «scrapear» webs, mi experiencia y consejos como blogger, el patrón de diseño no operation, usar marcadores con herramientas de logging como slf4j, el servidor de aplicaciones JBoss y Wildfly y muchas otras cosas que tengo apuntadas o que se me vayan ocurriendo según publico estas. Desde luego tengo contenido para seguir escribiendo en el nuevo blog que al ritmo de una entrada por semana continuaré publicando.

¿Por que este cambio?

Por varias razones, blogger es una plataforma estupenda y a mi durante todo este tiempo me ha servidor perfectamente, es sencillo usarla y en muy poco tiempo se puede tener un blog listo para empezar a escribir en él sin necesidad de muchos conocimientos. Pero tambien tiene varias desventajas, algunas de ellas son:
  • Las entradas han de ser escritas con su editor wysiwyg y como muchos editores en los que ves es lo que obtienes a veces para dejar las cosas como uno quiere al final hay que acceder al código html que genera y modificarlo directamente, esto consume tiempo que podría dedicarse a escribir contenido en el blog y no en la publicación. Yo suelo escribir las entradas en un bloc de notas (con gedit) en texto plano, el pasarlo a blogger y formatearlo posteriormente con su editor me consume también bastante tiempo, tanto o más que en escribir una primera versión de la entrada.
  • La edición de la entrada con el editor de blogger requiere conexión a internet, si no estamos conectados a internet no podemos editar o nos obliga a usar un bloc de notas y posteriormente cuando dispongamos de conexión a internet transpasarlo al editor y darle formato.
  • Las imágenes hay que subirlas usando la propia herramienta de blogger en el momento de publicación de la entrada y conectado a internet. La gestión de las mismas no es muy cómoda, para borrar una imagen una vez subida hay que ir a los álbumes de picasa y cuando se tienen muchas imágenes ya subidas al blog encontrar una en toda la lista se vuelve complicado y lento.
  • Ajustar el diseño de blogger no es muy complicado pero para personalizarlo de forma avanzada requiere editar el HTML de la plantilla. Esta edición no es nada amigable para un usuario con pocos conocimientos y para algunas cosas hay que hacerlo, como por ejemplo, integrar Karmacracy en blogger.
  • Parece que blogger no es una de las herramientas que Google cuide (al igual que otras varias), las actualizaciones son escasas y con el tiempo van surgiendo herramientas mejores que blogger.
  • Los ejemplos de código los añado a cada entrada utilizando Gist e introducir la referencias adecuadas en cada entrada implica editar e introducir código en la vista html. Además en la vista del editor wysiwyg los gist no se visualizan y si no se tiene cuidado se pueden borrar sin querer con lo que hay que volver a introducirlos. Nuevamente incluir las referencias de los gist me consume tiempo.

¿Que herramienta de blogging he elegido?

La plataforma de blogging que he elegido ha sido Octopress, una plataforma de blogging que en mi caso solventa casi todos los problemas o molestias que actualmente me ocasiona blogger descritos en los anteriores puntos. Es una plataforma basada en Ruby y Jekyll, uno de los precursores de una nueva generación de plataforma para blogear y es la plataforma de referencia para escribir en blogs y alojarlos en GitHub Pages. Aún asi hay alternativas parecidas en otros lenguajes de programación como en Python con Pelican. La verdad es que usar Pelican en un principio me atraía más porque con ello quizá aprendiese algo de Python pero el hecho de que Jekyll sea la plataforma de referencia de GitHub es un punto a su favor.

En las siguientes entradas (1), (2) hay algunos comentarios interesantes sobre Pelican y Jekyll. Jekyll por lo visto ha estado abandonado durante un tiempo y Octopress no ha avanzado durante un buen tiempo aunque el desarrollo parece haberse retomado, desde luego por lo que he leído (3) de Octopress es que llevan bastante tiempo con la intención de publicar una nueva versión pero hasta el momento no se ha producido.

Lo principal que buscaba en cualquiera de estas plataformas eran las siguientes ventajas sobre blogger:
  • Markdown (4): este es un formato en texto plano que puede ser transformado a html con ciertos estilos. Como edito con gedit en texto plano usando markdown me va a evitar tener que transformar el contenido de la entrada a html usando el editor wysiwyg de blogger. Además, el html resultante será mejor gracias por una parte a las plantillas de Octopress y por otro a Markdown.
  • Edición fuera de linea o desconecatado: como el editor puede ser cualquier editor de texto no hace falta estar conectado a internet para escribir o transformar lo escrito al editor de bogger, para las imágenes tampoco hace falta usar la herramienta de blogger sino que su administración es tan simple como gestionar archivos con el navegador de archivos de nuestro sistema operativo. El sitio puede previsualizarse en local.
  • Diseño adaptable («responsive»): blogger posee plantillas que puede visualizarse más o menos correctamente tanto en el navegador como en un dispositvo móvil con una resolución y pantalla más pequeña pero no se adaptan al tamaño de pantalla o ventana del navegador que esté usando el usuario. Por el contrario, las plantillas por defecto de Octopress son adaptables o «responsivas» lo que mejora la experiencia del usuario al leer el blog, los elementos cambian de posición y de tamaño según el tamaño de ventana para el navegador. Esto se consigue mediante las nuevas características de CSS3 con las que se pueden aplicar unos estilos u otros en función del espacio disponible para los elementos en el navegador del usuario.
  • Git: todo el código del blog lo tenemos en local y podemos regenerar su contenido en cualquier momento. Al usar git tenemos un histórico de todos los cambios que hemos hecho a los archivos y podemos recuperar algo si nos es necesario, en blogger solo tenemos la última versión. Si en blogger perdiesemos el acceso a nuestro blog regenerar uno nuevo nos sería complicado, tendríamos que tener una copia de seguridad del contenido y esto no nos serviría para recuperar la plantilla si la hemos personalizado.
  • Gist: el soporte que ofrece Octopress para incluir trozos de código de los gist es más simple, basta indicar el número y el nombre del archivo del gist.
  • Cualquier servidor web como hospedaje: si disponemos de una cuenta de GitHub podemos crear un repositorio para servir el contenido del blog con lo que no necesitaremos contratar ningún servidor de hosting pero si disponemos de un servidor web podemos emplearlo para servir el contenido del blog ya que todo es contenido estático.
  • Y otras ventajas como la posiblidad de hacer referencia a otras entradas del blog sin usar la url completa.
Octopress también es fácilmente integrable con todos los elementos de terceras partes que buscaba como Share This y Karmacracy para compartir contenido, Disqus para los comentarios, AdSense para la publicidad, Feedburner para los feeds y Gist para los ejemplos de código.

Así que dicho todo esto solo me queda añadir, suscríbete al nuevo feed y... ¡Hola nuevo mundo!

viernes, 29 de noviembre de 2013

Instalar un lector de tarjetas inteligentes y usar el DNIe en Arch Linux

Arch Linux
Ya desde hace un tiempo los documentos nacionales de indentidad que emite la administración pública española son en el formato de tarjeta inteligente (SmartCard), conocido como DNI electrónico o DNIe. Estas tarjetas inteligentes tienen la ventaja de que incluyen un certificado digital que nos permiten identificarnos en sitios que lo soporten y realizar diversos trámites y acciones.

El DNI electrónico nos puede servir para identificarnos en varias páginas de la administración pública, en las páginas de varios bancos y realizar diferentes trámites electrónicos. El DNIe como medio de identificación en una página tiene la ventaja de que no necesitamos tener un usuario y una contraseña específica para ese sitio sino que con el DNI físico y el PIN nos será suficiente. Para identificarnos necesitamos algo que poseemos (el DNI) y algo que conocemos (PIN) con lo que las posibilidades que de alguien que quiera realizar alguna acción en nuestro nombre suplantando nuestra identidad será más complicado, la seguridad es mayor ya que no basta con conocer únicamente el usuario y clave sino que se necesita algo físico. Conseguir ambas cosas es más difícil que solo la clave. Realizar tramites administrativos de forma electrónica tiene la ventaja que no necesitamos desplazarnos hasta la correspondiente ventanilla para realizar el trámite. Algunos bancos que permiten identificarnos con el DNIe son el Santander, BBK, el infame Bankia  y posiblemente muchos otros, también podemos consultar los puntos que poseemos en el carnét de conducir, seguro que hay muchas más cosas útiles en las que podemos dar uso al DNIe.

En esta entrada voy a explicar como instalar el DNI electrónico en Linux más concrétamente en Arch Linux. La primera cosas que necesitaremos será disponer de un lector de tarjetas inteligentes como el siguiente que yo adquirí por unos 12€:

Después en Arch Linux deberemos instalar los siguientes paquetes:

opensc-dnie (AUR) y ccid nos darán el soporte para acceder al DNIe, pcsc-tools nos proporcionará una herramienta (pcsc_scan) con la que podremos comprobar si el lector funciona correctamente y detecta la tarjeta o DNI. Una vez instalados los programas debemos modificar el archivo de configuración «/etc/opensc.conf» aplicando los siguientes cambios y valores en cada apartado y propiedad:

Después debemos iniciar el servicio de opensc, podemos hacer que se inicie con el sistema (enable) o cuando deseemos de forma manual (start):

Una vez hecho todo esto podemos comprobar el funcionamiento de nuestro lector con el DNIe, para ello utilizamos pcsc_scan que nos indicará si ha detectado un lector de tarjetas y si este tiene o no una tarjeta introducida:

Con el siguiente comando podemos ver los certificados del DNIe:



Y con el siguiente comando podemos exportar el certificado del DNI, se nos solicitará el PIN del DNI:

Si examinamos el certificado podemos darnos cuenta de una cosa curiosa y es que aunque el DNI físico se emite con una validez de 10 años el certificado incluido en él solo tiene una validez de 2 años y medio, con lo que pasado este tiempo deberemos acudir a la oficina de expedición para ampliar el periódo límite de uso.

Y esto debería ser parecido para otras distribuciones como Ubuntu, Debian, Mint, openSUSE, Fedora. Los paquetes pueden ser diferentes pero el proceso de instalación será similar a este

Cone esta entrada de momento solo hemos instalado el lector de tarjetas inteligentes en posteriores entradas explicaré como usar el DNIe para autenticarnos en una página usando Firefox, firmar documentos PDF con Sinadura o enviar correos electrónicos firmados digitalmente usando el cliente de correo Evolution. También puedes consultar como crear un parde claves GPG y usarlas para enviar correos firmados digitalmente.

Referencia:
Usar el DNI electrónico con Firefox en Linux
https://wiki.archlinux.org/index.php/Common_Access_Card
http://www.banot.net/?q=node/15

viernes, 22 de noviembre de 2013

Como usar GPG con Evolution

GnuPG
Evolution
Después de la introducción a la criptografía y crear una clave GPG ya sea a través de la linea de comandos en la terminal o con la herramienta Contraseñas y claves de GNOME además de usarla para cifrar y firmar documentos desde la terminal podemos usarla para firmar y cifrar los correos electrónicos que enviemos usando nuestro cliente de correo. La firma de los correos electrónicos permitirá conocer al receptor si el correo ha sido modificado por una tercera parte, comprobar la autenticidad del mensaje y si tenemos la clave pública del destinatario podremos enviarle el correo cifrado evitando que pueda ser leído salvo por el destinatario.

En esta entrada explicaré como firmar y cifrar el correo electrónico que enviemos usando nuestra clave GPG y el cliente de correo por defecto de GNOME, Evolution. Para firmar los correos electrónicos que enviemos deberemos conocer previamente el id de nuestra clave GPG, podemos averiguarlo con el comando:


Este comando nos mostrará todas las claves GPG que tenemos en nuestro sistema, buscaremos la nuestra y nos fijaremos en la segunda columna de la linea que empieza por pub. En mi caso el id de mi clave es E012C989 como puede verse en la captura de pantalla (en la segunda clave).

Una vez que conocemos del id de nuestra clave, vamos a las propiedades de la cuenta de correo de Evolution y lo introducimos en el campo preparado para ello del apartado Seguridad (Propiedades de la cuenta > Seguridad). Y esto será suficiente para que a partir de ahora los correos que enviemos con nuestra cuenta de correo vayan firmados si marcamos la opción «Firmar siempre los mensajes salientes cuando se use esta cuenta» o marcando la opción «Firmar on GPG» en el menu Opciones en la redacción de un mensaje.


La firma digital será añadida como un documento adjunto de nombre «signature.asc» que empezará con el contenido «-----BEGIN PGP SIGNATURE-----». Si evolution nos indica que la firma es válida pero que el remitente no puede ser validado nos falta confiar en la clave.


Con Seahorse accedemos a las propiedades de la clave y en la pestaña «Detalles» modificamos el nivel de confianza de «Predominar confianza del propietario», si confiamos en la clave podemos indicar el valor «Absoluta». Los diferentes mensajes que nos puede indicar Evolution dependiendo de si poseemos la clave pública del remitente, poseemos la clave pero aún no hemos confiado en ella y si tenemos confianza absoluta en la clave son:



Para enviar correos cifrados deberemos solicitar a cada destinatario su clave GPG o PGP pública e importarla en nuestro anillo de claves. También si queremos que nos envíen el correo cifrado deberemos distribuir entre nuestros remitentes nuestra clave pública. Para importar una clave pública de un contacto podemos hacerlo con el siguiente comando desde la terminal:

O también con la aplicación de GNOME Contraseñas y claves con la opción «Archivo > Importar...»

Con otros clientes de correo electrónico la forma de usar GPG varía, en esta entrada he explicado la combinación de GPG/Evolution. Con Thunderbird debemos usar la extensión Enigmail, para Outlook parece que la mejor opción es Gpg4win.

En siguientes entradas de esta serie sobre seguridad explicaré como crear certificados, SSL, servidores, firma digital con Sinadurasmart cards en linux y DNIe, ... y quizá alguna cosa más.


Referencia:
GnuPG
https://addons.mozilla.org/es/thunderbird/addon/enigmail/
http://www.gpg4win.org/

viernes, 15 de noviembre de 2013

Introducción a la criptografía e inicio con GPG

GnuPG
Internet está formado por una red de máquinas interconectadas que en conjunto permiten que un par de máquinas de esa red puedan comunicarse entre si aunque no estén directamente conectadas, el protocolo TCP/IP es el que posibilita esa comunicación. En la comunicación entre las máquinas que no están directamente conectadas la información de la máquina origen ha de ser transportada por un camino de varias máquinas hasta llegar a a la máquina destino y posteriormente de vuelta por el mismo camino u otro. En muchos casos la información que viaja a lo largo de ese camino de terceras máquinas no es relevante ni sensible pero en otros casos podemos necesitar o queremos evitar que esas terceras máquinas puedan acceder a la información que se está transmitiendo. En este último caso es donde entra en acción la criptografía.

Diagrama de enrutadores en internet, cada elipse (roja) es un enrutador por el que pasa la información transmitida entre el cliente (verde) y el servidor (azul)

La criptografía nos permite que el contenido de un mensaje solo sea legible para el emisor y receptor, aunque los datos sean transportados por terceras máquinas solo verán datos ofuscados (o cifrados) a cuyo contenido no se les podrá dar ningún sentido ni interpretación. La criptografía proporciona las siguientes propiedades:
  • Confidencialidad: garantiza que el mensaje solo pueda ser leído por su destinatario.
  • Integridad: garantiza que el mensaje no ha sido modificado por un tercero.
  • Vinculación: trata de asociar el emisor con una clave.
  • Autenticación: consiste en garantizar que el mensaje ha sido emitido por un determinado agente.
Para conseguir estas propiedades la criptografía usa diversos elementos como algoritmos de cifrado simétricos, asimétricos o híbridos, claves privadas o claves públicas y privadas, certificados digitales, huellas y firmas digitales. Los algoritmos de cifrado son los que garantizan la propiedad de confidencialidad, tienen la propiedad de que una vez cifrado los datos es muy difícil o se necesita una cantidad de cómputo y tiempo muy elevada para descifrar el mensaje. Hay varios tipos.

Los algoritmos simétricos

Estos algoritmos utilizan la misma clave tanto para cifrar la información como para descifrarla. Son rápidos y a misma longitud de claves más seguros que los de clave asimétrica pero plantea el problema de como intercambiar la clave privada de forma segura a través de la red, para ello se usan los algoritmos asimétricos.



Los algoritmos asimétricos o de clave pública y privada

Este tipo de algoritmos usan dos claves para realizar el proceso de cifrado. Cada usuario posee dos claves, una pública y otra privada. La clave pública de cada par de claves se puede compartir a cualquier otra persona, el que quiera enviarle un mensaje cifrado al propietario de esa clave pública lo cifrará con la clave pública, el mensaje solo puede ser descifrado con su clave privada asociada que solo conoce su propietario. De esta manera los algoritmos asimétricos evitan el problema de como compartir la clave de los algoritmos simétricos ya que en este par de claves hay una pública que puede ser compartida.



Sin embargo, los algoritmos de clave pública y privada no solucionan todos los problemas de seguridad por si solos, está el problema de confianza en la clave pública, es decir, estar seguros de que la clave pública es realmente del destinatario al que pretendemos enviar un mensaje y no la de alguien que se ha colacado en medio del emisor y receptor con la intención de realizar un ataque «man-in-the-middle». Para ello podemos confiar en una tercera parte en la que confiamos, si nosotros confiamos en esa autoridad y esa autoridad certifica que la clave pública es de quien dice ser podemos confiar en que el mensaje será solo legible por destinatario y propietario de esa clave pública, aquí es donde entran las autoridades de certificados. Para certificar las claves públicas se emplean certificados y firmas digitales.

Los algorítmos híbridos

Este tipo de algoritmos aprovechan y combinan lo mejor de los algoritmos simétricos y asimétricos. Para cifrar un mensaje se genera una clave simétrica, se usa un algoritmo simétrico para cifrar el mensaje con la clave generada y la clave usada para cifrar el mensaje se cifra a su vez con la clave pública (algoritmo asimétrico) del destinatario. Posteriormente cuando el destinatario recibe el mensaje descifra con su clave privada la clave con la que fue cifrada el mensaje y con la clave descifrada usando el algorítmo simétrico se descifra el mensaje. En el siguiente esquema se puede apreciar el proceso:

GPG (Gnu Privacy Guard)

Esa es la teoría básica, ahora veamos como utilizar GnuPG que es una implementación libre de PGP (Pretty Good Privacy) y sacar provecho de esta entrada y la criptografía. Crearemos una clave pública y privada, cifraremos y descifraremos un archivo y verificaremos su integridad. A continuación los comandos en orden para generar el par de claves (se nos guiará en el proceso), ver su huella digital, exportar la clave pública y exportar la clave privada para conservarla en un archivo.

El parámetro --armor sirve para codificar la salida en formato texto, con cualquier editor de texto podremos ver su contenido (aunque lo que veamos sea una sopa de letras). Este comando es combinable con otros con similar resultado. Entre usar o no usar armor depende de nuestras necesidades, sin --armor el resultado ocupa menos pero es dificilmente legible por un editor de texto y con --armor el resultado ocupa más pero es legible por un editor de texto.


Si enviamos la clave pública a un servidor de claves para que otros usuarios puedan descargarse nuestra clave y verificar los mensajes que enviamos es aconsejable generar un certificado de revocación para poder revocar la validez de la clave en caso de que su seguridad haya sido comprometida.

Como cifrar un archivo con GPG
Esto generará un archivo del mismo nombre que el que firmamos pero con las extensión .gpg añadida al final, en este caso se generaría un archivo de firma secret.zip.gpg (podemos usar el parámetro --armor y se creará el archivo con extensión .asc). Con -r indicamos el destinatario del mensaje, necesitaremos su clave pública para cifrar el archivo y que solo el destinatario pueda descrifrarlo con su clave privada.

Como firmar un archivo con GPG
Con -u indicamos la clave que realizará la firma. Si no necesitamos cifrar el archivo para garantizar su confidencialidad pero queremos garantizar que no es modificado hasta llegar al receptor y su origen, es decir queremos garantizar su integridad y autenticidad, podemos firmarlo digitalmente.

Como descifrar y verificar un archivo con GPG
Para descrifrar un archivo:

Si hacemos alguna modificación al archivo e intentamos descifrarlo veremos que el programa nos alerta de que el archivo ha sido modificado, tal como podría ocurrir si en la transmisión del mensaje hubiese sido interceptado y modificado. Para verificar la intergridad de un archivo hacemos:



Para crear la clave también podemos emplear la aplicación Seahorse o Contraseñas y claves de GNOME. O si la hemos creado mediante comandos con GnuPG importarla en esta aplicación además de almacenarlas en un depósito seguro de claves. Usando Seahorse para generar una par de claves GnuPG no necesitamos usar la terminal y los comandos anteriores pero el proceso nos pide los mismos datos.



Sehaorse también tiene opciones para importar y exportar las claves GnuPGP a y del anillo de claves.

Aunque enviemos los datos cifrados y hagamos inaccesible el contenido no es sinónimo de privacidad, a veces saber simplemente que un mensaje se envío, a que hora, de que longitud, duración, tamaño, desde donde, a donde y a quien puede ser información suficiente para extraer conclusiones, patrones o sobre que trataba la información entre otras cosas, sino preguntarle a la NSA/CSS que de esto saben bastante por las recientes informaciones de espionaje realizadas impunemente y en secreto por el gobierno de los EEUU, esa recolección ingente de datos son una muestra de ello.

En siguientes entradas de esta serie sobre seguridad explicaré como configurar un gestor de correo electrónico (evolution) para enviar mensajes de correo electrónico firmados o cifrados con las claves GPG creadas con los comandos de esta entrada, certificados, SSL, servidores, firma digital con Sinadurasmart cards en linux y DNIe, ... y quizá alguna cosa más.

Referencia:
PGP Web of Trust: Core Concepts Behind Trusted Communication
Criptografía
Manual de GPG: cifra, firma y envía datos de forma segura
Getting Started with GNU Privacy Guard
http://www.gnupg.org/gph/es/manual.html
https://wiki.archlinux.org/index.php/GnuPG

viernes, 8 de noviembre de 2013

Integración y transacciones con Spring en Apache Tapestry

Apache Tapestry
Spring
En otra entrada comentaba como hacer transacciones en una base de datos relacional con Apache Tapestry y como mejorar el soporte que ofrece de por si con la anotación CommitAfter mediante con una solución propia que proporciona la anotación Transactional. La solución propia mejora la anotación CommitAfter y es usable en más casos como cuando dos servicios distintos necesitan colaborar en una transaccion y compartirla. Sin embargo, si el correcto funcionamiento de las transacciones es una parte importante de la aplicación (y en una aplicación grande lo será) podemos evaluar si optar por Spring o los EJB en vez de la solución propia o la anotación CommitAfter.

Unos buenos motivos para optar tanto por Spring como por los EJB es que son soluciones ya desarrolladas con lo que solo tendremos que integrarlo en nuestros proyectos y no tendremos que preocuparnos de mantener nuestra solución en caso de que tenga errores, además ambas son ampliamente usadas incluso en proyectos grandes y complejos y están ya probadas lo que es una garantía. Entre optar por Spring o los EJB depende de varios factores como puede ser si la aplicación va ha ser desplegada en un servidor de aplicaciones con soporte para EJB (como JBoss/Wildfly, Geronimo, ...) o no (Tomcat, Jetty) o de nuestras preferencias entre ambas opciones. En esta entrada explicaré como integrar Spring con el framework Apache Tapestry y como hacer uso de las transacciones de Spring en los servicios que contienen la lógica de la aplicación.

Primeramente, decir que en cierta medida la funcionalidad proporcionada por el contenedor de dependencias de Tapestry y el contenedor de dependencias de Spring se solapan, ambos proporcionan Inversion of Control (IoC). Pero el contenedor de dependencias de Tapestry tiene algunas ventajas como permitir configuración distribuida, esto hace referencia a que cada librería jar puede contribuir con su configuración al contenedor de dependencias y que la configuración se hace mediante código Java en vez de xml como en Spring con la ventaja de que es más rápido, tenemos la ayuda del compilador para detectar errores y el lenguaje Java es más adecuado para expresar la construcción de objetos. De modo que si podemos es mejor usar el contenedor de Tapestry que el de Spring, sin embargo, Spring ofrece un montón de funcionalidades muy útiles y esto nos puede obligar a usar el contenedor de Spring para ciertos objetos. Una de ellas son las transacciones para cumplir con las reglas ACID de las bases de datos relacionales, para ello deberemos definir en el contenedor de Spring (y no en el de Tapestry) los servicios con la lógica de negocio con necesidades transaccionales y las dependencias referidas por esos servicios en la configuración del contexto de Spring. A pesar de todo en los demás casos podemos optar por la opción que prefiramos ya que tanto a los servicios de Spring se les pueden inyectar dependencias del contenedor de Tapestry y, el caso contrario, a los servicios de Tapestry se les pueden inyectar servicios de Spring.

Veamos en código un ejemplo de como conseguir integración entre Tapestry y Spring. La primera cosa que cambia es que hay que usar un filtro de Tapestry especial para integrarse con Spring con lo que deberemos modificarlo en el archivo web.xml. Si normalmente usamos el filtro org.apache.tapestry5.TapestryFilter para que Tapestry procese las peticiones que llegan a la aplicación, integrándonos con Spring usaremos un filtro especial, org.apache.tapestry5.spring.TapestrySpringFilter. También mediante una propiedad de contexto indicaremos el (o los) xml con la definición de los beans de Spring.

En el xml del contexto para Spring definimos la configuración para que Hibernate se conecte a la base de datos, definimos el SesionFactory que creará la sesiones de Hibernate, el gestor de transacciones y los servicios con la lógica de negocio. En este ejemplo he optado por definir las transacciones mediante anotaciones en los servicios con la lógica de negocio. Spring también permite definir la transaccionalidad de forma declarativa en este xml.

Como Spring se encargará de la configuración de Hibernate si incluimos la dependencia tapestry-hibernate tendremos un problema ya que este módulo de Tapestry también intenta inicializar Hibernate. Para evitarlo y disponer de toda la funcionalidad que ofrece este módulo como encoders para las entidades de dominio, la página de estadísticas de Hibernate o el objeto Session como un servicio inyectable en páginas o componentes hay que redefinir el servicio HibernateSessionSource. El nuevo servicio es muy sencillo, básicamente obtiene el la configuración de Hibernate mediante el bean SessionFactory definido en Spring y además mediante el mismo bean se crea el objeto Session que podrá inyectarse en los componentes y páginas de Tapestry en los que lo necesitemos. También deberemos añadir un poco de configuración en el módulo de la aplicación para redefinir este servicio.

Para definir la transaccionalidad de una operación debemos usar la anotación Transactional usando los valores por defecto o indicando la propagación, el aislamiento, si es de solo lecura, timeout, etc, ... según consideremos. Debido a lo simple de la lógica de negocio de la aplicación de este ejemplo la anotación se aplica al DAO, sin embargo, en una aplicación más compleja y con mas clases sería mejor definirlo a nivel de servicio de lógica de negocio o punto de entrada a la lógica de negocio y no al nivel de los DAO que están en una capa de la aplicación más baja.

Finalmente, debemos añadir o modificar las dependencias de nuestra aplicación. La dependencia tapestry-spring usa por defecto la versión 3.1.0 de Spring, en el ejemplo la sustituyo por la versión 3.2.4 más reciente. A continuación incluyo la parte relevante.

Si te ha parecido interesante esta entrada puedes descargar el libro PlugIn Tapestry en el que explico más en detalle como desarrollar aplicaciones web en Tapestry y en el que descubrirás como resolver problemas comunes en las aplicaciones web de una forma tan buena como esta.

Si quieres probarlo en tu equipo lo puedes hacer de forma muy sencilla con los siguientes comandos y sin instalar nada. Si no dispones de git para clonar mi repositorio de GitHub puedes obtener el código fuente del repositorio en un archivo zip.

Referencia:
Transacciones en Apache Tapestry
Persistencia con JPA y Apache Tapestry
Acceso a base de datos con Hibernate y JPA
Transaction Management (Spring)

viernes, 1 de noviembre de 2013

Transacciones en Apache Tapestry

Apache Tapestry
Tapestry no proporciona de por sí un soporte completo a las aplicaciones que necesitan realizar operaciones en una base de datos relacional de forma transaccional. La dependencia tapestry-hibernate provee la anotación @CommitAfter para Hibernate y la dependencia tapestry-jpa otra del mismo nombre para JPA pero esta anotación en ambos casos proporciona una funcionalidad muy básica y probablemente no no sirva en casos de uso complejos. Esto ha sido objeto de discusión varias veces en la lista de distribución de los usuarios [1] [2] y el JIRA de Tapestry [3].

Con la anotación CommitAfter si se produce una excepción no controlada («unchecked») se hará un rollback de la transacción y, esto es importante, aún produciendose una excepción controlada («checked») se hará el commit de la transacción y es responsabilidad del programador tratar la excepción adecuadamente. Se puede usar en los métodos de los servicios y en los métodos manejadores de eventos de los componentes.

Sabiendo como funciona la anotación se nos plantean preguntas:
  1. ¿Cuál es el comportamiento cuando un método del servicio anotado llame a otro también anotado del mismo servicio?
  2. ¿Que pasa si cada método está en un servicio diferente?
Para el primer caso (métodos del mismo servicio) se hará una sola transacción ya que las anotaciones y los advices se aplican en el proxy del servicio no en la implementación. En el segundo caso (métodos en diferentes servicios) se iniciará una transacción pero haciendo un commit en la salida de cada método.

Si tenemos una aplicación compleja probablemente se nos planteará el caso de tener varios servicios que se llaman entre si y que ambos necesiten compartir la transacción, en esta situación la anotación CommitAfter probablemente no nos sirva por hacer un commit en la salida de cada método.

Tapestry no pretende proporcionar una solución propia que cubra todas las necesidades transaccionales que puedan tener todas las aplicaciones sino que con la anotación CommitAfter pretende soportar los casos simples, para casos más complejos ya existen otras opciones que están ampliamente probadas. Si necesitamos un mejor soporte para las transacciones que el que ofrece Tapestry debemos optar por Spring o por los EJB. Sin embargo, la solución de Spring nos obliga a definir los servicios transaccionales como servicios de Spring y los EJBs nos obligan a desplegar la aplicación en un servidor de aplicaciones que soporte un contenedor de EJB como JBoss/Wildfy, Gernimo, TomEE, ... Si nuestro caso no es tan complejo como para necesitar mucho de lo que ofrece Spring o no queremos o podemos usar un servidor que soporte EJB podemos aplicar el ejemplo ya comentado en Tapestry Magic #5: Advising Services.

En esta entrada pondré un ejemplo completo usando la solución de Tapestry Magic #5 pero con la adición de una anotación que permite definir más propiedades de las transacciones y la diferencia respecto a la anotación CommitAfter de que independientemente de si se produce una excepción checked o unchecked se hace un rollback de la transacción. La anotación Transactional permite definir si la transacción es de solo lectura, definir un timeout para completar la transacción o el nivel de aislamiento de la transacción además de la estrategia de propagación. Aunque no sea una solución tan buena como la de usar Spring o EJBs, puede ser suficiente para muchos más casos que la anotación CommitAfter.

La solución consiste en implementar una nueva anotación para los métodos transaccionales que he llamado Transactional, unos advices con las diferentes estrategias de transaccionalidad (REQUIRED, SUPPORTS, NEVER, NESTED, MANDATORY), un advisor que aplicará una estrategia transaccional en función de la anotación Transactional de los métodos y un poco de configuración para el contenedor IoC que define los servicios y aplica la decoración a los métodos anotados.

Hay que tener en cuenta que esta solución es una prueba de concepto que he probado en este ejemplo y puede presentar problemas que aún desconozco en una aplicación real. Una vez dicho esto veámos el código.

Primero la anotación, el enumerado de las estrategias de propagación de transacciones, el DTO (Data Transfer Object) con las propiedades de la anotación y la interfaz del servicio transaccional.

Ahora el advisor que usará el servicio transaccional y en función de la estrategia de propagación aplicará el advice adecuado.

El funcionamiento de las estrategias transaccionales son:
  • REQUIRED: si no hay una transaccion activa inicia una y hace el commit al finalizar. Si existe una al entrar en el método simplemente ejecuta la lógica usando la transacción actual
  • MANDATORY: requiere que haya una transacción iniciada, en caso contrario produce una excepción.
  • NESTED: inicia una nueva transacción siempre aún existiendo ya una, con lo que puede haber varias transacciones a la vez de forma anidada.
  • NEVER: es el caso contrario de MANDATORY, si existe una transacción produce una excepción.
  • SUPPORTS: puede ejecutarse tanto dentro como fuera de una transacción.
Probablemente con la anotación REQUIRED tengamos suficiente para la mayoría de los casos, para la estrategia NESTED necesitaremos soporte del motor de la base de datos que no todos tienen, el resto son otras posibilidades comunes en el ámbito de las transacciones: MANDATORY, NEVER, SUPPORTS.

Y ahora las implementaciones de las estrategias de propagación que iniciarán, harán el rollbak y commit de forma adecuada a la estrategia usando el servicio transaccional.

A continuación la implementación del servicio transaccional para el caso de Hibernate.

Finalmente el gestor de sesiones de Hibernate y la configuración necesaria en el módulo de la aplicación.

Si te ha parecido interesante esta entrada puedes descargar el libro PlugIn Tapestry en el que explico más en detalle como desarrollar aplicaciones web en Tapestry y en el que descubrirás como resolver problemas comunes en las aplicaciones web de una forma tan buena como esta.

Si quieres probarlo en tu equipo lo puedes hacer de forma muy sencilla con los siguientes comandos y sin instalar nada. Si no dispones de git para clonar mi repositorio de GitHub puedes obtener el código fuente del repositorio en un archivo zip.

Referencia:
Integración y transacciones con Spring en Apache Tapestry

viernes, 25 de octubre de 2013

Relaciones jerárquicas en bases de datos relacionales

Otro de los problemas que se suele presentar al trabajar con bases de datos relacionales además de como internacionalizar las entidades del dominio o como hacer búsquedas de texto completo es como modelar las relaciones jerárquicas. Para resolver el problema de las búsquedas en las bases de datos relacionales con datos jerárquicos hay varias soluciones posibles cada una con sus ventajas y desventajas y una más ideal si la base de datos lo soporta, son:

Listas adjacentes

En este modelo se crea una campo adicional que indicará el nodo padre de la relación jerárquica, los nodos raíz tendrán este campo a null al no tener padre.

Buscar los descendientes de un nodo, sin el soporte de quieries recursivas y suponiendo una profundidad máxima en la jerarquía de diez se puede conseguir con la siguiente sql:

En este caso obtendremos una fila con su jerarquía por cada hoja del árbol. Todo el conjunto de identificativos obtenidos forman los descendientes. Hay que tener en cuenta que en los resultados un identificativo puede aparecer varias veces y con esta consulta el nodo del que se buscan descedientes está incluido.

Buscar los ascendientes se puede hacer de forma similar:

Con esta sql obtendremos una fila con los identificativos, c1 será el identificativo del nodo superior y c10 el nodo inferior de la jerarquía.

Con esta solución para mover un nodo de un padre a otro en el árbol basta con actualizar el identificativo del nodo padre, es simple y rápido. Sin embargo buscar descendientes y ascendientes es más complejo e ineficiente si la base de datos no soporta queries recursivas (que las bases de datos más importantes, Oracle, SQL Server, PosgreSQL salvo MySQLsoportan y a partir de laversión 5.6 ya lo hace), también puede requerir una segunda query para buscar los datos de los descendientes y ascendientes, con estas solo recuperamos los identificativos.

Conjuntos anidados

Esta solución se basa en que cada nodo de la jerarquía esté numerado, el padre tendrá dos campos el número de menor hijo y el número del mayor hijo, todos los nodos cuyos números estén entre esos dos números son descendientes del nodo padre. La consulta de buscar los nodos descendientes es simple y eficiente.

Buscar los nodos ascendientes también se puede conseguir una sql eficientemente:

La desventaja de esta solución está en el momento que queremos insertar un nuevo nodo en el árbol de la jerarquía o mover un nodo dentro del árbol ya que implica reorganizar los valores de las columnas left y right, puede que de muchas filas y por tanto resultar lento.

Consultas recursivas

Con el soporte de consultas recursivas se puede conseguir la simplicidad de las adjacency list y la eficiencia de los nested sets. El modelo de datos es similar al caso de las Adjacency List con una columna del identificativo padre del nodo.

Para buscar los descendientes de un nodo sería:

Para buscar los nodos ascendientes:

Como comentaba de las bases de datos más importantes de entre Oracle, SQL Server, PostgreSQL y MySQL solo MySQL no lo soporta aunque a partir de laversión 5.6 también lo hace. Dependiendo de si hacemos más consultas que modificaciones y de si queremos complicarnos más con los nested sets deberemos optar por una solución u otra, en cualquier caso optaremos por las queries recursivas si la base de datos lo soporta.

Referencia:
http://en.wikipedia.org/wiki/Hierarchical_query
http://en.wikipedia.org/wiki/Nested_set_model
http://en.wikipedia.org/wiki/Adjacency_list_model

http://vadimtropashko.wordpress.com/2008/08/09/one-more-nested-intervals-vs-adjacency-list-comparison/
http://stackoverflow.com/questions/4048151/what-are-the-options-for-storing-hierarchical-data-in-a-relational-database
http://explainextended.com/2009/09/24/adjacency-list-vs-nested-sets-postgresql/
http://www.postgresql.org/docs/8.4/static/queries-with.html