Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GWT Dynamic loading using GWT.create() with String literals instead of Class literals

Tags:

gwt

GWT.create() is the reflection equivalent in GWT, But it take only class literals, not fully qualified String for the Class name. How do i dynamically create classes with Strings using GWT.create()?

Its not possible according to many GWT forum posts but how is it being done in frameworks like Rocket-GWT (http://code.google.com/p/rocket-gwt/wiki/Ioc) and Gwittir (http://code.google.com/p/gwittir/wiki/Introspection)

like image 973
Sathish Avatar asked Jan 16 '09 19:01

Sathish


2 Answers

It is possible, albeit tricky. Here are the gory details:

If you only think as GWT as a straight Java to JS, it would not work. However, if you consider Generators - Special classes with your GWT compiler Compiles and Executes during compilation, it is possible. Thus, you can generate java source while even compiling.

I had this need today - Our system deals with Dynamic resources off a Service, ending into a String and a need for a class. Here is the solutuion I've came up with - btw, it works under hosted, IE and Firefox.

  • Create a GWT Module declaring:
    • A source path
    • A Generator (which should be kept OUTSIDE the package of the GWT Module source path)
    • An interface replacement (it will inject the Generated class instead of the interface)
  • Inside that package, create a Marker interface (i call that Constructable). The Generator will lookup for that Marker
  • Create a base abstract class to hold that factory. I do this in order to ease on the generated source code
  • Declare that module inheriting on your Application.gwt.xml

Some notes:

  • Key to understanding is around the concept of generators;
  • In order to ease, the Abstract base class came in handy.
  • Also, understand that there is name mandling into the generated .js source and even the generated Java source
  • Remember the Generator outputs java files
  • GWT.create needs some reference to the .class file. Your generator output might do that, as long as it is referenced somehow from your application (check Application.gwt.xml inherits your module, which also replaces an interface with the generator your Application.gwt.xml declares)
  • Wrap the GWT.create call inside a factory method/singleton, and also under GWT.isClient()
  • It is a very good idea to also wrap your code-class-loading-calls around a GWT.runAsync, as it might need to trigger a module load. This is VERY important.

I hope to post the source code soon. Cross your fingers. :)

like image 86
aldrinleal Avatar answered Sep 20 '22 13:09

aldrinleal


Brian,

The problem is GWT.create doen't know how to pick up the right implementation for your abstract class

I had the similar problem with the new GWT MVP coding style ( see GWT MVP documentation )

When I called:

ClientFactory clientFactory = GWT.create(ClientFactory.class);

I was getting the same error:

Deferred binding result type 'com.test.mywebapp.client.ClientFactory' should not be abstract

All I had to do was to go add the following lines to my MyWebapp.gwt.xml file:

<!-- Use ClientFactoryImpl by default -->
    <replace-with class="com.test.mywebapp.client.ClientFactoryImpl">
    <when-type-is class="com.test.mywebapp.client.ClientFactory"/>
    </replace-with>

Then it works like a charm

like image 45
Daghan --- Avatar answered Sep 23 '22 13:09

Daghan ---