lunes, 21 de marzo de 2011

java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to java.lang.String

Ver lo que tenemos delante de nuestras narices requiere una lucha constante.
-- George Orwell (1903-1950) Escritor británico.

Un error en tiempo de ejecución como éste: java.lang.ClassCastException: [LFQN_ClassName; cannot be cast to FQN_ClassName, puede dejarte con cara de perplejidad durante algunos minutos. A mi me pasó. Y reconozco cierta vergüenza al admitir que fueron unos cuantos largos minutos en los que no daba crédito. Estaba tan concentrado en que el casting era correcto que no podía entender cómo la JVM me decía que no podía adaptar un tipo de dato a otro exactamente igual... Al cabo de unos minutos me di cuenta que la clave está en el corchete ("["). No se trata del mismo tipo: la máquina virtual me está diciendo que no puede convertir un array de ese tipo a ese mismo tipo (directo).

En efecto, el capítulo 4.3 de la especificación de la máquina virtual referente al fichero class, lo explica bien claro: estamos intentando convertir una instancia de String[] a String. En fin, es de estas veces que tienes la solución delante pero no la estás buscando: estás en otra cosa.... Hay que confiar más en los mensajes de error.

Por cierto que no veo sustituto de ésta url en el dominio oracle.com... así que puede que no esté disponible a partir del 1 de junio. Así es, amigos, uno de los primeros dominios que se registraron y más antiguos, dejará de existir (desaparecerá, en palabras de Oracle).


Referencias y más información:

miércoles, 9 de marzo de 2011

Balteus cumple 10 años (en binario)

(Ilustración: Fran Barquero)
- "¿Le gusta nuestro búho?" -Rachael
- "¿Es artificial?" - Rick Deckard
- "Naturalmente." - Rachael
--Blade Runner.


El pasado domingo 6 de Marzo, este blog cumplió su segundo año de vida. Y he aprovechado la ocasión para hacerle un sutil cambio en el diseño, en la línea del anterior: sobrio y sencillo. Espero que os guste.

Este año me han ocurrido algunas situaciones anecdóticas y relevantes para mi, teniendo en cuenta que soy un escritor de un blog muy especializado y con pocos lectores asiduos. La primera me ocurrió con mi post "La galaxia en un campo de fútbol", en el que comenté el libro de Juan Fernández Macarrón y el propio Juan me dejó un afectuoso comentario (también me pasó en el artículo sobre Logback: también el autor comentó en mi web).  La segunda es que enlazaron mi artículo sobre el control del nivel de aislamiento transaccional con JPA en "The Aquarium", el blog de referencia sobre Java EE y Glassfish. Fue una grata sorpresa, la verdad.

Por otro lado, este año he sido menos prolífico que el primero, y no por falta de temas, sino por falta de tiempo. También he encontrado que los lectores habituales son "silenciosos" y no tienen tiempo y/o ganas de comentar mis artículos (en fin, sois así, ¿qué le vamos a hacer?).

También he contado con un regalo-ilustración realizado especialmente para la ocasión. Gracias, Fran, por la ilustración. Me ha hecho mucha ilusión.

A mis lectores frecuentes: gracias por seguir por ahí... y dejad algún comentario, por favor!. Me gusta saber que hay alguien ahí leyendo.

P.D.: Si veis algo que ha quedado "raro" con el cambio de diseño, por favor, decídmelo.

lunes, 28 de febrero de 2011

Documentación de código con Doxygen y Maven


Voluminous documentation is part of the problem, not part of the solution.
-- Tom DeMarco, software development consultant
Documentation is like sex: when it is good, it is very, very good; and when it is bad, it is better than nothing.
-- Dick Brandon

La documentación de proyectos software siempre ha sido un tema controvertido. Aspectos como la estructura, enfoque, perspectiva, y metodología han generado decenas de tratados y "estándares" (como sinónimo de modelo, patrón o referencia) tan voluminosos como imprácticos e irrealistas. Sin embargo, ya comenté en "La falacia de la Ingeniería del Software" mi poca confianza en la aplicación realista de muchas metodologías y estándares que comparten entre sí la escasez de referencias reales profesionales.

Mi experiencia a la hora de documentar un proyecto para la cesión de  administración y mantenimiento a terceros me ha enseñado que la documentación sólo sirve si:
  • está contínuamente actualizada y sincronizada con lo que documenta (el adverbio continuamente aquí, es clave)
  • la documentación y lo documentado están mutuamente accesibles
  • tiene estructura y formato ágil para la consulta
Por supuesto, creo que los aforismos "cuanta más documentación mejor" o "toda documentación que se haga es poca" son del todo erróneos. El objetivo es la calidad, y creo honestamente que la cantidad participa de forma inversamente proporcional en una ecuación de calidad.

En lo que a documentación de código se refiere, los objetivos anteriores se obtienen con creces con sistemas de generación de documentación automatica:
  • La documentación está junto a lo documentado favoreciendo la contínua actualización
  • Están mutuamente accesibles
  • La estructura es la idónea para facilitar el acceso a la documentación precisa fácilmente ya que suelen generar HTML
En este aspecto, la mejor herramienta que he probado hasta ahora es, sin duda y con diferencia, Doxygen.

Doxygen es un generador de documentación gratuito para  C++, C, Java, Objective-C, Python, IDL, Fortran, VHDL, PHP, C# y D. Su licencia es GPL y sus resultados son comparables (e incluso mejores en algunos aspectos) a documentadores comerciales.

Los desarrolladores de Java, que ya conocen Javadoc, cuya generación está perfectamente integrada con Maven, se preguntarán para qué diablos necesitarían otro documentador. Como se comenta en la segunda cita introductoria de este artículo, Javadoc está bien: es mejor que nada. Pero comparar Doxygen con Javadoc es equivalente a comparar maven con "make".

Las características más destacables, frente a Javadoc, desde mi punto de vista:
  • Genera automáticamente diagramas de clase y colaboración. Opcionalmente, diagramas de dependencia, llamada, etc... 
  • Permite incluir el código fuente resaltado en la propia documentación
  • Formatos: HTML,CHM, PDF, XML, etc..
Doxygen es una utilidad basada en línea de comando, como Javadoc, con más 100 opciones configurables que permiten ajustar la documentación final. Aunque la mayoría de las opciones interesantes ya están configuradas por defecto, Doxygen cuenta con un frontal gŕafico (doxywizard) muy util para gestionar las opciones y los ficheros de configuración. Se instala fácilmente ("sudo apt-get install doxgen-gui", en *ubuntu) existiendo distribuciones en código fuente y binarios para Mac OS y Windows... y, he aquí lo mejor: existe un plugin para maven.

Usando Doxygen con Maven
De la misma forma que podemos automatizar la generación de documentación javadoc en nuestras construcciones con maven, podemos hacerlo con Doxygen. Para ello, tan sólo debemos seguir los siguientes pasos:
  1. Instalar Doxygen y hacerlo disponible en el path (para *ubuntu esto es automático con la instalación)
  2. Añadir el plugin a nuestro pom.xml. A continuación muestro las opciones de configuración que yo suelo usar

    ...
    
        
            
                com.soebes.maven.plugins.dmg
                doxygen-maven-plugin
                1.0.1
            
        
    
    ....
    
        
            
                com.soebes.maven.plugins.dmg
                doxygen-maven-plugin
                1.0.1
                
                    false
                    es.cestel.szarza.balteus
                    1.0
                    spanish
                    true
                    true
                    true
                    true
                    src/main
                    true
                
            
        
    
    ....

Recomiendo probar con las opciones de generación de diagramas. Especialmente los diagramas de colaboración pueden ser muy útiles para ciertos módulos de proyecto.


Referencias y más información:


lunes, 31 de enero de 2011

StatementTimeout / QueryTimeout con PostgreSQL

Si no esperas lo inesperado no lo reconocerás cuando llegue.
- Heráclito de Efeso (540 AC-470 AC) Filósofo griego

Como comentaba en "las 8 falacias de los sistemas distribuídos", en los entornos de producción debemos tener en cuenta que pueden suceder hechos que no se producen en nuestros entornos de desarrollo, integración o preproducción... y ciertamente ocurren. En estos entornos son necesarios procesos y tareas concurrentes inherentes a su propia naturaleza y ambiente de "explotación" (tareas de mantenimiento tanto programados -backups-, como no programados -recuperaciones de datos-, arranque eventual de otras -nuevas- aplicaciones, procesos de datawarehousing, etc).

Uno de estos sucesos típicos suele ser el inexplicable y aleatorio bloqueo de una sesión o de toda una aplicación entera. Tras el correspondiente susto y examen exhaustivo, detectamos la causa en una consulta de base de datos que, eventualmente, tarda demasiado. En algunas ocasiones las causas son muy poco evidentes y muy difíciles de detectar, ya que sólo se producen por la coincidencia de determinados eventos (periódicos o no), e incluso en un determinado orden.

¿Y por qué tarda tanto una consulta que en nuestro entorno de preproducción se lleva apenas unas pocas decenas de milisegundos? Pues típicamente porque ocurre un bloqueo en la base de datos debido a una transacción de larga duración. Si las cosas se complican, puede existir incluso un deadlock (bloqueo mutuo) que deje nuestro sistema completamente bloqueado y produzca un efecto dominó en otras aplicaciones dependientes de la misma base de datos.

Obviamente, la solución pasa por detectar la casuística concreta y evitarla, pero mientras buscamos la causa o la solución, necesitamos mantener nuestro sistema funcionando con normalidad. Para protegernos a este tipo de eventualidades, se debe establecer un valor de timeout en nuestras consultas y transacciones a bases de datos que impida que una consulta se quede indefinidamente esperando el resultado y, por tanto, todas las sesiones de la aplicación que llegan a ese punto. En los entornos JEE, donde se configuran pools de conexiones a bases de datos que permiten un uso eficiente de recursos y conexiones de bases de datos, la ausencia de estos timeouts en esas condiciones pueden suponer el agotamiento de las conexiones del pool, debido a que no se liberan las conexiones y, por tanto, la imposibilidad de que nuevas sesiones de la aplicación puedan funcionar.

Configuración de Statement Timeout en Glassfish
En la mayoría de los servidores de aplicaciones y contenedores web JEE, existe una forma de indicar este parámetro para cada uno de nuestros pools, permitiendo especificar distintos parámetros en función de las características de las aplicaciones o de la duración de las transacciones. En el caso de Glassfish, por ejemplo, es a través del atributo StatementTimeout del pool (que internamente realiza las llamadas a setQueryTimeout() del driver.


Usando PostgreSQL, este atributo sin embargo nos ha dado una desagradable sorpresa:

Caused by: org.postgresql.util.PSQLException: Method org.postgresql.jdbc4.Jdbc4PreparedStatement.setQueryTimeout(int) is not yet implemented.
        at org.postgresql.Driver.notImplemented(Driver.java:753)
        at org.postgresql.jdbc2.AbstractJdbc2Statement.setQueryTimeout(AbstractJdbc2Statement.java:635)
        at com.sun.gjc.spi.base.ConnectionHolder.prepareStatement(ConnectionHolder.java:477)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.prepareStatement(DatabaseAccessor.java:1162)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseCall.prepareStatement(DatabaseCall.java:612)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:485)

Pues si, aunque parezca increíble, el driver jdbc de Postgresql no implementa aún setQueryTimeout(), al menos hasta la versión disponible en el momento de escribir este artículo (versión Version 9.0-801 de 2010-09-20).

Establecimiento de propiedades de la conexión en el pool de conexiones de Glassfish
La solución es establecer el parámetro de conexión SocketTimeout, que especifica en segundos el tiempo máximo que se espera respuestas del servidor antes de cerrar la conexión. Este parámetro tiene el mismo efecto que el atributo StatementTimeout / QueryTimeout que comentaba anteriormente.


Para nuestros scripts PL/pgSQL, podemos establecer directamente el parámetro statement_timeout al inicio:

SET statement_timeout TO 5000; -- para 5 segundos

 <...resto del PL>

RESET statement_timeout; -- reset

En general, establecer un valor de timeout en operaciones síncronas es una buena práctica para evitar sorpresas desagradables.

lunes, 27 de diciembre de 2010

2010: El fin de una etapa

Este año que ha terminado ha sido extraño y agridulce en lo que a acontecimientos y efemérides se refiere.

En el pasado 2010 se han cumplido 25 años desde que se registró el primer dominio .com (symbolics.com). Aquél año de 1985 se registraron 7 dominios. Hoy hay registrados más de 80 millones. En cuanto a los dominios .es, comenzaron a registrarse en el año 1997 y hoy, dominios.es (anterior ES-NIC) cuenta con más de 1.200.000 dominios registrados.

También ha sido el cumpleaños de Java, ya que según su creador, fue hace 15 años cuando nació Java, si bien la primera versión se publicó en 1996.

Decía Unamuno que el progreso consiste en renovarse. Sea ésa la última causa o sea por causas pecuniarias más prosaicas, el caso es que este año 2010 ha sido el fin de Sun Microsystems, tras la confirmación de compra que se produjo finalmente por estas fechas el año pasado. Esta compra ha producido una preocupante desbandada de personas de esencial relevancia en las filas del antiguo Sun, ahora Oracle. Desde el propio CEO de Sun, Jonathan Schwartz, pasando por Tim Bray (coinventor del XML) hasta incluso el mismísimo James Gosling (creador de Java), la lista no ha cesado: Eduardo Pelegri (lider de la especificacioń Java EE, padre de JSP, y responsable de Glassfish), Simon Phipps (Sun's Chief Open Source Officer), casi todo el equipo de OpenOffice.... SunOracle ha perdido un enorme valor humano. Se diría que Oracle tiene una filosofía con un enfoque totalmente diferente, en lo que a su postura con el FOSS e innovación se refiere... ejem.

En sus 28 años de vida como empresa independiente (de momento Oracle mantiene la marca) Sun ha sido sinónimo de innovación, seriedad, escalabilidad y grandes sistemas. El procesador SPARC (la primera arquitectura RISC-II implementada comercialmente), el sistema de ficheros NFS, el Sistema Operativo Solaris (con ZFS, en su versión 10), Java (JSE, JEE, y resto de estándares asociados) han sido innovación directa de Sun Microsystems y legado tecnológico sobre el cual se han basado decenas de avances actuales hoy día.

Tras la absorción de Sun por parte de Oracle, el futuro de productos de código abierto como Glassfish, MySQL, Java, etc, es una incógnita, como ya comenté en un anterior artículo. Comienza a partir de aquí una nueva etapa para las tecnologías Java.

Veremos qué nos depara 2011.

¡Feliz año nuevo a todos!

jueves, 9 de diciembre de 2010

Las 8 falacias de la informática distribuída

En 1994, Peter Deutsch, uno de los miembros originales de Sun Microsystems, afirmó que arquitectos, diseñadores, y programadores de aplicaciones distribuidas a menudo solían asumir 7 supuestos que, en última instancia, resultaban falsos, poniéndose de manifiesto en forma de fallos del sistema, reducción sustancial en el ámbito de aplicación del sistema, o en grandes gastos imprevistos necesarios para rediseñar el sistema de forma que pueda cumplir con sus objetivos originales. En 1997, James Gosling (creador de Java) añadió un octavo supuesto.

Esas hipótesis son conocidas conjuntamente como Las 8 falacias de la informática distribuída o las 8 falacias de los sistemas distribuídos (8 fallacies of distributed computing):

  1. La red es confiable
  2. La latencia es cero
  3. El ancho de banda es infinito
  4. La red es segura
  5. La topología no cambia
  6. Hay un administrador
  7. El costo del transporte es cero
  8. La red es homogénea



Explicar cada una de las falacias (explicar por qué lo son) es bastante obvio. De hecho, llama la atención la adición de la falacia nº 8 en 1997 cuando realmente la heterogeneidad no era ni la centésima parte de lo que es ahora, con decenas de tipos de redes y dispositivos de distintas características accediendo simultáneamente a los mismos sistemas.

15 años después, las características y problemas subyacentes de los sistemas distribuídos siguen siendo más o menos los mismos. Cualquiera que haya puesto en producción sistemas distribuídos (qué sistema empresarial actual no lo es) ha sufrido la mayoría (si no todas) de estas realidades.

Definitivamente, lo que hay que tener claro es que no es posible proteger un sistema frente a todas estas eventualidades de forma indefinida ni es simplemente una cuestión de tecnología. Preservar a un sistema de las consecuencias de estos hechos ahora (es decir, para un momento concreto en el tiempo) es muy caro, así que se tiene que llegar a un compromiso entre el coste y riesgo que se quiere asumir. Incluso aún cuando se proteja de forma razonablemente un sistema, habremos de tener en cuenta que los sistemas crecen y evolucionan. Si no se presta atención a las cuestiones abarcadas por las falacias, llegará un momento en que la situación haya cambiado de forma sustancial y quede nuevamente expuesto.

Por tanto, estas falacias no solamente deben tenerse en cuenta en las etapas de diseño y construcción de un sistema, sino también (e incluso de forma especial) en la de mantenimiento, porque llegará un momento en que se mostrarán sus consecuencias... y no será tan tarde como imaginamos.


Referencias y más información:



Related Posts Plugin for WordPress, Blogger...
cookieassistant.com