miércoles, 29 de diciembre de 2010

Fechas con un día menos en Flex y Java usando BlazeDS

   Cuando trabajamos con fechas en entornos con Flex y Java debemos tener cuidado de un curioso efecto, al cargar una fecha correcta en Java en Flex puede verse con un día menos.

   Este efecto se debe a como son transferidas las fechas entre un servidor Java y un cliente Flex, para ello se serializa la fecha en UTC, es decir sin información de la zona horaria. La conversión a la hora local se realiza a nivel del protocolo de forma automática, por lo tanto si el servidor no conoce la zona horaria del cliente no podrá transformarla adecuadamente. Dependiendo de la aplicación puede ser deseable almacenar/recuperar los datos en la zona horaria del cliente que los guarda, pero en la mayoría de los casos no lo es.

La solución (tal como se indica en el CookBook de Flex) consiste en forzar que la fecha se intercambie sin la información de la zona horaria. Para ello modificaremos los métodos accesores (getters y setters) de las fechas tanto del objeto java, como en el objeto en actionscript de forma que intercambiemos la fecha como el numero de milisegundos desde 1970 menos la cantidad añadida por la zona horaria (para que la trate como en GMT+0). Los objetos quedarían  así:
Java
package com.fraguaDigital;
 
import java.io.Serializable;
import java.util.Date;
import java.util.TimeZone;
 
public class MiClase implements Serializable {

    // ... Otros atributos ...
 
 private Date _fecha;
 public Date getFecha() {
  Date newDate = new Date(_fecha.getTime() - TimeZone.getDefault().getOffset(_fecha.getTime()));
  return newDate;
 }
 public void setFecha(Date value) {
  Date newDate = new Date(value.getTime() + TimeZone.getDefault().getOffset(value.getTime()));
  this._fecha = newDate;
 }
}

ActionScript (Flex)
package com.fraguaDigital
{
 [RemoteClass(alias="com.fraguaDigital.MiClase")]
 public class MiClase
 {
     // ... Otros atributos ...
  
  public var _fecha:Date;
  public function set fecha(value:Date):void {
   var newDate:Date = new Date(value.valueOf() - value.timezoneOffset);
   this._fecha = newDate;
  }
  
  public function get fecha():Date {
   var newDate:Date = new Date(_fecha.valueOf() + _fecha.timezoneOffset);
   return newDate;
  }
 }
}

Con esto ya las fechas llegarán correctamente al cliente.

sábado, 6 de noviembre de 2010

Características del sistema desde un cliente Flex/Flash

Cuando desarrollamos aplicaciones web debemos tener en cuenta que nuestra aplicación se puede utilizar desde diferentes plataformas, y por tanto tenemos que tener en cuenta las posibilidades de cada plataforma. Un ejemplo claro de está situación es la pantalla, para un dispositivo móvil puede tener resoluciones más pequeñas que para un ordenador de sobremesa, así mismo cada sistema puede tener configuradas diferentes resoluciones o profundidad de color.

Vista esta situación, cuando desarrollamos una aplicación, podemos adaptar nuestra aplicación al entorno en el que se ejecutará. Para esto, tenemos una gran ayuda en la clase flash.system.Capabilities, esta clase proporciona propiedades que describen el sistema y el runtime del host. Dicha clase nos permite conocer, entre otras cosas, lo siguiente: 
  • Tamaño de la pantalla: ancho y alto de la pantalla por searado en las variables screenResolutionX screenResolutionY respectivamente.
  • Si tenemos información de depuracion: variable isDebugger.
  • La arquitectura de la CPU: variable cpuArchitecture.
  • Si podemos usar audio, vídeo, si tenemos codecs para audio y vídeo, o si podemos reproducir streams de audio y/o vídeo.
  • Si el host puede imprimir
  • etc.
Podemos ver la lista completa de propiedades en la documentación de la clase.

Como veis, es una buena idea adaptar nuestras aplicaciones al host donde se ejecutará, ya sea la resolución, la reproducción de audio o vídeo (dependiendo de la naturaleza de la aplicación), para de esta forma conseguir una mejor experiencia de usuario.


lunes, 23 de agosto de 2010

Identificador único en objetos Java

Recientemente hice una pequeña investigación sobre la mejor forma  de identificar una instancia de un objeto de forma única, de forma que podamos utilizar dicho UID (Unique identifier). Este identificador puede ser muy útil a la hora de cachear instancias , por ejemplo en un HashMap.

Documentándome un poco por la red, he leído muchas "soluciones", algunas más acertadas y otras menos, y he aquí el verdadero motivo de que escriba esta entrada.

Cualquier desarrollador con un poco de experiencia en Java sabrá que esto se resuelve usualmente mediante el método hashCode, el cuál genera un código de hash para un objeto, que nos permite indexarlo fácilmente. Pero, ¿que pasa cuando se han sobrecargado dicho método generando un override del objeto que cambia su funcionalidad?. Este escenario es bastante habitual, ya que se suelen generar los métodos equals y hashCode, para poder comparar objetos y saber a igualdad de datos si se trata del mismo objeto.

