jueves, 22 de agosto de 2013

Eclipse Kepler and Vaadin 7 - Visual Designer - Design Tab is missing

Workaround

I installed the Vaadin Plugin for Eclipse and I wanted to test the visual designer and there no was no design Tab. I found a useful link.

http://stackoverflow.com/questions/17994805/how-to-install-xulrunner-for-eclipse

1. Well I did the next. Downloaded the latest XULRunner from mozilla
http://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases/latest/runtimes/
and extracted in some directory.

2. Edit the eclipse.ini file and add this line

-Dorg.eclipse.swt.browser.XULRunnerPath=D:\xulrunner

3. When I start Eclipse Kepler I get a weird message

Now The Designer Tab is showing!




sábado, 15 de diciembre de 2012

Annotation processors for GXT and RequestFactory

UPDATED
_______________________________________________________________________________

For some reasons this library doesn't work well or don't work at all so I left using it.
The cause could be my bad programming or my lack of knowledge of how RequestFactory and Maven works. Then I don't know how to fix it.
I apologise if I made waste your time trying to test it. It was not my intention.
The Idea Is not bad at all. I think a better concept would be implement it as a plugin instead of an annotations processor.
Greetings
____________________________________________________________________________


In this post I don´t talk about annotation processors in java, I recommend a great article Code Generation using Annotation Processors in the Java language instead I talk about how I use it for generate boilerplate code. The source code is in GitHub gxt-processors

For example if I want to show a list  using GXT Grid and RequestFactory (The server is in Java).
I need to use additional class and interface.
The same happens for every object I want to show in a GXT Grid or Combo Box.
But instead of DIY you can try to generate this additional code.

First of all you need to download and install the artifacts into your local repository via command line.

mvn install:install-file -Dfile=gxt-processors-1.0-SNAPSHOT.jar -DgroupId=com.rhem.solutions -DartifactId=gxt-processors -Dversion=1.0-SNAPSHOT -Dpackaging=jar

____________________________________________________________________________
EDIT the artifact is on Maven Central Add the  following dependencies and configurations to your POM.xml

If you run the command
mvn generate-sources

the following structure are create

target
  |-generated-sources
     |-gwt
         |- server
            |- resultbean
               |- UserListLoadResultBean.java
               |- UserPagingLoadResultBean.java    
         |- shared
            |-resultproxy
               |- UserListLoadResultProxy.java
               |- UserPagingLoadResultProxy.java
            |- service
                |- AppRequestFactory.java (list of request contexts)

How it works
Well for generate the resultbean classes, the processor searches all classes annotated with @Entity (JPA annotation) and create two files for each entity e. g. UserListLoadResultBean.java (for combobox) and UserPagingLoadResultBean.java (for paging grid).
The processor searches all interfaces annotated with @ProxyFor (Request Factory annotation) and generate two files for each EntityProxy e. g. UserListLoadResultProxy.java and UserPagingLoadResultProxy.java

The processor searches all interfaces annotated with  @Service (Request Factory annotation) and create the list of request contexts: AppRequestFactory.java

martes, 4 de diciembre de 2012

GWT and PHP

This time I will describe a CRUD application using GXT Grid and HttpProxy on the client side and on the server side I use PHP and PDO to access a PostgreSQL database.
The communication between client and server side is using JSON then you can use whatever language on the server side that produce a JSON output.
The source code is on github https://github.com/poseidonjm/GXT3-PHP is structured using GWTP and GWT Editor for binding.

Database table

GXT and HttpProxy
First of all the next interfaz and class are required

MyAutoBeanFactory.java

MyHttpProxy.java

GWT AutoBean
With GWT AutoBean is easy to serialize/deserialize GWT Objects to json and vice versa,
on the client side there is the UserProxy interface that represents the model

UserListProxy represent a set of users

With AutoBean the objects are created from a factory


GXT Reader
GXT Grid use a reader to parse the output of the server.

GXT Grid

UserView.ui.xml

Run the proyect
You have to start your Apache Server and enable the following extensions for PostgreSQL and PDO:
php_pdo_pgsql
php_pgsql
You have to set the root of your web server to the war of the project
for example I use XAMPP and change the httpd.conf
restart Apache Server.
Set the parameters of connection to database PostgreSQL in war/config/connect.php
I usually work on Firefox for GWT DevMode




Compile GWT code to JS
I compile GWT with Google Plugin for Eclipse GPE

By default the compiled JS code is compressed.

Then enter the url http://localhost/phpcrud.html#users

The Server Side PHP
I use simple PHP and PDO
connect.php
users.php
paginate.php
Sorry if I am missing explain PHP code.

I hope you can use GWT with any backend and AutoBean is a nice feature of  GWT.

martes, 3 de julio de 2012

GWT-Platform and GXT3

Previously I wrote about GXT3 and RequestFactory to perform basic crud operations http://goo.gl/7ePse.
This time I will be focused in GWTPlatform using GXT3 widgets.
The source code is available through Github https://github.com/poseidonjm/GWTP-GXT3

GWT-Platform
Used to simplify the MVP architecture with minimal boilerplate (GWTP page)

GWTP Plugin for Eclipse
You should install the plugin that offers wizards for create Presenters and Events
Help > Install New Software
http://plugin.gwt-platform.googlecode.com/hg/update
I am using Eclipse Indigo.

Final Project



 Project Structure

CSS
I copied the style of Sencha examples

Project Layout
LayoutPresenter.java is the main presenter it contains the header and footer of the page.
LayoutPresenter is not a Place so the user cannot navigate.

Create a Presenter


I choose RevealRootContentEvent because this presenter takes all the screen.

All presenters are composed of three files.

All presenters have a inner interface that view implements.

Presenter lifecycle
  • Presenters are Singleton so it is instantiated once.
  • prepareFromRequest(): Is where you can get url parameters.
  • onBind(): Is called when the presenter is  instantiated.
  • onReveal(): Is called whenever the Presenter was not visible on screen and becomes visible.
  • onHide(): Is called whenever the Presenter was visible on screen and is being hidden.
  • onReset(): Is called whenever the user navigates to a page that shows the presenter, whether it was visible or not.
References GWTP Page and Dani GWTP Course.


Nested Presenters
Your header, footer and menu are in one presenter the "parent presenter".


