Intro
One of the features that are missed when using GWT is Java's ability to perform introspection on beans. The reason for this limitation is that GWT has no reflection API emulation (java.lang.reflect). In this article we will see how we can implement a kind of introspection in GWT. We will also explore some applications of introspection, since in principle it is not trivial utility.
What for?
The first thing we see is what we want it.
Suppose we want to develop a framework of visual components that have data binding (ability to "hook" the property of an object to a visual component). Surely anyone who touched her "wonderful" job of implementing a CURD (ABM Creole) was met with set starting and tedious reading of the visual components of the object and vice versa. If you had to do this, you did something wrong
. Well, this is a task as boring as prone to mistakes, especially Control-C + Ctrl-V. If we could say something like: "This UI component looks at the properties as of that object," then we can alleviate this task as well for example we save all the code for event handling.
So if we do this, we can build a set of components to which we set simply the bean and the property that "look" as well as the component value changes will automatically be reflected in the bean and vice versa.
But how to do this without introspection?
How? What?!
As we saw in GWT (at least until 1.7) there is no reflection, so we have no choice but to find another way to implement introspection. First let's see what is introspection in Java. According to the JavaDoc java.beans.Introspector class:
"The Introspector class Provides a standard way for tools to learn About the properties, events, and supported by a target Methods Java Bean."
In Spanish:
"The Introspector class provides a standard way for tools to discover properties, events and methods supported by a Java Bean."
The part that interests us is the part of the property. In other words, we want to implement a mechanism by which you can be a Java Bean to ask what are their properties and what are the values of these.
The form is going to implement it by creating a class for each class introspection we want to have insight.
Then for the class:
public class Person { private String name; private String address; private Date birth; private boolean sex; public Person () { } public String getName () { return name; } public void setName (String name) { this.name = name; } / / Getters and setters ... more ... }
We have to implement the kind of "insight":
{public PersonaIntrospection private Person person; public PersonaIntrospeccion () { } GetPerson public Person () { return person; } setPersona public Person (Person p) { person = p; } public List getProperties <String> () { List l = new ArrayList <String> <String> (); l.add ("name"); l.add ("address"); l.add ("birth"); l.add ("sex"); } public Object getProperty (String property) { if ("name". equals (property)) persona.getNombre return (); else if ("address". equals (property)) persona.getDireccion return (); else if ("birth". equals (property)) persona.getNacimiento return (); else if ("sex". equals (property)) persona.getSexo return (); else throw new IllegalArgumentException (property); } public void setProperty (String property, Object value) { if ("name". equals (property)) persona.setNombre ((String) value); else if ("address". equals (property)) persona.setDireccion ((String) value); else if ("birth". equals (property)) persona.setNacimiento ((Date) value); else if ("sex". equals (property)) persona.setSexo ((Boolean) value); else throw new IllegalArgumentException (property); } }
Beyond the optimizations that you can make to the code (and listings cache), the idea is to understand why this class gives us insight into a person object. As should be imagining, grace is not having to write the class PersonaIntrospection. Grace is working on things less boring and more "fun" things ![]()
Enter generators!
What we do is that GWT generates PersonaIntrospection class. How? Using generators. This is a very interesting feature of GWT. The focus of this article is to explain generators, there is much literature on the Internet. Here is a Just do not have to be an expert to understand what we do.
Basically we will write a class that generates code for the class Xxx XxxIntrospection as we saw in the example of Person. Y (to avoid having to make any step toward creating the kind compilation with some external utility) we will use the API which allows you to extend the GWT compiler (com.google.gwt.core.ext). NOTE: Those who have used Java APT will see a few similarities ( http://java.sun.com/javase/6/docs/technotes/guides/apt/index.html ).
When the GWT compiler encounters the statement GWT.create (class)-which returns an interface implementation class-generator invokes the interface associated with the class (this association is declared in the module gwt.xml). This generator is "write" the code that implements the interface class. To write this code have the assistance of the API that is very reminiscent com.google.gwt.core.ext.typeinfo API Java Reflection Mirror.
Generate
Now let's see if the generator. But first let's see how it is used. GWT.create () takes an interface and returns an implementation of it. Then we define an interface brand and we'll call introspective. Any kind you want to have support of introspection going to have to implement this interface will:
introspectible {} public interface Then the class Person:
public class Person {implements introspectible / / ... attributes and methods ... }
We also need to have the interface language of introspection:
public interface extends <I Introspectable> {Introspection I getIntrospectable (); setIntrospectable void (I i); <T> T getProperty (String propName); void setProperty (String propName, Object value); GetPropertyName <String> Collection (); }
And for introspection and use:
Person person = new Person (); Introspection <person> GWT.create instrospection = (Persona.class); instrospection.setIntrospectable (person); for (String prop: instrospection.getPropertyNames ()) { System.out.println (prop + "=" + instrospection.getProperty (prop)); } Instrospection.getProperty String name = ("name"); Instrospection.getProperty String address = ("address"); Date birth = instrospection.getProperty ("birth"); Instrospection.getProperty sex = Boolean ("sex");
To associate the interface generator introspective, to add the following snippet:
class="com.aquait.utils.gwt.rebind.IntrospectionGenerator"> <generate-with class="com.aquait.utils.gwt.introspection.Introspectable"/> <when-type-assignable </ Generate-with>
So when the GWT compiler is GWT.create (Persona.class), called the generator for the class Person implements introspective. Then we have an Introspection interface implementation for the Person class.
For use in a project, add this in the <module>. Gwt.xml:
name="com.aquait.utils.gwt.Introspection"/> <inherits The GWT module can be downloaded here: introspection4gwt
EDIT: updated the file due to a small bug.
EDIT: updated again due to a bug that did not take into account the properties of the super classes.
