jueves, octubre 07, 2010

MySQL: Lock wait timeout exceeded

Trabajando con MySql e iBatis me topé con un problema que, en principio no tenía muy claro de dónde podía venir.

El caso es que, aparentemente, de forma aleatoria cuando hacía un insert o un update, la aplicación dejaba de responder y acababa mostrando una traza como esta:

java.sql.SQLException: Lock wait timeout exceeded...

Después de mucho mirar y también mucho buscar en Google, caí en la cuenta que el problema lo daba una query que abría una transacción que no se cerraba antes de ser devuelta al pool.

En un método de la aplicación estaba abriendo una transacción y cerrandola en el catch en lugar de en el finally. Un finally y un endTransaction después, puedo respirar tranquilo... y por supuesto, mil gracias a este post sin el cual aún seguiría dando vueltas por los fuentes de la aplicación como alma en pena.

miércoles, septiembre 15, 2010

Clase BeanUtils de Apache Commons y las fechas

Hola,

Usando el API BeanUtils de Apache, en concreto su (gran) método copyProperties, me dí cuenta de que cuando el bean a copiar tenía algún campo con fechas y estas estaban a null se obtenía la siguiente traza:


No value specified for 'Date'
org.apache.commons.beanutils.ConversionException: No value specified for 'Date'


Bien, buscando por ahí encontré una forma de seguir usando BeanUtils aún cuando el bean tiene fechas a nulo.


Date defaultValue = null;
DateConverter converter = new DateConverter (defaultValue);
ConvertUtils.register (converter, java.util.Date.class);

BeanUtils.copyProperties (view, nuevo);


Simple pero eficaz. Lo encontré en un foro, pero no lo menciono ya que el "descubrimiento" fue hace ya bastante tiempo y no tengo ni idea de dónde lo saqué.

domingo, agosto 08, 2010

¿Un nuevo impulso para Linux?

Soy usuario habitual de Linux, en concreto de Ubuntu. Si, ya sé que muchos opinarán que hay mejores distribuciones. Particularmente no me interesa esa discusión. Cada usuario de Linux puede elegir la que más le convenza.

También habrá usuarios de otros sistemas que opinarán que dichos sistemas son mejores y expondrán sus razones. Tampoco es una discusión en la que quiera entrar. Ya le he tenido muchas veces.

Bueno, a lo que iba. Hace algún tiempo, en una reunión de amigos conocí a una persona metida en temas políticos en un pequeño pueblo, de izquierdas y fanático del software libre. Yo llevaba mi portátil y la última distribución de Ubuntu por aquel entonces. Había solicitado el CD a Canonical, con sus correspondientes pegatinas. Le vi tan entusiasmado, que le regalé las pegatinas.

Después empezamos una charla distendida sobre Linux, software libre y demás. Yo habitualmente tengo instalado un sistema dual (Windows/Linux) y me preguntó por qué, ya que con Linux podía hacer todo lo que necesitaba. Es casi cierto en mi caso, ya que desarrollo en Java y no necesito un Windows para realizar mi trabajo (puedo usar indiferentemente uno u otro sistema).

El caso es que sólo tuve que contestarle con tres palabras para que no siguiera insistiendo en el tema: "me gusta jugar". No dijo nada más.

Llegados a este punto, alguno me recordará que existe algo llamado Wine, que me permitirá instalar aplicaciones Windows en mi Linux, pero personalmente, no termina de convencerme. He tenido algunas experiencias con Wine, que no me han dejado buen sabor de boca. En ocasiones hay que remangarse para hacer que las cosas funcionen medianamente bien.

Es cierto que los esfuerzos de Canonical, Red Hat, Debian y otros han conseguido darle un impulso al S.O., pero recientemente ha surgido una noticia que creo que podría darle un impulso mucho mayor. Me refiero a la intención de Valve de publicar una versión de Steam para Linux.

Según las noticias, es posible que la primera versión esté disponible a finales de verano del 2010 y Valve ya ha confirmado que, aparte de los juegos que ya estaban disponibles para Linux (Unreal Tournament 2004, World of Goo o títulos de id Software como Enemy Territory: Quake Wars o Doom 3), títulos propios como Half-Life 2, Counter-Strike: Source o Team Fortress 2 y la siguiente versión de Portal también se lanzarán para esta plataforma.

Habrá que esperar a ver cómo se desarrollan los acontecimientos, pero tengo la impresión que este podría ser el mayor "empujón" que haya recibido Linux en los últimos años.

martes, mayo 04, 2010

Android no muestra todos mis calendarios

Si tenéis un móvil con Android, quizás también "sufrais" este pequeño contratiempo. Aunque en tu cuenta de Google Calendar dispongas de más de un calendario donde añadir tus citas, Android sólo muestra las citas de uno (o quiźas algunos) de los calendarios.