Presenter Widget
Is for reusable graphical and logical code.




LayoutPresenter.java

LayoutView.java

LayoutView.ui.xml


Create a Presenter Widget



MenuPresenter.java

MenuView.java

MenuView.ui.xml


Create Default Presenter
When you start you program the first page that you see is the default presenter.


Create Colaborador Presenter

Tokens
Most presenters have a token so the user can navigate.


For example #colaboradores is a token that identifies the program Colaboradores. When there is not token the default presenter is shown.

You can navigate from one presenter to another by:
  • Typing another url
  • Using a Hyperlink Widget
  • Using a Place Request
References Dani GWTP course

For Example MenuPresenter use Place Request to navigate through the programs.

Popup Presenters
Is a presenter widget that is shown inside a popup dialog.

Create a Popup Presenter


Popup Presenters and GXT3
Usually popup views extend PopupViewImpl or PopupViewWithUiHandler. But it works if you use GWT PopupPanel or DialogBox or whatever extend GWT PopupPanel.
I wanna use GXT Window like Popup Presenter so I copied  PopupViewImpl and PopupViewWithUiHandler and change GWT PopupPanel by GXT Window.

GXTPopupViewImpl.java


GXTPopupViewWithUiHandlers.java
Its all about GWTP and GXT3
Greetings.

_______________________________________________________________________________
UPDATED
GXTPopupViewImpl.java and  GXTPopupViewWithUiHandlers.java are available through maven central
gwtp-gxtwindow-1.0.jar
http://search.maven.org/#search%7Cga%7C1%7Ccom.rhemsolutions

add to your GWT module

<inherits name='com.rhemsolutions.PopupWindow'/>

lunes, 11 de junio de 2012

Sencha GXT3 RequestFactory Guice JPA

I am now starting a new blogspot. Next I will describe a Basic CRUD example with GXT Grid.
The project was build with Maven and is available via GIT https://github.com/poseidonjm/basic-crud
If you don't have Egit you can install Help -> Install New Software...

http://download.eclipse.org/egit/updates

I am using Eclipse Java EE IDE for Web Developers.
You should install Maven http://maven.apache.org/download.html download apache-maven-3.0.4-bin.zip

Install maven plugin Help -> Install New Software...
 m2e-wtp - http://download.jboss.org/jbosstools/updates/m2eclipse-wtp

Final Project

Database Table
I am using postgreSQL 8.4


General Structure
Project Structure
General POM.xml

GWT Module

Here I am include modules like RequestFactory,  GXT, UIBinder, GIN and set my locale to es_PE (spanish-Perú).


EntryPoint

So where is the code? Simple I am using Gin and is like Guice for GWT projects. It means you can use the powerful Dependency Intection in your GWT code.

What is Dependency Intection?
In a nutshell "Never use new use @Inject instead". Guice will create your object and initialized injected fields.

In GIN I need a Ginjector and create this with GWT.create().
private final ClientGinjector injector = GWT.create(ClientGinjector.class);

Ginjector code

Here I get a ColaboradorPanel to attach to the RootPanel. A Ginjector need a Module.

Client Module
The next code was extracted from http://cleancodematters.com/2011/05/19/gwt-requestfactory_with_gin/

Here I configure how GIN will create objects. My Messages Interface should be a Singleton, my ClientBundle AppImages too. In RequestFactory is needed an EventBus here I am using a SimpleEventBus and is a Singleton. There is a Provider method createRequestFactory that create my AppRequestFactory Interface and initialized it with a SimpleEventBus. More about GIN http://code.google.com/p/google-gin/.

ColaboradorPanel

In GWT there is not Java Reflection and GXT need access to the properties. For that purpose here is the interface ColaboradorProxyProperties.

I created a SaveEvent to be fired when a user click on Save Button.

SaveEvent

Inside there is already created a SaveHandler.
I created this class using a GWTP Plugin for Eclipse http://code.google.com/p/gwt-platform/wiki/EclipsePlugin Once installed you can use this wizard to easily create your events.

I entered the EventName: SaveEvent and check the Has Handlers box.

The Editor is the Dialog where the user entered your information and click on Save button. Here the SaveEvent is fired and the method save of SaveHandler is executed. Here I call the flush method to update the object modified in the editor. An next if the driver has not eny errors I hide the Editor and fire the context RequestContext.

What Is a RequestContext
In RequestFactory all changes in an object are done inside a context. When you want to persist your changes call the fire methot of a context. Your changes are sent to the server and are saved to a database. It means you can make many changes before sent your changes to the server.

Next I Inject Messages interface using Field Injection.
@Inject Messages messages;

Then I use Constructor Injection to initialized required variables.

@Inject
public ColaboradorPanel(final Binder uiBinder, EventBus eventBus, Provider<AppRequestFactory> provider, Driver driver, ColaboradorEditor editor)

What happens first Constructor Injection or Field Injection?
The answer is Constructor Injection. It means you can't use messages variable inside the constructor because you will get a NullPointerException. If you need a variable inside a constructor inject it using Constructor Injection.

For create a GXT Grid you need create a proxy, loader and a store. Inside the proxy I use two helper function createRequestSortInfo createRequestFilterConfig to get sort info and filter info. This is needed because in Request Factory you cannot sent any object to the server. You only can sent interfaces that extends ValueProxy or EntityProxy. You sent a EntityProxy if there is an Entity Implementation on the server  It means if you have a table in a database. For other objects use ValueProxy.

For create objects and edit In RequestFactory with GWT Editor. I use one method persist()

Create an Object with GWT Editor
First I declare a field member
private ColaboradorProxy colaborador;

If I wanna create an object I create en empty Object
colaborador = cs.create(ColaboradorProxy.class);

Then bind the object with the Editor
driver.edit(colaborador, cs);

Next show the Editor
editor.show(messages.addColaborador());

When the user see the Editor or Dialog will see empty TextFields because is binded with an empty object.
Then the user fill the Form and click on Save. The SaveEvent is fired and The SaveHandler is executed. Here I still have an empty object I you do a System.out.println(colaborador.getAge()) you will get nothing then I call the method flush() on driver and the empty object is update with the editor information the user was entered next you can do System.out.println(colaborador.getAge()) an will get what you want.
Next I fire the context and sent my changes to server.

