En datanucleus existe un mecanismo llamado attach/detach que sirve para acceder a las propiedades de los objetos fuera del contexto de una transacción. Esto es muy útil, por ejemplo, cuando estructuras tu aplicación en librerías o capas.

Supongamos que tenemos la siguiente clase

    @PersistenceCapable
    public class Audiencia {</p><pre><code>    @PrimaryKey
    @Persistent
    Integer id;
    @Persistent
    Juez juez;
    @Persistent
    Date inicio;
    @Persistent
    Date fin;
    @Persistent
    TipoAudiencia tipo;

    public Audiencia(){
    }

    public static List&lt;Audiencia&gt; getAudiencias(Integer idJuez) {
        List&lt;Audiencia&gt; audiencias;
        PersistenceManager pm = PMF.get().getPersistenceManager();
        Transaction tx = pm.currentTransaction();
        try{
            tx.begin();
            String filter = "juez.id == :idJuez";
            Query query = pm.newQuery(Audiencia.class, filter);
            audiencias = (List&lt;Audiencia&gt;) pm.detachCopyAll((List&lt;Audiencia&gt;)query.executeWithArray(idJuez));
            tx.commit();
        }finally{
            if(tx.isActive()){
                tx.rollback();
            }
            pm.close();
        }
        return audiencias;
    }

}
</code></pre><p>

cabe destacar que dentro del contexto de la transacción podríamos leer las propiedades Juez y TipoAudiencia, datanucleus cargaría los objetos relacionados de forma “lazy loading”. Pero si trataramos de leer alguna propiedad fuera de este contexto -es el caso cuando ejecutamos el método getAudiencias desde otra clase- está tendría el valor null. Datanucleus sólo hace el detach de las propiedades en el Default Fetch Group. Para poder utilizar las demás propiedades, podemos especificar un Fetch Group dinámico de la siguiente manera

    public static List getAudiencias(Integer idJuez, String[] fields) {
        List audiencias;
        PersistenceManager pm = PMF.get().getPersistenceManager();
        Transaction tx = pm.currentTransaction();
        try{
            tx.begin();
            FetchGroup fetchGroup = PMF.get().getFetchGroup(Audiencia.class, "fields");
            fetchGroup.addMembers(fields);
            pm.getFetchPlan().addGroup("fields");
            String filter = "juez.id == :idJuez";
            Query query = pm.newQuery(Audiencia.class, filter);
            audiencias = (List) pm.detachCopyAll((List)query.executeWithArray(idJuez));
            tx.commit();
        }finally{
            if(tx.isActive()){
                tx.rollback();
            }
            pm.close();
        }
        return audiencias;
    }

Fuentes:
http://www.datanucleus.org/products/accessplatform/jdo/fetchgroup.html
http://www.datanucleus.org/products/datanucleus/jdo/attachdetach.html
http://www.datanucleus.org/products/datanucleus/jdo/object
lifecycle.html

Anuncios

Para obtener el tipo de dato de las propiedades de un objeto podemos utilizar la reflexión.

Por ejemplo si tenemos las siguientes clases

public class Libro{
String isbn;
String titulo;
Autor autor;
}
public class Autor{
String id;
String nombre;
Date fechaNacimiento;
}

Un método para obtener el tipo de dato de una propiedad, incluso propiedades anidadas, sería el siguiente

private Class<?> getPropertyType(Class<?> clazz,String property){
 try{
 LinkedList<String> properties=new LinkedList<String>();
 properties.addAll(Arrays.asList(property.split("\\.")));
 Field field = null;
 while(!properties.isEmpty()){
 field = FieldUtils.getField(clazz,properties.removeFirst(),true);
 clazz=field.getType();
 }
 return field.getType();
 }catch(Exception e){
 throw new RuntimeException(e);
 }
}

Lo invocaríamos de la siguiente manera

Class<?> type=getPropertyType(Libro.class,"autor.fechaNacimiento");
System.out.println(type.toString()); //imprime java.util.Date

Notesé el uso de la clase FieldUtils de la librería Apache Commons Lang, cuyo método getField busca el campo recursivamente en la jerarquía de las clase y sus interfaces. Para agregar la librería a nuestro proyecto hay que agregar la siguiente dependencia


<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.1</version>
 </dependency>

Para listar todas las propiedades de un objeto recursivamente podemos utilizar como ejemplo el código de la clase FieldUtils.

Con la librería Jackson podemos obtener un esquema JSON de cualquier objeto. El detalle es que los tipos de datos que obtendríamos serían sólo los permitidos en JSON (string, number, boolean, object, array, null).

ObjectMapper mapper=new ObjectMapper();
System.out.println(mapper.generateJsonSchema(Libro.class));

Fuentes:
http://stackoverflow.com/questions/11125409/find-the-field-type-using-jackson-json
http://stackoverflow.com/questions/3567372/access-to-private-inherited-fields-via-reflection-in-java
http://wiki.fasterxml.com/JacksonJavaDocs
http://jackson.codehaus.org/1.8.8/javadoc/org/codehaus/jackson/map/ObjectMapper.html#generateJsonSchema(java.lang.Class)
http://wiki.fasterxml.com/JacksonTreeModel