Ese "bug" (no creo que se pueda llamar así, pero bueno...) se soluciona de una forma muy sencilla. En "Ajustes" seleccionar "Aplicaciones" y después "Administrar aplicaciones". Nos aparecerá una lista completa de las aplicaciones que tenemos instaladas.

Nos desplazamos por la lista buscando una llamada "Calendario" (es posible que aparezca también como com.android.calendar o similar). Seleccionamos esta aplicación y a continuación pulsamos el botón "Borrar datos" (con valor) y a después, abajo, "Forzar detención".

Si ahora abrimos nuestro calendario en Android, veremos cómo comienza a sincronizarse e irán apareciendo las citas de todos nuestros calendarios.

Espero que os ayude.

lunes, mayo 03, 2010

Ya está disponible Ubuntu 10.04

Para todos los fanáticos de Ubuntu, ya se puede descargar la nueva versión 10.04 (Lucid Lynx).

Esta es una versión LTS (Long Term Support). La ánterior LTS fue la 8.04.

Aquí puedes acceder a un tour con las novedades que se incluyen en la versión de escritorio.

jueves, abril 29, 2010

ScrumNinja: herramienta para la gestión de equipos con Scrum

Si gestionas tus proyectos con Scrum, aquí tienes una nueva herramienta que promete facilitarte las tareas de mantenimiento de los diferentes artefactos a mantener (Project Backlog, Sprints, User Stories, ...): ScrumNinja.

Disponen de dos diferentes modelos de explotación: hosting o software instalable. En el primer caso, los pagos son mensuales y dependen del numero de usuarios. En el segundo caso, se realiza un único pago en función del número de usuarios. Los precios son bastante asequibles.

Incluye herramientas visuales, como la pizarra de Scrum.

Puedes probarlo de forma gratuita durante 30 días.

Netbeans 6.9 Beta ya disponible

La beta del IDE Netbeans 6.9 ya está disponible para su descarga.

Incluye mejoras referentes a OSGi, JavaFX (editor visual similar al de Swing), PHP (soporte para Zend Framework), soporte para Ruby on Rails 3.0, soporte para Spring Framework 3.0.

Esta es la lista de todas las novedades:
http://netbeans.org/community/releases/69/

Y el enlace para descargarlo:
http://download.netbeans.org/netbeans/6.9/beta/

miércoles, abril 28, 2010

Cómo eliminar definitivamente una cuenta en facebook

Por si en algún momento quieres eliminar completamente tu cuenta de facebook:

Si entras en tu cuenta, en la configuración de la cuenta podrás ver que existe la posibilidad de desactivarla, pero aparentemente no hay una opción de eliminar tu cuenta definitivamente. Sin embargo esta opción existe. El enlace es el siguiente (tienes que estar logueado en la cuenta que deseas eliminar):

http://www.facebook.com/help/contact.php?show_form=delete_account


El procedimiento es rápido y te informan que tu cuenta pasa a estar desactivada y que se eliminará completamente en unos 14 días. También te informa que durante esos 14 días puedes entrar en cualquier momento y volver a activar tu cuenta, con lo cual se cancelará el proceso de eliminación.

A continuación te envían un correo a la dirección asociada a la cuenta con el título "Cuenta programada para su eliminación" (esto me suena a Star Wars, episodio IV), con el siguiente contenido:

"Hola, XXXXXXXXXXX:

Hemos recibido una petición para eliminar tu cuenta de Facebook permanentemente. Tu cuenta está ya inhabilitada y será eliminada de forma permanente en los próximos 14 días.

Si no deseas eliminar tu cuenta, haz clic en el siguiente enlace para cancelar la petición:

http://www.facebook.com/account_delete.php

Gracias,
El equipo de Facebook"

miércoles, abril 07, 2010

¿Por qué no funciona la etiqueta s:if al comparar con cadenas?

Usando Struts 2 me he encontrado con un problema que, a simple vista, no debería serlo.

Usando la etiqueta <s:if...> intentaba comparar el valor de una propiedad de un objeto en el ValueStack (proveniente de un action a través del ModelDriven) y una cadena. En concreto un 'N'.

Pero nunca llegaba a cumplirse la condición. Me aseguré de que la propiedad tuviera el valor adecuado, pero aún así, nada. El código que usaba era este:


<s:if test="%{nombre_propiedad eq 'N'}">...


La solución la encontré aquí. El problema es que ONGL no interpreta correctamente los char como string. La solución, hacer que compare con cadenas (entre comillas dobles) y no con caracteres (comillas simples):


<s:if test='%{nombre_propiedad eq "N"}'>...


Espero que os sirva.

martes, abril 06, 2010