Edit an Object with GWT Editor
Get the object selected
colaborador = grid.getSelectionModel().getSelectedItem();

And repeat the above steps.
When the user see the editor will see the information selected and can do changes and save them because It is binded with an selected object and is not empty. Here the same happens if you don't call the method flush() on driver your object won't be updated.

Two way for creating UiBinder
When you use UiBinder you should have two files ColaboradorPanel.java and ColaboradorPanel.ui.xml
Your java file may be writed in two ways:
First way
If you want to extend from Window you can see http://www.sencha.com/forum/showthread.php?181348-(beta2)-Editor-extends-Window-doesn-t-work
Second way
ColaboradorPanel.ui.xml


ColaboradorEditor.java
All fields that need binding should be declared like class fields. If the widget is only in UiBinder and not declared like class field the binding with GWT Editor does not work.
In UiBinder all widgets are create by GWT. If you need pass an argument by UiBinder you can use
@UiFactory http://blog.jeffdouglas.com/2010/02/24/gwt-uibinder-passing-objects-to-widgets/
In another way you can pass the argument in java code and your field should be annotated with @UiField(provided=true) what means the object will be created by java code and not by UiBinder.
For add events I use @UiHandler("save") annotation where "save" identifies the button Save.

ColaboradorEditor.ui.xml

AppImages.java

I am using a ClientBundle for application images and this class is injected by GIN where is needed and is not necessary use GWT.create.

EntityBase.java

There is not database table associated with this class. RequestFactory need a two fields in every domain class "id" and "version" these are columns in database table too.

Colaborador.java

Here I have my entity class. In eclipse I can use a wizard to generate this entity class.
First you should enable JPA Facet in your eclipse project.

You need configure a data source Window -->Show View --> Data Source Explorer
and create a new connection


Right click on your package and select  New --> JPA Entities from tables


RequestFactory with Guice
RequestFactory is not integrate with Guice por default. In that case there is a helpful set of classes that make RequestFactory injectable https://github.com/etiennep/injected-requestfactory. I only did copy and paste of that classes.

web.xml

Here I configure GuiceFilter. And GuiceServletContextListener.

MyGuiceServletConfig.java


In Guice you can configure all servlets and filters in java code here I configure my InjectedRequestFactoryServlet not use web.xml anymore. More info http://code.google.com/p/google-guice/wiki/ServletModule.

persistence.xml

Here I configured my connections parameters.

ColaboradorDao.java

Here I use injection fields to inject the Entity Manager and an Util class Paginate. Entity manager is initialized by Guice http://code.google.com/p/google-guice/wiki/JPA .
In JPA all objects are not persisted before commit the transaction. In Guice there is a useful annotation @Transactional http://code.google.com/p/google-guice/wiki/Transactions that made the method transactional.

ColaboradorPagingLoadResultBean.java

This class that extend PagingLoadResultBean is needed for objects that will be shown in a GXT Grid.

Paginate.java

This class use CriteriaBuilder for paginate a database table. http://www.ibm.com/developerworks/java/library/j-typesafejpa/

EntityLocator.java

In Request Factory you work with interfaces that are Proxy and require a locator. This is a generic locator for all Proxies.

ColaboradorProxy.java

This is the object that you use in your GWT code and is initialized using GWT.create sent to the server and Request Factory does the magic to translate this proxy in an entity object. This proxy extend EntityProxy because represent a domain class or a database table.

ColaboradorService.java

For each database table I create a Service or RequestContext. The proxy ColaboradorPagingLoadResultProxy is required for GXT.

AppRequestFactory.java

Here I configure all my services.

Internationalization with GWT
I use two properties files

Messages.properties


Messages_es_PE.properties

There is needed an aditional interface. In GWT that interface could be generated.
Go to project path and write the command mvn gwt:i18n

Is generated in target/generated-sources

You should add to build path right click on generated-sources/gwt folder  Build Path --> Use as Source Folder.
You can use command mvn gwt:run to launch the Hosted Mode.

jueves, 16 de febrero de 2012

Basic Grid with GXT3


En el siguiente ejemplo uso I am using GWT 2.4, AppEngine 1.7.0

A continuación muestro un pantallazo del ejemplo. Next is the screenshot of the example
El codigo Fuente lo encuentran aqui:The source code is here:  https://github.com/poseidonjm/GAE-GXT3
Demo http://gae-gxt3-basic.appspot.com/
La estructura del proyecto:The project organization:

Introducción:
 A continuación voy a mostrar un ejemplo básico de como hacer un CRUD utilizando GXT3 RequestFactoryEditorDriver teniendo en el servidor a Objectify como medio de persistencia. Al igual que en posts anteriores voy a utilizar AppEngine, pero igualmente podria utilizar una base de datos relacional y JPA para la persistencia.
Introduction:
In this post I show a basic example of how to build a CRUD using GXT3 and RequestFactoryEditorDriver with Objectify and AppEngine, but I could use a relational database and JPA for the ORM. EXT GWT 2 a GXT3
La nueva versión de GXT3 tiene como objetivo hacerlo más compatible con GWT. Por ejemplo utilizar los eventos de GWT, soporte para UIBinder, hacer el binding con el Editor Framework, etc.Más información lo pueden encontrar en la presentación de senchacon2011 http://www.slideshare.net/senchainc/migrating-from-ext-gwt-2x-to-30-10013673
y el video http://vimeo.com/33640855.
Debido a esta actualización varios componentes de gxt2 fueron removidos para ser reemplazados por componentes propios de GWT. Por ejemplo El FormBinding fue removido para se reemplazado por el Editor de GWT. En GXT2 los modelos debían heredar del ModelData para poder se mostrados en los componentes de datos. El objetivo del uso del ModelData era para poder acceder a las propiedades de los objetos ya que GWT no soporta Java Reflection. En la versión de GXT3 los objetos son simples POJOS (Objetos planos) y para acceder a las propiedades de los objetos utiliza una interfaz llamada PropertyAccess<T> . Para lograr esto el equipo de EXT GWT de Sencha tuvo que reescribir los stores desde cero.
Otro cambio importante es el renderizado de componentes. En GWT los componentes se renderizan cuando se llama al constructor del objeto. lo que no ocurría en GXT2. Pero en GXT3 ya es posible acceder al DOM desde el constructor ya que se renderiza al igual que un componente de GWT.
En GXT3 se hizo una cambio en los Layouts http://www.slideshare.net/senchainc/ext-gwt-30-layouts . Por ejemplo ahora existen un ContentPanel y un FramedPanel y el método setFramed fue removido.