En orientación a objetos la herencia es, después de la agregación o composición, el mecanismo más utilizado para alcanzar algunos de los objetivos más preciados en el desarrollo de software como lo son la reutilización y la extensibilidad. A través de ella los diseñadores pueden crear nuevas clases partiendo de una clase o de una jerarquía de clases preexistente (ya comprobadas y verificadas) evitando con ello el rediseño, la modificación y verificación de la parte ya implementada. La herencia facilita la creación de objetos a partir de otros ya existentes e implica que una subclase obtiene todo el comportamiento (métodos) y eventualmente los atributos (variables) de su superclase.

En nuestros objetos es fácil implementar la herencia, basta con agregar la palabra clave extends y específicar la clase padre. Pero en una base de datos relacional no siempre queda claro cómo debemos implementar la herencia. Datanucleus (JDO) nos ofrece 4 opciones:

  1. Cuando cada clase tiene su propia tabla en la base de datos: new-table
  2. Cuando los campos de la clase padre son almacenados en la tabla del hijo: subclass-table
  3. Cuando los campos del hijo son almacenados en la tabla del padre: superclass-table
  4. A partir de JDO3.1, cuando cada clase tiene su propia tabla y esta contiene todos los campos (incluídos los de la clase padre): complete-table

Supongamos que tenemos la entidad Trabajador de la cual derivan las entidades Empleado y Meritorio. Nuestras clases quedarían de la siguiente manera:

public abstract class Trabajador {
   private String id;
   private String departmento;
}
public class Empleado extends Trabajador {
   private float salario;
}
public class Meritorio extends Trabajador {
   private Date fechaTermino;
}

Las tablas para las distintas estrategias que ofrece Datanucleus (JDO) serían:

new-table

Trabajador
id departamento
Empleado
idTrabajador salario
Meritorio
idTrabajador fechaTermino

subclass-table

Empleado
id departamento salario
Meritorio
id departamento fechaTermino

superclass-table

Trabajador
id departamento tipo salario fechaTermino

complete-table

Trabajador
id departamento
Empleado
id departamento salario
Meritorio
id departamento fechaTermino

Finalmente mostraré cómo anotar nuestras clases para implementar la estrategia superclass-table, que es el caso particular que se me presentó.

@PersistenceCapable
@Discriminator(strategy=DiscriminatorStrategy.VALUE_MAP, column="tipo")
public abstract class Trabajador {
   private String id;
   private String departmento;
}
@PersistenceCapable
@Inheritance(strategy=InheritanceStrategy.SUPERCLASS_TABLE)
@Discriminator(value="EMPLEADO")
public class Empleado extends Trabajador {
   private float salario;
}
@PersistenceCapable
@Inheritance(strategy=InheritanceStrategy.SUPERCLASS_TABLE)
@Discriminator(value="MERITORIO")
public class Meritorio extends Trabajador {
   private Date fechaTermino;
}

Fuentes:

http://www.datanucleus.org/products/datanucleus/jdo/orm/inheritance.html#superclasstable
http://www.datanucleus.org/products/accessplatform/jdo/orm/inheritance.html
https://developers.google.com/appengine/docs/java/datastore/jdo/dataclasses#Inheritance
http://es.wikipedia.org/wiki/Herencia_(programaci%C3%B3n_orientada_a_objetos)

Si trabajas con GWT y JSON es muy probable que hayas utilizado overlay types. Para utilizar una enumeración en un overlaytype puedes hacerlo de la siguiente manera.

public class Parametro extends JavaScriptObject{

public static enum Tipo{ComboBox,TextBox,Date,ValueList}

protected Parametro() {

}

public native final String getNombre() /-{return this.nombre;}-/;

public native final void setNombre(String nombre) /-{this.nombre = nombre;}-/;

public native final String getTitulo() /-{return this.titulo;}-/;

public final native void setTitulo(String titulo) /-{this.titulo = titulo;}-/;

public final Tipo getTipo(){

&nbsp; &nbsp; return Tipo.valueOf(getNativeTipo());

}

public native final String getNativeTipo() /-{return this.tipo}-/;

public final void setTipo(Tipo tipo){

&nbsp; &nbsp; setNativeTipo(tipo.toString());

}

public native final void setNativeTipo(String tipo) /-{this.tipo = tipo;}-/;

}

Notesé que la propiedad Tipo es un enum, lo que hicimos fue agregar los métodos JSNI getNativeTipo y setNativeTipo que utilizan el tipo de dato String -que es soportado en javascript- y lo convertimos a su valor de la enumeración en los métodos getTipo y setTipo respectivamente.

Fuentes:
http://www.mail-archive.com/google-web-toolkit@googlegroups.com/msg50923.html
https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsOverlay 

En un vídeo muy interesante con las recomendaciones de las mejores prácticas en el desarrollo de aplicaciones con GWT -y aplicaciones web en general- se habla de utilizar un EventBus como canal de comunicación de nuestras aplicaciones a través de eventos.

Bueno, pues en el framework de GWT encontramos 2 clases con ese nombre:

La primera es la que debemos utilizar, ya que en la documentación de la segunda especifica que sólo esta para soportar la compatibilidad con aplicaciones viejas -que hayan usado esta-

Un ejemplo de uso sería como el siguiente:

import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.SimpleEventBus;

EventBus eventbus = new SimpleEventBus();
eventbus.addHandler(MyEvent.getType(), MyHandler);