Eclipse-Databinding 3.5 for GWT


I’m a big fan of GWT but one of the real pain points when developing GWT applications is that there’s no databinding framework [*] available to synchronize your domain objects and UI-Widgets.

As many of you know I’m an even bigger fan of Eclipse-Databinding because it is written so that it can be used with ANY Model-Technology you want and even more important ANY UI-Technology you want and in fairly every environment you want (or at least porting to it is possible without too much trouble).

I’m happy to announce that the days without a databinding solution are gone forever now because yesterday in the night I made Eclipse-Databinding 3.5 compile under GWT and already wrote the first WidgetProperty implementations for Text and Label-Widgets.

Take a look at this video to see it in action

The code used to create this small presentation looks like this:

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.value.ComputedValue;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.ufacekit.core.ubean.databinding.observables.UBeansObservables;
import org.eclipse.ufacekit.ui.gwt.databinding.GWTObservables;
import org.eclipse.ufacekit.ui.gwt.databinding.IWidgetValueProperty;
import org.eclipse.ufacekit.ui.gwt.databinding.WidgetProperties;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class GWTDatabindingExample implements
		EntryPoint {
  /**
    * This is the entry point method.
    */
  public void onModuleLoad() {
    final Label titleLabel = new Label();
    final TextBox firstNameField = new TextBox();
    final TextBox lastNameField = new TextBox();
		
    final Person p = new Person();
    p.setFirstname("Tom");
    p.setLastname("Schindl");
		
    DataBindingContext dbc = new DataBindingContext(
      GWTObservables.getRealm()
    );
    IWidgetValueProperty uiProp = WidgetProperties.text();
		
    dbc.bindValue(
      uiProp.observe(firstNameField), 
      UBeansObservables.observeValue(
        GWTObservables.getRealm(), p, Person.FIRST_NAME
      )
    );

    dbc.bindValue(
      uiProp.observe(lastNameField), 
      UBeansObservables.observeValue(
        GWTObservables.getRealm(), p, Person.LAST_NAME
      )
    );
		
    ComputedValue titleValue = 
      new ComputedValue(GWTObservables.getRealm()) {
        private IObservableValue last = 
          UBeansObservables.observeValue(
            GWTObservables.getRealm(), p, Person.LAST_NAME
        );

       private IObservableValue first = 
         UBeansObservables.observeValue(
           GWTObservables.getRealm(), p, Person.FIRST_NAME
       );
			
      @Override
      protected Object calculate() {
        return last.getValue().toString().toUpperCase() 
          + ", " + first.getValue()
        ;
      }
    };

    dbc.bindValue(uiProp.observe(titleLabel), titleValue);

    RootPanel.get("titleContainer").add(titleLabel); 
    RootPanel.get("firstNameFieldContainer").add(
      firstNameField
    );
    RootPanel.get("lastNameFieldContainer").add(
      lastNameField
    );
  }
}

If you take a close look to the sources above the first thing you’ll spot is the usage of org.eclipse.ufacekit.core.ubean which is very light weight domain model implementation part of UFaceKit. The domain model has it’s own notification concept and a reflective API similar to EMF but is as light weight as possible.

A domain object implementation looks like this:

import org.eclipse.ufacekit.core.ubean.UBaseBean;
import org.eclipse.ufacekit.core.ubean.notify.Notification;

public class Person extends UBaseBean {
  public static final int FIRST_NAME = 1;
  public static final int LAST_NAME = 2;

  private String lastname;
  private String firstname;

  public void add(int featureId, Object value) {
    throw new IllegalArgumentException(
      "No multi feature with id '"+featureId+"'"
    );
  }

  @SuppressWarnings("unchecked")
  public <V> V get(int featureId) {
    if (featureId == FIRST_NAME) {
      return (V) getFirstname();
    } else if (featureId == LAST_NAME) {
      return (V) getLastname();
    }
    throw new IllegalArgumentException(
      "No feature with id '"+featureId+"'"
    );
  }

  public void remove(int featureId, Object value) {
    throw new IllegalArgumentException(
      "No multi feature with id '"+featureId+"'"
    );
  }

  public void set(int featureId, Object value) {
    if( featureId == FIRST_NAME ) {
      setFirstname((String) value);
    } else if( featureId == LAST_NAME ) {
      setLastname((String) value);
    } else {
      throw new IllegalArgumentException(
        "No feature with id '"+featureId+"'"
      );
    }
  }

  public String getLastname() {
    return lastname;
  }

  public void setLastname(String lastname) {
    notifyListeners(
      new Notification(
        this, 
        Notification.SET, 
        LAST_NAME,
        this.lastname, 
        this.lastname = lastname
      )
    );
  }

  public String getFirstname() {
    return firstname;
  }

  public void setFirstname(String firstname) {
    notifyListeners(
      new Notification(
        this, 
        Notification.SET, FIRST_NAME,
        this.firstname, 
        this.firstname = firstname
      )
    );
  }
}