EXT GWT 2 to GXT3
The new GXT3 is going to be more compatible with GWT. Will use system events of GWT, UiBinder support, binding with Editor Framework. For More information you can see the slides of senchacon2011 http://www.slideshare.net/senchainc/migrating-from-ext-gwt-2x-to-30-10013673 and on Vimeo http://vimeo.com/33640855.
Because this is the major upgrade of GXT, some GXT2 components was removed in GXT3 and replaced with GWT components. For example: The FormBinding was replaced by The Editor Framework. GXT2 models have to extend ModelData because is a requirement for data components. The use of ModelData is for get access to object properties because GWT does not support Java Reflection. In GXT3 models are simple POJOS and for get access to object properties use PropertyAccess<T> interface. And The EXT GWT team had to build stores from scratch.
The renderized of GXT2 components was called Lazy Rendered and you couldn't access to DOM in constructor. In GXT3 you could access to DOM in constructor and the renderizer is the same as GWT.
In GXT3 Layouts was modified http://www.slideshare.net/senchainc/ext-gwt-30-layouts . Now we have a ContentPanel and FramedPanel and the method setFramed was removed.
Los metodos como setTopComponent y setBottomComponent fueron removidos del ContentPanel
y ahora se utilizara el VerticalLayoutContainer para posicionar los toolbars.
En GXT3 es posible utilizar el ClientBundle de GWT para optimizar la descarga de tus imágenes y estilos. Por ejemplo ahora todas las imágenes de tu sitio estarán en un paquete de tu código fuente ya no en la carpeta pública. En GXT2 era necesario hacer un link en el html al archivo css de gxt2 y copiar la carpeta resources con las imágenes requeridas a la carpeta pública e tu sitio. Pero en GXT3 gracias al uso del ClientBundle todos los archivos de recursos están incluidos en el jar de GXT.
The methods like setTopComponent and setBottomComponent were removed and replaced by VerticalLayoutContainer for toolbars.
In GXT3 you can use ClientBundle  of GWT for images and styles. All images should be in a package. And all resources of GXT3 like images and styles are in jar of GXT.

Adicionalmente ahora GXT3 tiene su propia librería para la generación de gráficos estadísticos http://www.sencha.com/blog/ext-gwt-3-drawing-and-charting/ a diferencia de GXT2 que utilizaba una librería de un tercero basado en flash llamado OpenFlashChart.

Algunos Inconvenientes en GXT3 ?
En GXT2 he utilizado mucho la característica del FormButtonBinding para que el botón guardar de un formulario permaneciera desactivado mientras existan campos inválidos. Pero en GXT3 aún no se si esta característica se mantendra http://www.sencha.com/forum/showthread.php?177964-FormButtonBinding-is-there-a-replacement


Some troubles in GXT3?
I used FormButtonBinding feature a lot, to make buttons disable while the fields are invalid. But in GXT3 I don't know how can I do that  http://www.sencha.com/forum/showthread.php?177964-FormButtonBinding-is-there-a-replacement
ExampleRF por dentro
ExampleRF in detail

La aplicación de ejemplo usa AppEngine y Objectify para el almacenamiento de datos y RequestFactory para la comunicación con el servidor.
The example was build using AppEngine and Objectify for persistence and  RequestFactory for interact with the server side.

Archivo de Módulo GWT ExampleRF.gwt.xml
Module file ExampleRF.gwt.xml

<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='examplerf'>  
  <inherits name='com.google.gwt.user.User'/>
  <inherits name="com.googlecode.objectify.Objectify" />
  <inherits name='com.google.web.bindery.requestfactory.RequestFactory' /> 
  <inherits name='com.sencha.gxt.ui.GXT'/>
  <inherits name="com.sencha.gwt.uibinder.UiBinder" />  
  <entry-point class='com.examplerf.client.ExampleRF'/>  
  <source path='client'/>
  <source path='shared'/>
</module>

Aquí el único mudulo necesario es com.sencha.gxt.ui.GXT adicionalmente necesita de otro módulo com.sencha.gwt.uibinder.UiBinder para poder declarar atributos personalizados en UiBinder según sencha ya no será necesario en GWT 2.5.
The module needed is com.sencha.gxt.ui.GXT and for custom attributes in UiBinder com.sencha.gwt.uibinder.UiBinder is required and not will need in GWT 2.5

Archivo html ExampleRF.html
Html file ExampleRF.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="reset.css">
    <link type="text/css" rel="stylesheet" href="ExampleRF.css">

    <title>Web Application Starter Project</title>    
    <script type="text/javascript" language="javascript" src="examplerf/examplerf.nocache.js"></script>
  </head>
  <body>
    
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
    
  </body>
</html>

Aquí mi archivo ExampleRF.css es un archivo en blanco. Según sencha el único archivo de recursos necesario es reset.css
ExampleRF.cc is an empty file. And the resource file needed is reset.css

/**
 * Ext GWT 3.0.0-SNAPSHOT - Ext for GWT
 * Copyright(c) 2007-2011, Sencha, Inc.
 * licensing@sencha.com
 *
 * http://sencha.com/license
 */
html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}

Mi Clase DAO ColaboradorDao
My Class DAO ColaboradorDao

package com.examplerf.server.service;

import java.util.List;

import com.examplerf.server.domain.Colaborador;
import com.examplerf.server.domain.ColaboradorListLoadResultBean;

public class ColaboradorDao extends ObjectifyDao<Colaborador> {
 
 public void save(Colaborador colaborador){
  this.put(colaborador);
 }
 
 public void remove(Colaborador colaborador){
  this.delete(colaborador);
 } 

 public ColaboradorListLoadResultBean list() {
  List<Colaborador> list = listAll();  
  return new ColaboradorListLoadResultBean(list);
 }
}
Aquí la clase de dominio es Colaborador y ColaboradorListLoadResulBean es una clase adicional requerida para poderse mostrar en los componentes de datos de GXT3.
The domain class is Colaborador and ColaboradorListLoadResulBean is required for data components.

Colaborador.java
package com.examplerf.server.domain;

