Showing posts with label GWT. Show all posts
Showing posts with label GWT. Show all posts

Tuesday, August 11, 2009

GWT Metawidget takes a walk on the client side

The latest release of Metawidget upgrades our GWT support to 1.7 and includes a new example of running pure client-side GWT:

By default, GwtMetawidget inspects business objects server-side. This is because client-side JavaScript does not support reflections or annotations.

However if you don't need reflections or annotations, and have your own way of retrieving inspection results, you can plug in your own Inspector and keep everything client-side. This example retrieves inspection results from a textarea and generates the UI.

Download the example here. More documentation can be found here.

Sunday, June 22, 2008

GWT and Metawidget Part 4: Over to you

A recent Metawidget bug report has highlighted I need better documentation around how to build your own GWT app. I will be putting this in the next release, but for now please note:
  • when building your app, you need both metawidget.jar and metawidget-gwt-client.jar in your compiler CLASSPATH
  • when deploying your app, you need metawidget.jar in your WEB-INF/lib and a reference to GwtRemoteInspectorImpl in your web.xml
  • you can see this in action in addressbook-gwt.war in the binary distribution
  • you may also find the example-gwt-addressbook Ant task in the source distribution's build.xml useful

Thanks to the anonymous bug reporter for highlighting this lack of documentation!

Tuesday, June 17, 2008

GWT and Metawidget Part 3: Binding

Update: the APIs shown in this blog entry have changed slightly in newer releases of Metawidget. Specifically bindings are now set using .addWidgetProcessor. Please download the latest documentation from http://metawidget.org

The latest release of Metawidget adds supports for Google Web Toolkit (GWT) 1.5. This series of blogs explores the challenges that had to be overcome to acheive this.

Two Way Binding

Almost all Web frameworks support some form of automatic two-way binding between Web pages and domain objects. Some supply sophisticated expression languages (Java Server Faces), others straight property name mapping (Struts), but most supply something.

Except GWT.

To be fair, Google are planning to add this feature in an upcoming release - but it's not there in 1.5 just yet. One of the main stumbling blocks is that most binding implementations use reflection, and JavaScript doesn't support reflection.

As an interim solution, Metawidget supplies SimpleBinding. Metawidget's binding implementations are pluggable, so we can swap in 'real' GWT binding one day, but for now SimpleBinding gets you most of the way: a simple two-way binding, including converters.

But! How do we solve the reflection problem?

As with the last blog entry, Generators are our friend. SimpleBinding uses SimpleBindingAdapters, and comes with a SimpleBindingAdapterGenerator that can generate SimpleBindingAdapters automatically for your business classes.

A SimpleBindingAdapter is capable of 'reflecting' every property (and even sub-property) of a business class by pre-generating code that automatically traverses getters and calls setters. In effect, it statically generates codes that looks like this:

