miércoles, 13 de febrero de 2008

Plataforma de gobierno electrónico

Hace pocos días se realizó una pre-publicación (*) de una licitación pública que tiene como objetivo incorporar una plataforma basada en SOA para el desarrollo del gobierno electrónico en el Uruguay.

Como se anuncia en el sitio web de AGESIC (Agencia para el Desarrollo del Gobierno de Gestión Electrónica y la Sociedad de la Información y el Conocimiento), dicha plataforma deberá proporcionar el ambiente normativo legal, normativo técnico, así como los instrumentos informáticos necesarios para facilitar la instalación de aplicaciones y servicios de Gobierno Electrónico en el Estado Uruguayo.

Los requisitos que se detallan en los pliegos son bastante concretos, plantea alternativas basadas en tecnologías JEE o Microsoft .NET. Se realizarán tres licitaciones simultáneas:

  1. Middleware y Metadata
  2. Herramienta de Portal
  3. Control de Acceso
Me resultó muy interesante el concepto de metadata que proponen, extraigo textualmente:



El soporte de Metadatos debe contar con las siguientes características:

Permitir la definición distribuida, integrada y uniforme de objetos de la metadata.
  • Distribuida: Diferentes organismos pueden mantener diferentes aspectos de cada objeto de la metadata (para BPS "beneficiario" es una persona que recibe determinadas prestaciones que se representan como determinadas propiedades en la metadata. Para MSP, "paciente" es una persona que tiene derecho a determinados servicios que también se representan como propiedades asociadas. Cada organismo agrega las propiedades que correspondan.)
  • Integrada: Todos los organismos trabajan sobre los mismos objetos de la metadata. En el ejemplo anterior, las prestaciones y los servicios de salud deben quedar integrados en el objeto persona.
  • Uniforme: Debe proveerse una visión de los objetos, propiedades y restricciones de la metadata que sea común y estándar a todos los consumidores de la misma.


Queda claro que la idea es evitar la situación actual, donde cada organismo tiene definido en su esquema persistente, de forma redundante, los datos de toda la población. Lo que se propone es que exista una definición común a todos, pero que cada "consumidor" pueda complementar la metadata con la información que necesita mantener.

Dejo los links de los pliegos:

LICITACION_01-2008_MIDDLEyMETADATA_vF.pdf 1,6Mb
LICITACION_02-2008_CONTROL_ACCESO_vF.doc.pdf. 1,2Mb
LICIT_PORTAL_vBorrador.pdf 1,9Mb

(*) Nota: El 20/02/2008 se realizó la publicación final de los pliegos para Middleware y Metadata, y Control de Acceso.

viernes, 1 de febrero de 2008

equals y hashCode en Hibernate

La clase java.lang.Object, de la cual heredan todas las demás clases, define dos métodos muy importantes:

public boolean equals(Object obj)
public int hashCode()

El API de Java describe un conjunto de reglas que deben cumplir ambos métodos en caso de sobreescribirlos, la idea del post no es repetir esos fundamentos teóricos, sino plantear una receta muy sencilla para implementarlos.

Como norma siempre los sobrescribo en todas las entidades usando como clave de comparación una combinación de atributos con significado de negocio (business key) que me asegure la unicidad del objeto.
Si usamos la funcionalidad de id autogenerado (generator class="native"), debemos descartar éste atributo porque es asignado luego de que el objeto es salvado, hasta ese momento el id es null.

Para implementar los métodos me baso en la librería Commons Lang de Apache, es muy probable que ya tengan el jar en el classpath si usan otros frameworks open source, en caso contrario es solo bajarlo del sitio web.

Vamos al grano, por ejemplo si tenemos una entidad Pais (id, codigoISO, nombre), el atributo candidato que nos asegura la unicidad es el código ISO, por lo tanto la implementación sería:


public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(this.codigoISO)
.toHashCode();
}

Instanciamos el HashCodeBuilder con dos números primos diferentes y luego hacemos append de los atributos que definen la business key, en éste caso solamente el codigoISO.

public boolean equals(Object object) {
Pais otroPais = (Pais)object;
return new EqualsBuilder()
.append(this.codigoISO, otroPais.getCodigoISO)
.isEquals();
}

Instanciamos el EqualsBuilder y luego hacemos append de la comparación de los atributos que definen la business key, en éste caso solamente el codigoISO.

Para no tener comportamientos inesperados en la aplicación, es recomendable siempre sobreescribir los métodos equals y hashCode en todas las entidades persistentes, usando ésta librería nos aseguramos que lo hacemos de manera consistente.

Nota: En los ejemplos falta contemplar la posibilidad de NullPointerException o ClassCastException, eso lo dejo como tarea ;-)

Hasta el próximo post!!

viernes, 25 de enero de 2008

Schema Update en Hibernate

Una de las funcionalidades que extrañaría mas si dejara de usar Hibernate es la capacidad de impactar el esquema de la base de datos en forma incremental y automática. Afortunadamente, nos podemos centrar en crear las entidades de negocio como POJOS, con sus atributos y relaciones sin tener la necesidad de crear manualmente las tablas, todo ésto mediante la tarea Ant SchemaUpdate.

Por ejemplo cuando agregamos una nueva entidad al hibernate.cfg.xml o nuevos atributos/relaciones a una entidad existente, al ejecutar la tarea se realiza una comparación entre el esquema de la base de datos actual y el que se deduce a partir de los mappings de Hibernate con las modificaciones. Tomando en cuenta las diferencias, se ejecutan las sentencias SQL necesarias para sincronizar el modelo (básicamente CREATE TABLE ... y ALTER TABLE ...).

Debemos incluir en el build.xml el siguiente target:

<target name="schema.update" description="Update Schema" depends="build">
<taskdef name="schemaupdate" classname="org.hibernate.tool.hbm2ddl.SchemaUpdateTask"
classpathref="class.path">
<schemaupdate config="${conf.dir}/hibernate.cfg.xml"
quiet="no"
text="no">
</schemaupdate>
</taskdef>
</target>

Es importante aclarar que ésta herramienta no borra estructuras ya creadas, es decir no hace DROPS de tablas ni campos que hayan quedado sin usar, tampoco crea índices definidos por el programador (las restricciones de integridad referencial si las crea). La gente de Hibernate no lo considera un bug, según la documentación oficial, el SchemaUpdate está pensado para usarse en ambiente de desarrollo, se basa en la metadata que brinda el API JDBC, el cual no es consistente en todos los drivers. Como comentario, yo lo vengo usando desde hace tiempo sin problemas con MySQL, solo tengo en cuenta la restricción de los índices, los cuales creo manualmente.

Además de la tarea Ant, también es muy útil la opción para que el esquema se actualice automáticamente en el start up de la aplicación. En el hibernate.cfg.xml, mediante el property:
<property name="hbm2ddl.auto">update</property>

indicamos que la primera vez que se use la SessionFactory, ejecute las modificaciones a la base de datos, al igual que lo haría la tarea Ant. Ésta opción la uso mucho para las instalaciones en producción, en desarrollo uso Ant para no enlentecer los deploys.

Hasta el próximo post!