The reflective API has the advantage that it doesn’t need reflection to call methods and thus is directly usable within GWT applications where no reflection is available. This is only the start of the many things UFaceKit is going to provide to you starting from full GWT-Databinding support over JFace-Viewer like implemenations to it’s highlevel UI-Abstraction.

For UFaceKit the support of GWT marks a new milestone because now we have a solution for another Java-Developer Community. We now support:

  • SWT/JFace – including a Java5 JFace-Viewer implementation
  • Qt – Qt-Databinding and Qt-JFace-Viewers
  • Swing – Swing-Databinding and Swing-Viewers (though this needs some TLC)
  • GWT – GWT-Databinding and start of GWT-Viewers (Combo, List and Tree)
  • UBean – a very lightweight model technology compatible with GWT

The sources are available from the UFaceKit-repository (you need to have the Google-Eclipse-Plugin installed) and an Eclipse 3.5 as the target (if you don’t want to see compile errors in your IDE)

* Update there are databinding-frameworks (GXT, gwittir) but they force me to buy into their whole framework and even reach out into my Domain-Model if I understood them appropiately.

This entry was posted in Databinding, GWT. Bookmark the permalink.

15 Responses to Eclipse-Databinding 3.5 for GWT

  1. Lars Vogel says:

    Hello Tom,

    very impressive and very useful. Thank you, Lars

  2. Kai Tödter says:

    Very cool, Tom! Do you plan to Open Source the GWT databinding integration?

  3. This seems to be a great solution. But, even if I like GWT, I think that its ‘client centric’ approach is a real problem because of domain objects detachment threw the Java->JS gateway. That’s why I prefer working on a server centric framework such as Apache Wicket in many cases.
    By the way, you made a useful work!

  4. Pingback: André seine Welt » Eclipse-Databinding 3.5 for GWT

  5. Tom, just a correction of your above statement: qooxdoo _is_ licensed under the EPL (and alternatively LGPL). So it can very easily be used within Eclipse projects (e.g. Eclipse RAP). 🙂

  6. tomeclipsedev says:

    Ah I see – I talked about a libary which builds on top of Qooxdoo developed by my company!

  7. Frode says:

    Excellent, one thing GWT has been lacking.

    Have you looked into using GWT generators to automatically decorate the domain objects with the listener and generic get/set methods? This should make it a lot easier to use (and avoid binding specific code in your domain model)

    Cheers,
    Frode

    • tomeclipsedev says:

      not yet but that’s definately an area we should explore in future for people whose domain model objects are only used in GWT (mine for example are used in GWT and Desktop-Applications) though there’s no binding specific code in the domain model but only the domain-model specific listener/notification system. This is one of strengths of Eclipse-Databinding because it doesn’t reach out to the domain model.
      Do you have any knowledge in this area you want to contribute to our UFaceKit-Project then file a bug and we can work on such a thing.

  8. Google Eclipse plugin does not install in Eclipse 3.5 yet.

    I’m running Eclipse 3.5 and tried to install the Eclipse plugin. I get
    the following error while trying to install:

    Cannot complete the install because one or more required items could not be
    found. Software being installed:

    com.google.gdt.eclipse.suite.e34.feature.feature.group 1.0.0.v200904062334

    Missing requirement:

    com.google.gdt.eclipse.suite.e34.feature.feature.group 1.0.0.v200904062334
    requires ‘org.eclipse.platform.feature.group [3.4.0,3.5.0)’ but it could
    not be found

    • tomeclipsedev says:

      The google plugin requires 3.4 – Since the blog post I modified the classpaths in a way that you can run the stuff on 3.4 where the google plugin is available. So please use the gwt.psf to setup your eclipse workspace in a 3.4 installation.

  9. Cyril Lakech says:

    Great news!

    Can we avoid to change our domain object with the notification API and the extend to UBaseBean ?
    or
    Can we have Simplest pojo AND databinding with GWT ?

    Regards,

    • tomeclipsedev says:

      The problem you always have with POJO is that it needs reflection which is not available out of the box so. POJO don’t have a notification concept either so in the only possibility I see if you don’t want your domain object to implement the UBean-Interface (you don’t necessary need to implement notifications) you need to wrap them or write your own Properties/Observable-implementation.

      Wrapping could look like this:
      ——–8<——–
      Person p = new Person();
      UBeanPerson facade = new UBeanPerson(p);
      ——–8<——–

      ——–8<——–
      public UBeanPerson extends UBaseBean {
      public static final int NAME = 1;

      private final Person p;

      public UBeanPerson(Person p) {
      this.p = p;
      }

      public void set(int attribute, Object value) {
      if( attribute == NAME ) {
      p.setName(value);
      }
      }
      }
      ——–8<——–

      If you somehow get reflection working you could naturally also simply copy the stuff from Eclipse-Databinding and patch it so that it runs under GWT. I thing I never explored until today is to use the possibility to let the GWT-Compiler generated the needed bindable object for you which would be the best solution in my eyes because then your POJO don't even need to fire events because this can all be done by the GWT compiler

  10. Trung says:

    See this project http://code.google.com/p/kauthara

    It uses Eclipse databinding for building up UI using JSP

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.