Preview: Java Bean support with Ext GWT
July 14, 2008 by Darrell Meyer
The Ext GWT Store and Binder API work with ModelData instances. The primary goal of ModelData is to provide a type of “introspection” as GWT does not allow runtime inspection of Java objects. You can query ModelData for a list of properties it contains, and these properties can be retrieved and set using the parameter name with the get and set methods.
Although this approach works, it forces you to either implement the ModelData interface in your Java Beans or extend the Ext GWT base classes that implement the ModelData interface. What is missing is a way to use your Java Beans as is, without having to extend the Ext GWT base classes or implement an “invasive” interface.
With the 1.1 release of Ext GWT, it is possible to use any Java Beans in the Store and Binder API. This allows you to send your Java Beans from server to client using GWT RPC.
Java Bean support is provided by dynamically creating new BeanModel instances using any bean. The new type will “wrap” the bean, and all get and set calls on the model will be delegated to the underlying bean. Also, the original bean is available via the new bean model instance. The new model instances are created using a GWT Generator. Basically, the generator allows “new” types to be created at compile time using GWT.create(). The GXT generator will create a BeanModelFactory than can create new BeanModel instances from a Java Bean.
Identifying Java Beans
There are 2 ways of identifying Java Beans. The first method requires a new interface that extends BeanModelMarker and uses annotations. This method does not require the JavaBean to be modified. With the second method, your Java Bean implements the BeanModelTag interface.
BeanModellMarker Interface
The first step to enable Java Bean support is to identify the Class you would like to “adapt”. Rather than specifying the class directly, a new interface is created that extends BeanModelMarker. Then, a @BEAN annotation is added to the interface to identify the actual bean. This approach is beneficial, as it allows a single deferred binding rule to be used to identify your bean. Also, by using a marker interface, other configuration information can be specified by annotations.
public class Customer implements Serializable { private String name; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @BEAN(Customer.class) public interface CustomerBeanModel extends BeanModelMarker { }
BeanModelTag Interface
With this method, a new interface is not required as you tag the Java Bean directly. This means your beans will have a reference to a GXT interface.
public class Customer implements BeanModelTag, Serializable { private String name; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
BeanModelLookup
BeanModelLookup is used to obtain a BeanModelFactory instance for a given bean type. You will use the BeanModelLookup singleton to obtain a BeanModelFactory for your given bean. The BeanModelFactory can be used to create new bean model instances from your bean instances.
BeanModelFactory factory = BeanModelLookup.get().getFactory(Customer.class);
With the factory, you are able to create new BeanModel instances that wrap your bean.
Customer c = new Customer(); c.setName("Darrell"); BeanModel model = factory.createModel(c);
BeanModelReader
It is common to use the GXT data loading API to retrieve remote data and populate a Store. The BeanModelReader can be used to handle creating new model instances from the beans being returned from the data proxy. With this approach, you can return any Java Beans from the RPC call. BeanModelReader will lookup the factory given the type of the objects being returned from the data proxy.
Store
When using this approach, the type of objects in the store will be the dynamically created types that were created based on the bean. These objects will extend BeanModel. BeanModel provides access to the “wrapped” bean via the getBean method.
Customer customer = (Customer)model.getBean();
Grid Example
Here is a snippet of code from the Explorer demo. It demonstrates uses a BeanModelReader with a Grid.
// gwt service final ExplorerServiceAsync service = (ExplorerServiceAsync) Registry.get("service"); // proxy and reader RpcProxy proxy = new RpcProxy() { @Override public void load(Object loadConfig, AsyncCallback callback) { service.getCustomers(callback); } }; BeanModelReader reader = new BeanModelReader(); // loader and store ListLoader loader = new BaseListLoader(proxy, reader); ListStore<BeanModel> store = new ListStore<BeanModel>(loader); loader.load(); // column model List<ColumnConfig> columns = new ArrayList<ColumnConfig>(); columns.add(new ColumnConfig("name", "Name", 200)); columns.add(new ColumnConfig("email", "Email", 100)); columns.add(new ColumnConfig("age", "Age", 50)); ColumnModel cm = new ColumnModel(columns); Grid<BeanModel> grid = new Grid<BeanModel>(store, cm); grid.setAutoExpandColumn("name"); grid.setWidth(400); grid.setAutoHeight(true); grid.setBorders(true);
Summary
The new Java Bean support allows easy data integration of your existing Java Bean objects. Sending any Java Bean over the wire is possible, and Ext GWT can create bean model instances on the client.
These features will be available with the 1.1 release of Ext GWT. For those with access to SVN, the working code is in the trunk.

Posted on July 14th, 2008 at 11:33 pm
Nice work, just got it from svn and it works great!
Posted on July 15th, 2008 at 9:11 pm
OH~ it’s like great!
Posted on August 26th, 2008 at 1:42 am
[...] Java bean support [...]
Posted on September 3rd, 2008 at 10:51 am
Hi,
I’m trying to use GXT 1.1alpha3 and can’t get the table equivalent of “grid example” working.
Did anything change in the mean time?
I’m using it this order:
BeanModelReader reader = new BeanModelReader();
BasePagingLoader loader = new BasePagingLoader(proxy, reader);
loader.load(0, 20);
ListStore store = new ListStore(loader);
final PagingToolBar toolbar = new PagingToolBar(20);
toolbar.bind(loader);
new TableBinder(table, store);
Anything terrebly wrong?
Posted on September 5th, 2008 at 5:01 am
Any idea on how to wire Enteprise Java Beans over the wire?
First problem is that the EJB wont compile in gwt becouse they relate to annotatioons in javax.persistence.*;
I then made fake annotation files, that made the gwt js compile and run.
But then the gwt-servlet fails to serialize the beans for transmission
This error is shown in console:
Caused by: com.google.gwt.user.client.rpc.SerializationException: Type ‘oracle.toplink.essentials.internal.indirection.UnitOfWorkQueryValueHolder’ was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.
Posted on September 18th, 2008 at 1:39 am
[...] With the 1.1 release of Ext GWT, it is possible to use any Java Beans in the Store and Binder API. This allows you to send your Java Beans from server to client using GWT RPC. More information can be found in this blog post. [...]
Posted on October 4th, 2008 at 5:01 pm
I’m trying to get the Java Bean stuff working.
But when I follow your example using the factory the system won’t compile.
This is caused by the fact that the GWT compiler can’t find the BeanModelLookup implementation which is made at run-time, but I need it to create instance of my model.
At the following code to a project that is not build with the GXT.gwt.xml.
BeanModelFactory factory = BeanModelLookup.get().getFactory(MyJavaBean.class);
BeanModel model = factory.createModel(myJavaBean);
Posted on October 4th, 2008 at 5:06 pm
Hereby the build error,
Scanning for additional dependencies: jar:file:/G:/gwt/gxt-1.1/gxt.jar!/com/extjs/gxt/ui/client/data/BeanModelLookup.java
Computing all possible rebind results for ‘com.extjs.gxt.ui.client.data.BeanModelLookup’
Rebinding com.extjs.gxt.ui.client.data.BeanModelLookup
Invoking
[ERROR] Class com.extjs.gxt.ui.client.data.BeanModelLookup not found.
java.lang.NullPointerException
at com.extjs.gxt.ui.rebind.core.BeanModelGenerator.getMarkerBean(BeanModelGenerator.java:169)
at com.extjs.gxt.ui.rebind.core.BeanModelGenerator.generate(BeanModelGenerator.java:53)
at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:51)
at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.tryRebind(StandardRebindOracle.java:116)
at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:61)
at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:166)
at com.google.gwt.dev.GWTCompiler$DistillerRebindPermutationOracle.getAllPossibleRebindAnswers(GWTCompiler.java:195)
at com.google.gwt.dev.jdt.WebModeCompilerFrontEnd.doFindAdditionalTypesUsingRebinds(WebModeCompilerFrontEnd.java:128)
at com.google.gwt.dev.jdt.AbstractCompiler$CompilerImpl.process(AbstractCompiler.java:150)
at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:392)
at com.google.gwt.dev.jdt.AbstractCompiler$CompilerImpl.compile(AbstractCompiler.java:84)
at com.google.gwt.dev.jdt.AbstractCompiler$CompilerImpl.compile(AbstractCompiler.java:180)
at com.google.gwt.dev.jdt.AbstractCompiler$CompilerImpl.access$400(AbstractCompiler.java:70)
at com.google.gwt.dev.jdt.AbstractCompiler.compile(AbstractCompiler.java:493)
at com.google.gwt.dev.jdt.WebModeCompilerFrontEnd.getCompilationUnitDeclarations(WebModeCompilerFrontEnd.java:73)
at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.(JavaToJavaScriptCompiler.java:277)
at com.google.gwt.dev.GWTCompiler.distill(GWTCompiler.java:353)
at com.google.gwt.dev.GWTCompiler.run(GWTCompiler.java:564)
at com.google.gwt.dev.GWTCompiler.run(GWTCompiler.java:554)
at com.google.gwt.dev.GWTCompiler.main(GWTCompiler.java:214)
[ERROR] Errors in ‘jar:file:/G:/gwt/gxt-1.1/gxt.jar!/com/extjs/gxt/ui/client/data/BeanModelLookup.java’
[ERROR] Line 17: Failed to resolve ‘com.extjs.gxt.ui.client.data.BeanModelLookup’ via deferred binding