GWT Reflection

December 5th, 2009 by Enrique Leave a reply »

Intro

Following in the line of introspection, today we see a simple reflection that will allow us to invoke on an instance of a class method by name.

What for?

Reflection is an interesting feature, which is essential when designing generic components. We can create instances of a class with the name of the class or also invoke methods on an instance of a class having the name of the method. This, for example, it greatly simplifies the implementation of the command pattern.

How? What?!

In GWT (at least until 1.7) there is no reflection. What we do in this implementation of reflection is to provide a mechanism for invoking methods by name. Assuming we have a class called MyClass has a method called myMethod we could do something like this:

  MyClass instance = new MyClass (); 
  NombreMetodo String = "myMethod"; 
  Object [] parameters = new Object []{...}; 
  invoke (instance, nombreMetodo, parameters); 

Enter generators!

What we do is that GWT generates MiClaseReflection 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 MiClaseReflection code, which has a single method-call-it is a chain if .. elseif .. else who asks for each method of MyClass and if any match, it invokes. It would be something like this:

  if (nombreMetodo.equals ("miMetodo1")) { 
  target.miMetodo1 (params) / / void 
  } Else if (nombreMetodo.equals ("miMetodo2")) { 
  target.miMetodo2 return (params) / / not void 
  Else {} 
  throw new Exception ("Method not found:" + nombreMetodo); 
  } 

Obviously missing parameter checks.

To avoid having to make any step toward creating the kind compilation with some external utility we will use the API which has for 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

The instruction GWT.create () takes an interface and returns an implementation of it. Then we define an interface brand and we'll call Reflect. Any kind you want to have support for reflection will have to implement this interface:

  Reflect {public interface 
  } 

Then the class MyClass:

  public class Reflect {MyClass implements 
  miMetodo1 void (); 
  miMetodo2 int (); 
  } 

We also need to have the interface language of reflection:

  public interface extends <I Reflectable> {Reflection 
  Object invoke (I target, String methodName, Object ... params) 
  InvocationException throws; 
  } 

For a discussion and use myMethod assuming no parameters:

  MyClass object = new MyClass (); 
  Reflection Reflection = GWT.create <MiClase> (MiClase.class); 
  reflection.invoke (object, "myMethod"); 

To associate the interface generator Reflect, add the following snippet to:

  class="com.aquait.utils.gwt.rebind.ReflectionGenerator"> <generate-with 
  class="com.aquait.utils.gwt.reflection.Reflectable"/> <when-type-assignable 
  </ Generate-with> 

So when the GWT compiler is GWT.create (MiClase.class), called the generator as MyClass implements Reflect. Then we have an implementation of the interface for MyClass Reflect.

For use in a project, add this in the <module>. Gwt.xml:

  name="com.aquait.utils.gwt.Reflection"/> <inherits 

The JAR can be downloaded here: introspection-reflection4gwt.jar

Note: This JAR has an updated version of introspection that eliminates getIntrospectable methods () and setIntrospectable () Introspection interface. Therefore, the methods getProperty () and setProperty () take as first parameter to the introspective.

Blogger Post Digg Reddit Google Reader Share
Advertisement

3 comments

  1. pepe says:

    All good, but still useless as having to pass the class literal MiClase.class, they have to know beforehand what kind it is and have a reference to it. As you know the name alone of the class to instantiate at runtime? You can not put that gwt will not let you do. The only solution to this problem is to have a limited set of classes and pre-processed by the generator and inserted into a library or record. Eg. register.add (new GWT.create (MiClase.class)) so, then invoke serious register.invocarmetodo ("class", "method"). This leads to the problem of knowing in advance all possible classes to use.

  2. Enrique Enrique says:

    Everything you say, yes, except that it is useless :) .
    I also met these challenges and implementing the registration ended like as you say.
    Then I realized that GWT does not support static initializers when "load" the class (even if running at the time of new).
    Also gave us good results. This long already, but I think what we use to make a generic component of the user menu that could be configured and stored in the database or something.
    Greetings and thanks for the input.

  3. pepe says:

    Sorry for the useless, I knew I did not express. I've used for book-entry domain classes automatically generate the user interface. A similar approach but with GWT OpenXava. Basically "leo" JPA annotations and my own at runtime and create a wrapper that contains the information needed to get DONE in that class. Then in Ex-gwt and I have a component when running AbmMenuItem shows you a complete Abm that class, which includes filters, the entry form with special components to find an object associated with ManyToOne eg.
    Greetings.

Leave a comment

Spam protection by WP Captcha-Free