import com.googlecode.objectify.annotation.Entity;

@Entity
public class Colaborador extends DatastoreObject {
 private String nombres;
 private String apellidos;
 private Integer edad;
 public String getNombres() {
  return nombres;
 }
 public void setNombres(String nombres) {
  this.nombres = nombres;
 }
 public String getApellidos() {
  return apellidos;
 }
 public void setApellidos(String apellidos) {
  this.apellidos = apellidos;
 }
 public Integer getEdad() {
  return edad;
 }
 public void setEdad(Integer edad) {
  this.edad = edad;
 } 
}
ColaboradorListLoadResulBean.java
package com.examplerf.server.domain;

import java.util.List;

import com.sencha.gxt.data.shared.loader.ListLoadResultBean;

@SuppressWarnings("serial")
public class ColaboradorListLoadResultBean extends ListLoadResultBean<Colaborador> {
    public ColaboradorListLoadResultBean(List<Colaborador> list) {
      super(list);
    }
    public ColaboradorListLoadResultBean() {
        super();
    }
}
Mi clase RequestContext ColaboradorService
My class RequestContext ColaboradorService

package com.examplerf.shared.service;

import java.util.List;

import com.examplerf.server.domain.ColaboradorListLoadResultBean;
import com.examplerf.server.locator.DaoServiceLocator;
import com.examplerf.server.service.ColaboradorDao;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
import com.sencha.gxt.data.shared.loader.ListLoadResult;

@Service(value = ColaboradorDao.class, locator = DaoServiceLocator.class)
public interface ColaboradorService extends RequestContext {
 
 Request<Void> save(ColaboradorProxy colaborador); 
 Request<Void> remove(ColaboradorProxy colaborador);
  
 @ProxyFor(value = ColaboradorListLoadResultBean.class)
 public interface ColaboradorListLoadResultProxy extends ValueProxy, ListLoadResult<ColaboradorProxy> {
     @Override
     public List<ColaboradorProxy> getData();
 }
 
 Request<ColaboradorListLoadResultProxy> list(); 
}
En GWT 2.4 es necesario validar los RequestContext, cada vez que se modifica este archivo se debe hacer un clean al proyecto Project->Clean . Aquí la unica interfaz especial es ColaboradorListLoadResultProxy y es necesaria para poder llenar el Grid con datos. Nuestro método list() debe retornar objetos de este tipo.
RequestContest in GWT 2.4 have to be validated, every time is modified you have to clean the project Project->Clean . ColaboradorListLoadResultProxy interface is needed for data components.

Mi Proxy ColaboradorProxy
My Proxy ColaboradorProxy

package com.examplerf.shared.proxy;

import com.examplerf.server.domain.Colaborador;
import com.examplerf.server.locator.ObjectifyLocator;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;

@ProxyFor(value = Colaborador.class, locator = ObjectifyLocator.class)
public interface ColaboradorProxy extends EntityProxy {
 String getNombres();
 void setNombres(String nombres);
 String getApellidos();
 void setApellidos(String apellidos);
 Integer getEdad();
 void setEdad(Integer edad); 
 Long getId();
 void setId(Long id);
}
La interfaz ColaboradorProxy.java representa a la clase de dominio Colaborador.java y sirve para hacer la persistencia desde el cliente. Más información aquí http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html .
ColaboradorProxy.java interface is like domain class Colaborador.java but in the client side. More about RequestFactory http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html .


Diseñando mi Formulario con UiBinder: ColaboradorEditor.ui.xml
Designing my Form with UiBinder: ColaboradorEditor.ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
 xmlns:g="urn:import:com.google.gwt.user.client.ui"
 xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
 xmlns:form="urn:import:com.sencha.gxt.widget.core.client.form"
 xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container"
 xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button" >
 
 <ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" />
 
 <ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="verticalLayoutData">
     <ui:attributes width="1" height="-1" />
   </ui:with>
      
 <ui:style>
  .important {
   font-weight: bold;
  }
 </ui:style>
 
   <gxt:FramedPanel ui:field="form" headerVisible="false" buttonAlign="END" >
     <form:FieldSet ui:field="fieldSet" headingText="User Information" collapsible="false"  >
       <container:VerticalLayoutContainer>
         <container:child layoutData="{verticalLayoutData}">
           <form:FieldLabel text="First Name">
                <form:widget>
                  <form:TextField ui:field="nombres" allowBlank="false" />
                </form:widget>
              </form:FieldLabel>
         </container:child>
         <container:child layoutData="{verticalLayoutData}">
           <form:FieldLabel text="Last Name">
                <form:widget>
                  <form:TextField ui:field="apellidos" allowBlank="false" />
                </form:widget>
              </form:FieldLabel>              
         </container:child>
         <container:child layoutData="{verticalLayoutData}">
           <form:FieldLabel text="Age">
                <form:widget>
                  <form:NumberField ui:field="edad" />
                </form:widget>
              </form:FieldLabel>
         </container:child>
       </container:VerticalLayoutContainer>
     </form:FieldSet>
     
     <gxt:button>
       <button:TextButton text="Save" ui:field="save" icon="{images.save}" />
     </gxt:button>
     <gxt:button>
       <button:TextButton text="Cancel" ui:field="cancel" icon="{images.cancel}" />
     </gxt:button>
          
   </gxt:FramedPanel>

</ui:UiBinder>
Para Poder usar el FramedPanel es necesario importar el namespace
xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
igualmente se han importato el resto de namespaces.
Para poder utilizar las imágenes en el código UiBinder es necesario referenciar al ClientBundle con la etiqueta <ui:with>
<ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" />
For FramedPanel is needed import the namespace
xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
likewise import the rest of namespaces.
For imáges in ClientBundle and UiBinder is needed put  <ui:with>
<ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" />

Lo siguiente es una forma de declarar los layout data en UiBinder (necesita el jar adicional). También e posible hacerlo por código pero yo prefiero el xml
The following code show a way to declare custom attributes like layout data inn UiBinder (aditional jar is required). You could declare layout data in code but I prefer xml

<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="verticalLayoutData">
    <ui:attributes width="1" height="-1" />
</ui:with>

El ClientBundle ExampleRFImages.java
The ClientBundle ExampleRFImages.java

package com.examplerf.client.images;

import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;

