GWT – JavascriptObject overlay types Map

Para facilitar el uso de servicios REST utilzamos JavascriptObject overlay types, los cuales nos permiten obtener un objeto a partir de una cadena JSON. Los overlay types sólo permiten ciertos tipos de datos como parámetros o valores de retorno. Entonces, para obtener un Map a partir de una cadena JSON como la siguiente, podemos utilizar la clase JSOHelper del framewrok SmartGwt:

{“id”:”menu1″,”opciones”:{“key1″:”value1″,”key2″:”value2″,”key3″:”value3”}}

tendríamos que hacerlo de la siguiente manera:

public class Menu extends JavaScriptObject{

public final native String getId()/*-{return this.id}-*/;

public final native JavaScriptObject getNativeOpciones()/*-{return this.opciones}-*/;

public final LinkedHashMap<String,String> getOpciones(){

LinkedHashMap<String,String> linkedMap=new LinkedHashMap<String,String>();

Map map=JSOHelper.convertToMap(getNativeOpciones());

Iterator iterator=map.entrySet().iterator();

while(iterator.hasNext()){

Map.Entry item=(Map.Entry)iterator.next();

linkedMap.put((String)item.getKey(),(String)item.getValue());

}

return linkedMap;

}

}
Anuncios

GWT – JavaScriptObject overlay types Enum

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 

Java – Serializar a XML con XStream

Hace poco comparaba la serializacion en .NET con la de Java. En ese entonces utilice una libreria llamada Simple. Ahora me he encontrado con otra libreria llamada XStream que me ha gustado bastante.
Un problema que tuve, fue para serializar una clase que tenia atributos derivados(calculated,transient).
Tomemos el ejemplo del tutorial de XStream y modifiquemoslo

public class Person {
  private String firstname;
  private String lastname;

  public String getFullname(){
    return this.firstname+this.lastname;
  }
  public void setFullname(){
    throw new IllegalArgumentException(“Atributo de solo lectura”);
  }
  // … constructors and methods
}

luego lo serializamos de la siguiente forma

Person joe = new Person(“Joe”, “Walnes”);
Stream xstream = new XStream();
xstream.alias(“person”, Person.class);
String xml = xstream.toXML(joe);

que nos resulta en el siguiente XML

<person>
  <firstname>Joe</firstname>
  <lastname>Walnes</lastname>
</person>

notese que no aparece por ningun lado nuestro atributo calculado “Fullname”
Esto se debe a que la libreria XStream utiliza la reflexión para serializar nuestra clase y por ello accesa directamente a los campos de nuestra clase. Y no tenemos ningun campo que se llame fullname.
La solución podría ser agregar un campo llamado fullname y actualizarlo cada que se modifique alguno de los campos de los cuales depende ‘:-) uffff
Otra opción es utilizar la clase JavaBeanConverter para indicarle a XStream que debe utilizar los getters y setters de nuestra clase para serializar. Para ello necesitamos que nuestra clase cumpla la definicion de un JavaBean(constructor por default, getters y setters basicamente). Es por esto que en la clase de ejemplo tambien codificamos un método setFullname pero simplemente arrojamos una excepción si se intenta establecer algún valor.
Ahora si, veamos como utilizamos la clase JavaBeanConverter

Person joe = new Person(“Joe”, “Walnes”);
Stream xstream = new XStream();
xstream.alias(“person”, Person.class);
xstream.registerConverter(new JavaBeanConverter(xstream.getMapper()),-20);
String xml = xstream.toXML(joe);

Nótese el segundo parámetro del método registerConverter(-20), sin éste, la serialización falla miserablemente. El valor lo obtuve de aqui, creo que ese es un fallo de XStream(la documentación)
y finalmente nos produce el XML deseado

<person>
  <fullname>Joe Walnes</fullname>
</person>