if ( "address".equals( property[0] )) {
   Address address = contact.getAddress();
   if ( property.length == 1 ) return address;

   // Address properties

   if ( "street".equals( property[1] )) {
      if ( property.length > 2 )
         throw new RuntimeException( "Cannot reflect into property 'street." + property[2] + "'" );
      return address.getStreet();
   }

To stop the tree of possible properties getting too large, it restricts itself to only classes within the same package or sub-package.

To use SimpleBinding in your code, add the following to your application-name.gwt.xml file:

<generate-with class="org.metawidget.gwt.generator.binding.simple.SimpleBindingAdapterGenerator">
   <when-type-assignable class="org.metawidget.example.shared.addressbook.model.Contact"/>
</generate-with>

...and in your application code add...

metawidget.setBindingClass( SimpleBinding.class );
SimpleBindingAdapter<Contact> adapter = (SimpleBindingAdapter<Contact>) GWT.create( Contact.class );
SimpleBinding.registerAdapter( Contact.class, adapter );

How does this work in practice? See for yourself! The Metawidget download includes a pre-built sample application, addressbook-gwt.war, that showcases a GwtMetawidget using two-way bindings in the UI. It's covered in detail in the reference guide.

GWT and Metawidget Part 2: Pluggability

Update: the APIs shown in this blog entry have changed slightly in newer releases of Metawidget. Specifically Layouts are now set as an object instance, not as a class. Please download the latest documentation from http://metawidget.org

The latest release of Metawidget adds supports for Google Web Toolkit (GWT) 1.5. This series of blogs explores the challenges that had to be overcome to acheive this.

Pluggability

Pluggability is everywhere in Metawidget: pluggable inspectors, pluggable layout managers, pluggable binding implementations, etc. etc. The usual way this is acheived is through code like...

metawidget.setLayoutClass( TableLayout.class );

...which, somewhere behind the scenes, ends up calling...

layoutClass.newInstance();

GWT, however, is a very different kind of Web framework: it compiles Java to JavaScript, and JavaScript doesn't support newInstance.

But! Using GwtMetawidget, you can plug in different implementations by calling setLayout (and also setBinding, setInspector, etc.)! How is this possible?

GWT supplies a powerful concept called Generators. With a bit of work, you can use Generators to do all sorts of things, including scanning a project's available classes and generating fragments of code that be inserted at runtime.

For example, you can scan all the classes that implement Layout, and then generate a function that says:

if ( givenClass.equals( TableLayout.class )) return new TableLayout();

What's really great is you can push all this into the framework (in our case, Metawidget) so that it becomes 'magic' to the application code.

How does this work in practice? See for yourself! The Metawidget download includes a pre-built sample application, addressbook-gwt.war, that showcases a GwtMetawidget using pluggable bindings at runtime to generate the UI. It's covered in detail in the reference guide.

GWT and Metawidget Part 1: Reflection and Inspecting Annotations

The latest release of Metawidget adds supports for Google Web Toolkit (GWT) 1.5. This series of blogs explores the challenges that had to be overcome to acheive this.

Reflection and Inspecting Annotations

Whilst Metawidget does not require reflection and annotations (eg. you can just use XmlInspector), it's certainly a lot more powerful with them. By using reflection and inspecting the existing annotations on your business objects (you know, the JPA ones, the Hibernate Validator ones, etc.), Metawidget can automatically generate accurate UIs.

However, GWT is a very different kind of Web framework because it pre-compiles Java code to JavaScript. Java and JavaScript have similarities, but two areas they differ greatly is that JavaScript has no support for reflection or annotations.

But! Using GwtMetawidget, you can take your business object, reflect and inspect it, and generate your UI! How is this possible?

Well, GwtMetawidget showcases the power of Metawidget's separate Inspector/renderer architecture. Metawidget comes with a range of different inspectors targeting different aspects of back-end architectures (JPA annotations, Hibernate Validator annotations, JavaBean getters/setters etc). Each Inspector returns a piece of XML, and you can use CompositeInspector to compile them all together into one.

Because of this approach, inspection can be performed anywhere and the result passed somewhere else for rendering:

The process becomes:

  • instantiate the business object on the client-side as normal (ie. as JavaScript)
  • give your business object to GwtMetawidget (a client-side, JavaScript GWT Widget)
  • GwtMetawidget uses AJAX to pass the business object to the server
  • the server, using Java, runs all the Inspectors (including reflection and annotations)
  • the server returns the inspection results as an XML document
  • GwtMetawidget uses JavaScript to render the HTML widgets

How does this work in practice? See for yourself! The Metawidget download includes a pre-built sample application, addressbook-gwt.war, that showcases a GwtMetawidget using reflection and inspecting annotations at runtime to generate the UI. It's covered in detail in the reference guide.

Friday, May 30, 2008

GWT Dictionary and Unit Tests

Much like Firing onClickListeners in GWT Unit Tests, unit testing a GWT Dictionary is possible, but it is neither:
  • intuitive

  • documented anywhere at all (that I could find)

The problem is...

Dictionary.getDictionary( "bundle" );

...requires a JavaScript-level variable bundle to be declared on your 'host HTML page'. When the GWT application is running normally, the 'host HTML page' is the index.html page. However, when running unit tests, there is no host HTML page, so where to define that JavaScript-level variable?

The answer is in those tricky JSNI methods again. Just do...

public class MyTest extends GWTTestCase {

      public void testSomething() {
         prepareBundle();
         ...your tests here...
      }

      ...your other tests here...

      native void prepareBundle() {
      /*-{
         $wnd["bundle"] = {
            "dateOfBirth": "Date of Birth",
            "surname": "Surname"
         };
      }-*/;

...and use the special $wnd variable to initialize a JavaScript variable bundle prior to running your tests.

Hope that helps somebody. This is going to be in the upcoming release of Metawidget.

Friday, May 16, 2008

Firing onClickListeners in GWT Unit Tests

Firing event handlers, such as onClickListener, from GWT Unit Tests is possible, but it is neither:
  • intuitive
  • well documented
You can't just do...

myButton.click();

...because that clicks the button without firing any listeners. Instead, within your GWTTestCase-derived unit test, put a method like this:

private native void fireClickListeners( FocusWidget w )
/*-{
  w.@com.google.gwt.user.client.ui.FocusWidget::fireClickListeners()();
}-*/;

It looks funny I know. Make sure you:
  • include the native keyword, which the GWT compiler understands to mean JavaScript Native Interface (JSNI), rather than Java Native Interface (JNI)

  • include the starting and ending comment delimiters, because the code inside the function is actually JavaScript code, which
    means nothing to the Java compiler

You can then call this method just as you would a normal method:

fireClickListeners( myButton );

Hope that helps somebody. I'm using this in the upcoming release of Metawidget.