public interface ExampleRFImages extends ClientBundle {

 public ExampleRFImages IMAGES = GWT.create(ExampleRFImages.class);
 
 @Source("add.gif")
 ImageResource add();
 
 @Source("delete.gif")
 ImageResource delete();
 
 @Source("update.png")
 ImageResource update();
 
 @Source("save.png")
 ImageResource save();
 
 @Source("cancel.png")
 ImageResource cancel();
}
Las imágenes están en el mismo paquete:
The images are in the same package:




La Clase Manejadora ColaboradorEditor.java
Handler Class ColaboradorEditor.java

package com.examplerf.client;

import com.examplerf.client.events.SaveEvent;
import com.examplerf.client.events.SaveEventHandler;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.FramedPanel;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor;
import com.sencha.gxt.widget.core.client.form.TextField;

public class ColaboradorEditor implements Editor<ColaboradorProxy>, HasHandlers {

 private HandlerManager handlerManager;
 
 private static ColaboradorUiBinder uiBinder = GWT.create(ColaboradorUiBinder.class);

 interface ColaboradorUiBinder extends UiBinder<Widget, ColaboradorEditor> {
 }
 @UiField
 FramedPanel form;
 
 @UiField
 TextField nombres;
 
 @UiField
 TextField apellidos;
 
 @UiField(provided = true)
 NumberField<Integer> edad;
  
 Window panel;
 
 public ColaboradorEditor() {
  handlerManager = new HandlerManager(this);
  panel = new Window();
  panel.setResizable(false); 
  
  edad = new NumberField<Integer>(new NumberPropertyEditor.IntegerPropertyEditor());
  //edad.setAllowDecimals(false);
  
  panel.setWidget(uiBinder.createAndBindUi(this));
  form.getHeader().setVisible(false);  
 }
  
 public void show(String title){
  panel.setHeadingText(title);
  panel.show();
 }  
 
 @UiHandler("save")
 public void onSave(SelectEvent event){  
  fireEvent(new SaveEvent());
 }
 
 @UiHandler("cancel")
 public void onCancel(SelectEvent event){
  hide();
 }

 @Override
 public void fireEvent(GwtEvent<?> event) {
  handlerManager.fireEvent(event);  
 }
 
 public HandlerRegistration addSaveEventHandler(
            SaveEventHandler handler) {
        return handlerManager.addHandler(SaveEvent.TYPE, handler);
    }

 public void clearFields() {
  nombres.clearInvalid();
  apellidos.clearInvalid();  
 }
 
 public void hide() {
  panel.hide();
 }
 
 public boolean isValid() {
  boolean n = nombres.isValid();
  boolean a = apellidos.isValid();
  return n && a;
 }

}
Este Editor esta implementando la interfaz HasHandler para poder enviar eventos personalizados. en este caso el evento SaveEvent. Es importante recordar que si se quiere hacer el binding de un objeto ColaboradorProxy con los campos de texto, estos campos de texto deben existir como variables en el código java. No basta con declarar la caja de texto en UiBinder. Si el TextField nombres sólo se encuentra en el archivo UiBinder y no como variable de clase el GWT Editor no podra hacer el binding.
This Editor is immlementing HasHandler interface for send custom events. The event is SaveEvent. Is important remember that Editor Framework need the fields like class attributes. Is not enough put the fields in UiBinder is needed declare the fields like class attributes.

@UiField
 TextField nombres;
 


Resumen de Eventos en GWT:
Summary of Events in GWT:

Extraido de http://stackoverflow.com/questions/2951621/gwt-custom-events
Los eventos son siempre enviados para informar sobre algo(por ejemplo el cambio de un estado). Los eventos existen en todos los sistemas y frameworks. Para poder enviar y recibir eventos es necesario lo siguiente:
Extracted from http://stackoverflow.com/questions/2951621/gwt-custom-events
Events are always sent to inform about something (e.g. a change of state). This is how events work in general in every system or framework (not only in GWT). In order to send and receive events in such systems you have to define:
  1. Que es lo que es va a enviar (algun objeto). Esto es opcional.
  2. Quién recibe el evento.
  3. Quién envía el evento.
  1. What is sent (some object). It is not required.
  2. Who receives events (event receivers).
  3. Who sends events (event senders).
Evento SaveEvent
Event SaveEvent

Este evento se encargara de ejecutar una acción cuando el usuario pulsa en el botón Save. Las clases de eventos los puse en un paquete client.events
This event will do something when the user to click in button Save. The events class are in client.events package.

La Clase SaveEvent.java
Class SaveEvent.java

package com.examplerf.client.events;

import com.google.gwt.event.shared.GwtEvent;

public class SaveEvent extends GwtEvent<SaveEventHandler> {

 public static Type<SaveEventHandler> TYPE = new Type<SaveEventHandler>();
 
 @Override
 public Type<SaveEventHandler> getAssociatedType() {
  return TYPE;
 }

 @Override
 protected void dispatch(SaveEventHandler handler) {
  handler.onSave(this);
 }

}
Toda clase que representa un evento GWT debe extender GwtEvent esta clase contiene dos metodos abstractos que deben ser implementados getAssociatedType y dispatch.
Every class representing a GWT event has to extend GwtEvent class. This class contains two abstract methods which must be implemented: getAssociatedType and dispatch.

La Interfaz SaveEventHandler.java
Interface SaveEventHandler.java

En GWT el que recibe el evento es llamado Handler. En este ejemplo la interfaz que recibe el evento es SaveEventHandler.
In GWT receivers are called handlers. In the example an event receiver interface will be named SaveEventHandler.

package com.examplerf.client.events;

import com.google.gwt.event.shared.EventHandler;

public interface SaveEventHandler extends EventHandler {

 void onSave(SaveEvent saveEvent);

}
Todo Handler debe extender la interfaz EventHandler. También debe definir el método que será llamado cuando el evento ocurra.
Each handler has to extend EventHandler interface. It should also define a method which will be invoked when an event occurs.

Quien envia el evento ColaboradorEditor.java
Define event senders ColaboradorEditor.java

package com.examplerf.client;

import com.examplerf.client.events.SaveEvent;
import com.examplerf.client.events.SaveEventHandler;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.FramedPanel;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor;
import com.sencha.gxt.widget.core.client.form.TextField;