JPA: Modificar unidades de persistencia programáticamente

Si trabajáis con JPA, nosotros concretamente con Netbeans (aunque en Eclipse funciona de forma similar), durante el desarrollo de las aplicaciones, procedemos a crear un modelo de datos y a desplegar el modelo físico sobre nuestro motor de base de datos.

En el caso de Netbeans, mediante wizards, creamos nuestra conexión, la unidad de persistencia ("persistence.xml") y podemos generar nuestras entidades a partir del modelo físico.

¿Y el proceso inverso?. Supongamos que ya tenemos nuestra aplicación y lo que queremos es que al desplegar nuestra aplicación en los servidores de producción, en base a nuestras entidades, se recree la base de datos, sin necesidad de hacer una importación (debe existir el esquema y el usuario, por supuesto, pero no es preciso importar las tablas "manualmente").

Esto es posible modificando programáticamente una unidad de persistencia existente en el archivo "persistence.xml". Con un poco de trabajo, se puede crear un "wizard" en nuestra aplicación que detecte si la instalación es nueva y que sea capaz de recrear las tablas en base a nuestras entidades ya existentes.

Al menos, esta es la forma que hemos encontrado de hacerlo... es posible que haya formas mejores.

(Este ejemplo enlaza con el post anterior sobre el motor InnoDB de MySQL. En nuestro caso, las tablas originales eran InnoDB, pero cuando se recreaban las tablas en otro esquema, aparecían como MyISAM.)

En el ejemplo, uso TopLink Essentials, de Oracle. Las propiedades para Hibernate o EclipseLink, varían.

Este sería nuestro archivo "persistence.xml". Como véis, no tiene propiedades. Sólamente declaramos el nombre de la unidad, el proveedor y las entidades, pero no las propiedades:


<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="PersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>oracle.toplink.essentials.PersistenceProvider</provider>
<class>test.entities.Entidad2</class>
<class>test.entities.Entidad1</class>
</persistence-unit>
</persistence>


Modificar la unidad de persistencia pasando las propiedades programáticamente, es simple:


Properties props = new Properties();
props.put(TopLinkProperties.JDBC_USER,"user");
props.put(TopLinkProperties.JDBC_PASSWORD,"password");
props.put(TopLinkProperties.JDBC_URL,"jdbc:mysql://hostname:3306/targetddbb?sessionVariables=storage_engine=InnoDB");
props.put("toplink.ddl-generation","create-tables");
props.put(TopLinkProperties.JDBC_DRIVER,"com.mysql.jdbc.Driver");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnit",props);
EntityManager em = emf.createEntityManager();
em.close();
emf.close();


Si os fijáis, hay una propiedad "toplink.ddl-generation", con el valor "create-tables". Esto hace que al instanciar el objeto EntityManager, se regeneren las tablas en la base de datos, en base a las entidades declaradas en "persistence.xml" y asociadas a la unidad "PersistenceUnit". Es decir, sólo con ejecutar este código, se regeneran las tablas.

Por último insistir en que para realizar las pruebas, hemos usado:

- Netbeans 6.8
- TopLink Essentials
- MySQL

Los esquemas de origen y destino de nuestras tablas eran MySQL. No hemos probado a regenerar las tablas en una base de datos distinta...

MySQL: forzar la creación de tablas InnoDB

Hola a todos,

es posible que en alguna ocasión al crear nuevas tablas en MySQL os encontréis con que por defecto las tablas se crean con el motor MyISAM, en lugar de InnoDB. Esto ocurre porque en la instalación del servidor se ha seleccionado MyISAM como motor por defecto.

La primera solución que se nos puede ocurrir es modificar la configuración de MySQL para que el motor por defecto sea InnoDB. Esto tiene sus inconvenientes, ya que en un entorno de producción modificar la configuración del servidor puede ser un problema.

Sin embargo, hay una solución muy simple y que evitará que nos peleemos con el administrador de turno. En la propia cadena de conexión de MySQL, podemos pasar parámetros adicionales que modifican la forma en que el servidor se comporta para dicha conexión. El detalle de estos parámetros se puede consultar aquí (es para la versión 5.5, pero existen para versiones anteriores):

http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-configuration-properties.html

El parámetro que nos interesa se llama "sessionVariables". En este parámetro se puede pasar múltiples valores separados por coma que determinan el funcionamiento de la sesión de MySQL.

En concreto para forzar que el motor por defecto durante nuestra sesión sea InnoDB, deberíamos crear una conexión de este tipo:

"jdbc:mysql://hostname:3306/ddbbname?sessionVariables=storage_engine=InnoDB"

De esta manera, cualquier sentencia "CREATE TABLE" creará tablas InnoDB aunque el motor por defecto sea otro.