Una cosa que ha llamado mi atención en particular es que en muchos sitios proponen usar el método toString, para obtener a un identificador único, siempre y cuando no se halla sobreescrito dicho método en las clases. Esta suposición no es errónea per se,  pero resulta curiosa la forma de usar dicho método, y las limitaciones que conlleva (ya que no podremos modificar el método toString). Este método se basa en la implementación del método toString en la clase java.lang.Object, el cuál concatena el nombre de la clase con el hashcode y no con la dirección de memoria como cree mucha gente. El formato de la String devuelta  puede verse en la documentación de Java):

public String toString() {
   return getClass().getName() + '@' + Integer.toHexString(hashCode());
 }

Si esto es así, dicha solución tampoco funcionará en todos los casos, si hemos hecho un override del método hashCode basándonos en algunos datos, o cuando menos no podemos decir que la "resistencia a colisiones" sea alta.

En estas situaciones lo mejor sería utilizar el método hashCode original de la clase Object, el cual asegura que dos instancias distintas, aún cuando tengan los mismo datos, devolverán un hashCode diferente. Esto se debe a que el calculo de los datos se hace de forma nativa en base a la dirección de memoria donde se encuentra la instancia:

public int hashCode() {
   return VMMemoryManager.getIdentityHashCode(this);
 }

Para acceder al método de forma independiente de si lo hemos sobreescrito podemos usar la clase System, llamando al metodo identityHashCode.

System.identityHashCode(object);

Otra opción un poco más "delicada" es usar la clase sun.misc.Unsafe, para obtener la dirección real de memoria, podemos leer un poco más sobre ello aquí. esto es algo totalmente irrecomendable, que tiene cabida sólo como investigación para aquellos que gusten de saber como funcionan las cosas (Para que la llamaron Unsafe si no querían que trasteáramos con ella. XD).



lunes, 5 de julio de 2010

Primeras impresiones de Bonita 5 (aka Bonita Open Solution)

Bueno después de haber avanzado allá por Octubre la preview de la versión 5 de Bonita me había olvidado un poco de ella, pero hoy he comenzado a instalar y probar la versión 5.0.1 (ya ha salido la 5.02) y quería compartir mis primeras impresiones.

Para empezar diré que la estructura se mantiene más o menos igual. se puede desplegar la aplicación web y personalizar ciertos aspectos o bien desplegar el "runtime" en un servidor de aplicaciones para conectarnos a el mediante RMI.

Les dejo una pequeña valoración inicial con algunos aspectos que he encontrado en este primer acercamiento:

Aspectos positivos:
  • A nivel de la API han habido algunos cambios, ya que ha cambiado algo el modelo y se han añadido ciertas funcionalidades como por ejemplo la "reparacion de casos".
  • Donde se observan las mayores diferencias es en el cliente web. Han desarrollado un cliente totalmente nuevo, algo muy acertado a mi juicio, ya que el anterior fallaba bastante.
  • El BonitaStudio (desarrollado sobre eclipse), parece mucho más completo que las versiones anteriores de las herramientas de diseño.

Aspectos negativos:
  • El proceso de instalación es el mayor problema que he encontrado hasta el momento, el cuál es complicado y la documentación al respecto es insuficiente. Personalmente he trabajado con versiones anteriores de Bonita y esto parece ser un problema recurrente, imagino como sufrirá un usuario nuevo para llevar a cabo la instalación. Quién haya instalado antes Nova Bonita , no tendrá problemas para isntalar el runtime pero la aplicación web puede que le ed algún que otro problemilla.
  • No existe documentación para la API, o no esta disponible, tán sólo podemos acceder al javadoc de la API. He podido detectar algunos cambios gracias a los proyectos existentes con librerías (bonita-client) anteriores.
  • No hay compatibilidad con flujos anteriores. Esto hay que matizarlo, yo puedo importar un Bar de Bonita 4, pero hay una alta probabilidad de que no funcione si contenía lógica, por ejemplo Hooks. Se puede importar al BonitaStudio pero la importación no es del todo correcta y hay que arreglar los flujos. Además no trabajamos con un fichero XPDL sino que importaríamos el .bar.

Una vez que se ha instalado y comprobado que funciona correctamente, es necesario migrar las aplicaciones para usar la nueva API y hay que aprender a usar la nueva herramienta de diseño, ya que ha cambiado completamente. Esto implica que una migración requiere un coste relativamente alto, esto sin hablar de migrar las instancias existentes en un sistema antiguo al nuevo.

Seguiré comentando. Saludos.

Felicidades

Este post, aunque haya tardado un poco, es para celebrar que hay una nueva ingeniera informática en la familia, Felicitaciones a Amelia por haber presentado su proyecto final de carrera, titulado: "Adquisición de datos de una red de anemómetros.", cuya funcionalidad se basa en la recogida de muestras de viento a partir de sensores (anemómetros), para almacenarlas en una base de datos.

A dichos datos puede accederse a partir de una aplicación web rica. Toda la aplicación ha sido desarrollada con tecnologías openSource (Java, Spring, Hibernate en el servidor y Flex con BlazeDS en el cliente).

Espero que de ahora en adelante pueda participar más en el Blog .