public class ColaboradorEditor implements HasHandlers {

 private HandlerManager handlerManager; 
 
 public ColaboradorEditor() {
  handlerManager = new HandlerManager(this);
 }
   
 
 @UiHandler("save")
 public void onSave(SelectEvent event){  
  fireEvent(new SaveEvent());
 } 

 @Override
 public void fireEvent(GwtEvent<?> event) {
  handlerManager.fireEvent(event);  
 }
 
 public HandlerRegistration addSaveEventHandler(
            SaveEventHandler handler) {
        return handlerManager.addHandler(SaveEvent.TYPE, handler);
    }

}
Todo el que envía un evento debe implementar la interfaz HasHandlers. El elemento más importante aquí es HandlerManager como el nombre lo dice gestiona los Event Handler (manejadores de eventos). Todo evento recibidor que quiere recibir eventos debe registrarse asi mismo como interesado. Para eso son los handler managers. Ellos hacen posible registrar los manejadores de eventos (event handlers) para que puedan enviar un evento en particular a todos los manejadores de eventos registrados.
Cuando un HandlerManager es creado toma un argumento en su constructor. Todo un evento tiene una fuente de origen y este parametro sera usado como origen para todos los eventos enviados por este handler manager en el ejemplo es this como el origen de eventos es ColaboradorEditor.
El metodo fireEvent esta definido en la interfaz HasHandler y es responsable de enviar eventos. Como puede ver sólo usa un handler manager para enviar(fire) un evento.
addSaveEventHandler es usado por todos los recibidores de eventos para registrarse asi mismos como interesados en recibir eventos. De nuevo handler manager es usado para esto.
aEvery event sender has to implement HasHandlers interface.

The most important element here is a HandlerManager field. In GWT HandlerManager as the name suggest manages event handlers (event receivers). As it was said at the beginning every event receiver that wants to receive events must register itself as interested. This is what handler managers are for. They make it possible to register event handlers an they can send a particular event to every registered event handler.

When a HanlderManager is created it takes one argument in its constructor. Every event has a source of origin and this parameter will be used as a source for all events send by this handler manager. In the example it is this as the source of events is ColaboradorEditor.

The method fireEvent is defined in HasHandlers interface and is responsible for sending events. As you can see it just uses a handler manager to send (fire) and event.

addSaveEventHandler is used by event receivers to register themselves as interested in receiving events. Again handler manager is used for this.

Vincular el recibidor de eventos con el que envía el evento.
Bind event receivers with event senders.

public class ExampleRF implements EntryPoint{
              private ColaboradorEditor editor;
              public void onModuleLoad() {
  
  editor = new ColaboradorEditor();  

  editor.addSaveEventHandler(new SaveEventHandler() {
   
   @Override
   public void onSave(SaveEvent saveEvent) {
    
   }
  });
}
}
Como parámetro de addSaveEventHandler estoy pasando una clase anónima que es el recibidor de eventos y se registra asi mismo en el enviador de eventos ColaboradorEditor.
When everything is defined event receivers must register themselves in event senders. Now all events sent by   ColaboradorEditor will be received by anonymous class.

Enviar eventos
Send events

Para enviar un evento ColaboradorEditor debe crear una instancia de evento y enviarlo usando el método fireEvent.
To send an event, ColaboradorEditor must create an event instance and send it using fireEvent method

 @UiHandler("save")
 public void onSave(SelectEvent event){  
  fireEvent(new SaveEvent());
 }

El archivo  ExampleRF.ui.xml
File  ExampleRF.ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui"
    xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
    xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container"
    xmlns:toolbar="urn:import:com.sencha.gxt.widget.core.client.toolbar"
    xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button"
    xmlns:grid="urn:import:com.sencha.gxt.widget.core.client.grid" >
    
    <ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" />
    
    <ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="verticalLayoutData">
     <ui:attributes width="1" height="-1" />
   </ui:with>
   
   <ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="centerLayoutData">
     <ui:attributes width="1" height="1" />
   </ui:with>
   
   
    <ui:style>
      .background {
        background-color: white;
      }
    </ui:style>
    <g:VerticalPanel spacing="10">
      <gxt:FramedPanel ui:field="panel" collapsible="true" headingText="RequestFactory Grid Example" pixelSize="550, 300">
        <container:VerticalLayoutContainer borders="true" addStyleNames="{style.background}">
          <container:child layoutData="{verticalLayoutData}">
            <toolbar:ToolBar>
              <button:TextButton text="Add" ui:field="add" icon="{images.add}" />
              <toolbar:SeparatorToolItem />
              <button:TextButton text="Edit" ui:field="edit" icon="{images.update}" enabled="false" />
              <toolbar:SeparatorToolItem />
              <button:TextButton text="Delete" ui:field="delete" icon="{images.delete}" enabled="false" />
              <toolbar:FillToolItem />
            </toolbar:ToolBar>
          </container:child>
          <container:child layoutData="{centerLayoutData}" >
            <grid:Grid ui:field="grid" />                        
          </container:child>          
        </container:VerticalLayoutContainer>
      </gxt:FramedPanel>
    </g:VerticalPanel>
</ui:UiBinder>

El EntryPoint ExampleRF.java
The EntryPoint ExampleRF.java

package com.examplerf.client;

import java.util.ArrayList;
import java.util.List;

import com.examplerf.client.events.SaveEvent;
import com.examplerf.client.events.SaveEventHandler;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.examplerf.shared.service.ColaboradorService;
import com.examplerf.shared.service.ExampleRFRequestFactory;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.sencha.gxt.core.client.Style.SelectionMode;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.PropertyAccess;
import com.sencha.gxt.data.shared.loader.ListLoadConfig;
import com.sencha.gxt.data.shared.loader.ListLoadResult;
import com.sencha.gxt.data.shared.loader.ListLoader;
import com.sencha.gxt.data.shared.loader.LoadResultListStoreBinding;
import com.sencha.gxt.data.shared.loader.RequestFactoryProxy;
import com.sencha.gxt.widget.core.client.Dialog;
import com.sencha.gxt.widget.core.client.box.ConfirmMessageBox;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.HideEvent.HideHandler;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.info.Info;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent.SelectionChangedHandler;

public class ExampleRF implements EntryPoint, IsWidget {
 interface ColaboradorProxyProperties extends PropertyAccess<ColaboradorProxy> {
     ModelKeyProvider<ColaboradorProxy> id();
     ValueProvider<ColaboradorProxy, String> nombres();
     ValueProvider<ColaboradorProxy, String> apellidos();
     ValueProvider<ColaboradorProxy, Integer> edad();
 }
 
 interface MyUiBinder extends UiBinder<Widget, ExampleRF> {
 }
 
 private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
 
 private final ExampleRFRequestFactory myRF = GWT.create(ExampleRFRequestFactory.class);
  
 interface Driver extends RequestFactoryEditorDriver<ColaboradorProxy, ColaboradorEditor>{  
 }
 Driver driver = GWT.create(Driver.class);
 
 private ColaboradorEditor editor;
 
 private ColaboradorService cs;
 private ColaboradorProxy colaborador;
 private ListStore<ColaboradorProxy> store;
 private ListLoader<ListLoadConfig, ListLoadResult<ColaboradorProxy>> loader; 
 
 @UiField(provided = true)
 Grid<ColaboradorProxy> grid;
 
 @UiField
 TextButton edit;
 
 @UiField
 TextButton delete;
 
 public void onModuleLoad() {
  myRF.initialize(new SimpleEventBus());
  editor = new ColaboradorEditor();  
  driver.initialize(myRF, editor);
  editor.addSaveEventHandler(new SaveEventHandler() {
   
   @Override
   public void onSave(SaveEvent saveEvent) {
    
    RequestContext context = driver.flush();
    if(!driver.hasErrors()&&editor.isValid()){
     editor.hide();
     context.fire(new Receiver<Void>() {
      
      @Override
      public void onSuccess(Void response) {
       Info.display("ExampleRF", "Se guardo correctamente");      
       loader.load();
      }
     });
    }
      
   }
  });  
  
  RootPanel.get().add(this);  
  
 } 

 @Override
 public Widget asWidget() {
  RequestFactoryProxy<ListLoadConfig, ListLoadResult<ColaboradorProxy>> proxy = new RequestFactoryProxy<ListLoadConfig, ListLoadResult<ColaboradorProxy>>() {
   
   @Override
   public void load(ListLoadConfig loadConfig,
     Receiver<? super ListLoadResult<ColaboradorProxy>> receiver) {
    ColaboradorService cs = myRF.colaboradorService();
    cs.list().to(receiver);
    cs.fire();    
   }
  };
  
  loader = new ListLoader<ListLoadConfig, ListLoadResult<ColaboradorProxy>>(proxy);
  ColaboradorProxyProperties props = GWT.create(ColaboradorProxyProperties.class);
  
  store = new ListStore<ColaboradorProxy>(props.id());
  loader.addLoadHandler(new LoadResultListStoreBinding<ListLoadConfig, ColaboradorProxy, ListLoadResult<ColaboradorProxy>>(store));
    
     
     ColumnConfig<ColaboradorProxy, String> nombresColumn = new ColumnConfig<ColaboradorProxy, String>(props.nombres(), 150, "Nombres");
     ColumnConfig<ColaboradorProxy, String> apellidosColumn = new ColumnConfig<ColaboradorProxy, String>(props.apellidos(), 150, "Apellidos");
     ColumnConfig<ColaboradorProxy, Integer> edadColumn = new ColumnConfig<ColaboradorProxy, Integer>(props.edad(), 80, "Edad");
     
     List<ColumnConfig<ColaboradorProxy, ?>> l = new ArrayList<ColumnConfig<ColaboradorProxy, ?>>();
     l.add(nombresColumn);
     l.add(apellidosColumn);
     l.add(edadColumn);
     
     ColumnModel<ColaboradorProxy> cm = new ColumnModel<ColaboradorProxy>(l);
     
     grid = new Grid<ColaboradorProxy>(store, cm) {
         @Override
         protected void onAfterFirstAttach() {
           super.onAfterFirstAttach();
           Scheduler.get().scheduleDeferred(new ScheduledCommand() {
             @Override
             public void execute() {
               loader.load();
             }
           });
         }
     };
     
     grid.setLoader(loader);
     grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);     
     
     grid.getSelectionModel().addSelectionChangedHandler(new SelectionChangedHandler<ColaboradorProxy>() {

   @Override
   public void onSelectionChanged(
     SelectionChangedEvent<ColaboradorProxy> event) {
    int size = event.getSelection().size();
    if(size == 0){     
      edit.setEnabled(false);
      delete.setEnabled(false);
    }else if(size == 1){      
      edit.setEnabled(true);
      delete.setEnabled(true);
    }else if(size > 1){
      edit.setEnabled(false);
      delete.setEnabled(true);
    }       
    
   }
  });

     return uiBinder.createAndBindUi(this);
 }
 
 @UiHandler("add")
 public void onAdd(SelectEvent event){
  
  cs = myRF.colaboradorService();
  colaborador = cs.create(ColaboradorProxy.class);
  cs.save(colaborador);
  driver.edit(colaborador, cs);
  editor.clearFields();
  editor.show("Nuevo Colaborador");
 }
 
 @UiHandler("edit")
 public void onEdit(SelectEvent event){
  cs = myRF.colaboradorService(); 
  
  colaborador = grid.getSelectionModel().getSelectedItem();
  cs.save(colaborador);
  driver.edit(colaborador, cs);
  editor.clearFields();
  editor.show("Editar Colaborador");
 }
 
 @UiHandler("delete")
 public void onDelete(SelectEvent event){
  ConfirmMessageBox box = new ConfirmMessageBox("ExampleRF", "Esta seguro que desea eliminar?");
  box.addHideHandler(new HideHandler() {
   
   @Override
   public void onHide(HideEvent event) {
    Dialog btn = (Dialog) event.getSource();
    if("Yes".equals(btn.getHideButton().getText())){
     cs = myRF.colaboradorService(); 
     colaborador = grid.getSelectionModel().getSelectedItem();
     cs.remove(colaborador).fire(new Receiver<Void>() {
      
      @Override
      public void onSuccess(Void response) {
       Info.display("ExampleRF", "Se elimino correctamente");
       loader.load();
      }
     });
    }
   }
  });
  box.show();  
 } 
 
}
Eso es todo por hoy espero les sea de ayuda.
That's all for now, I hope it helps someone