Search Logger
Posts from: Fred Sauer, Developer Advocate

Author Archive

GWT Advocacy

12:57 pm - January 16, 2009 in Google Web Toolkit Blog

I'm a huge fan of GWT and have been since its public release in 2006. I have spent a fair amount of my spare time working with GWT by participating in the user forum and contributors forum, submitting patches to the issue tracker and maintaining open source libraries for GWT, including ones providing support for Drag and Drop (gwt-dnd), Logging (gwt-log) and sound (gwt-voices). GWT has gone through a number of exciting releases, with 1.5 easily being the most impressive release yet. You probably know that the team is fiercely working on the upcoming 1.6 release. Andrew posted a month ago about the new features slated for 1.6. As usual, I'm not sure if I'm more excited about what's in the upcoming release or all the possible things we can do next!

I'm pleased to announce that I have joined the Developer Relations team at Google as a Developer Advocate for GWT. Some of you may be wondering what a Developer Advocate does. The role has two parts. We are advocates for you, the developer, which is to make your voice heard within the product and engineering teams at Google. We also advocate broader use of Google Developer Products and APIs. Both roles work hand in hand. By listening to developer's needs I will be advocating to improve GWT as a product. A better product in turn helps increase adoption thereby growing the GWT community.

I look forward to spreading the word and to helping make GWT even better.

 

Upcoming AJAX panel – JQuery, Dojo, YUI, GWT, and MooTools at the Googleplex

1:13 pm - February 13, 2009 in Google Web Toolkit Blog

Community meetups are a great way to meet new people with similar passions and interests as your own. It's also a great place for the community to exchange ideas. Often you get an interesting presentation to boot.

In fact, for those of you interested and within reasonable traveling distance, the Silicon Valley Web Builders and the Silicon Valley JavaScript Meetup Group have organized an exciting AJAX Panel next week on February 18th 2009. There will be representatives there from YUI, Dojo, MooTools, JQuery and of course GWT. There's a lot of interest, so be sure to sign up before the event fills up.

I've also been talking with the SV-GTUG (Silicon Valley - Google Technology User Group) organizers about doing a GWT presentation at an upcoming meeting. We don't have a firm date yet, but I'd like to start collecting your questions and suggestions for material you'd like to see covered. You can vote on other people's ideas or post your own questions here.

Finally, if you know about or organize a local user group that has developers interested in GWT, let me know. I'd like to hear about your group, and perhaps there's a way we can help make your meetings even more compelling.

 

Tell us about your GWT applications and prototypes

4:28 pm - March 27, 2009 in Google Web Toolkit Blog
A common question that is asked when developers and IT managers first consider Google-Web-Toolkit is: Who's using it? There are a number of places where you can find a partial answer such our own App Gallery or the Google Code blog. The community has started its own lists as well, such as those here, here and here.

While we encourage you to share directly with the GWT community in the user forum, we realize some of you may prefer to give feedback more privately, perhaps because your company policies require you to. If you have a story you would like to share, we would love to hear about it. Just send me an email.

I look forward to hearing about your GWT projects and experiences.
 

Widget Best Practices / Widget Building

7:48 pm - May 1, 2009 in Google Web Toolkit Blog
Developers often asked what's the best way to go about building custom widgets. There are of course a number of best practices to consider when answering this question. In this post I'll highlight a few I like to start off with.
  • Prefer composition to inheritance. Unnecessarily exposing implementation details is generally a bad idea, and it's no different when you are building custom widgets. In GWT terms, this means that your custom widgets should typically extend Composite.
// Here the HorizontalPanel implementation is exposed 
// Others may come to depend on the presence of one or more inherited methods public class OverExtendedWidget extends HorizontalPanel {
  public OverExtendedWidget() {
    //...
  }
}


// The use of HorizontalPanel is a hidden implementation detail
// We are free to change the implementation without affecting others public class ConservativeWidget extends Composite {


  private final HorizontalPanel panel;


  public ConservativeWidget() {
    panel = new HorizontalPanel();
    initWidget(panel);
    // ...
  }
}
  • Conservative API. Extending Composite also ensures that you do not inadvertently expose methods inherited from the parent classes into your new widget's API. Doing so can quickly lead to other classes depending on not only your class' implementation, but also the implementation of any parent classes. Remember, you can always add to your API. It's generally impossible to take anything away without introducing a breaking change.
public class LabeledTextBox extends Composite {


  // Be wary of multiple constructors as they can quickly get out of hand
  public LabeledTextBox(String labelText) {
    // ...
  }


  public LabeledTextBox(String labelText, boolean hideUserEnteredText) {
    // ...
  }


  public LabeledTextBox(String labelText, String textBoxText, boolean hideUserEnteredText) {
    // ...
  }


  // Only expose getters and setters if you have a use case for them
  public void setLabelText(String labelText) {
    // ...
  }
  public String getLabelText() {
    // ...
  }
}
  • Recycle and reuse. When your widgets repeat themselves try to avoid mirroring that repetition in your implementation. Often it is better to compose your new widget out of smaller, reusable widgets. This can both reduce widget complexity and allows improved testability. In a future post we'll explore widget design trade offs and lighter weight alternatives to widget composition to ensure the best possible user experience, which is GWT's ultimate mission (see GWT's mission statement for details).
public class LoginPanel extends Composite {


  private final VerticalPanel container;


  // We've decomposed the Label/TextBox pair into a separate LabeledTextBox widget class
  private final LabeledTextBox usernameTextBox;
  private final LabeledTextBox passwordTextBox;


  private final Button loginButton;


  public LoginPanel() {
    container = new VerticalPanel();
    initWidget(container);


    usernameTextBox = new LabeledTextBox("Username");
    container.add(usernameTextBox);


    passwordTextBox = new LabeledTextBox("Password", true);
    container.add(passwordTextBox);



    loginButton = new Button("Login");
    container.add(loginButton);
  }


  @Override
  protected void onLoad() {
    super.onLoad();
    usernameTextBox.setFocus(true);
  }
}
  • Design for real use cases. Instead of just imagining how your API might be used, you should write actual use cases that you want to support. You can start with a few lines of code which construct and use your new widget. Once you get the hang of it, you may want to consider test-driven development, a software development method whereby you write failing tests before you implement the features and functionality to make those same tests pass. While it may feel odd to write code that uses non-existent classes and/or interfaces and doesn't even compile, it can really help to flush out design problems early on. This should also help you with your 'Conservative API' efforts since the compiler will only complain about methods you actually try to use. As a bonus you can use your IDE to help you stub out your code. Eclipse, for example, provides many different kinds of Quick Fixes.

Eclipse Quick Fix offers to create a new Java class for you.



Eclipse Quick Fix can add missing methods or make other code changes for you.


  • Use Style. Your widgets should have a default look and feel. Your widgets should also allow for easy styling so that they will fit in with the rest of the page they live on. Providing CSS class names to key DOM elements in your widget is a good start. Setting a (primary) style name in the constructor is generally a good practice as well. This allows a designer to easily use different class names for different instances of your widgets on the same page. Browse the source for some of the out of the box GWT widgets to get an idea on how to do this.
public class RadioButton extends CheckBox {


  public RadioButton(String name) {
    // ...
    setStyleName("gwt-RadioButton"); 
  }


  // ...
}
  • Clean up after yourself. If you do extend Widget directly, use onLoad()/onUnload() rather than onAttach()/onDetach() to perform any DOM attachment setup or detachment cleanup. Any JavaScript references, such as event listeners, should be cleaned up in onUnload() to avoid memory leaks. Those same references should be setup in onLoad() rather than in the widget constructor. See for example the Checkbox source code. Recall that the widget life-cycle consists of three stages (1) construction, (2) attach to DOM, (3) detach from DOM. The most common life cycle for a widget is simply 12. Since GWT is all about building AJAX applications, many of your widgets will at least see a 123 life cycle. Widgets that move around the DOM as they are manipulated on the page will likely see a 123, 23, 23, ... life cycle. A common way to be tripped up by life cycles is when you, say, move your initialization code from widget construction to the onLoad() method without realizing that onLoad() is called each time your widget is (re)attached to the DOM.
  // This method is called when a widget is attached to the browser's document
  @Override
  protected void onLoad() {
    setEventListener(inputElem, this);
    // ... 
  } 


  // This method is called when a widget is detached from the browser's document 
  @Override   protected void onUnload() {
    // Clear out the inputElem's event listener (breaking the circular
    // reference between it and the widget); avoid memory leaks
    setEventListener(inputElem, null);
    // ...
  }

I hope you enjoyed reading a few high level best practices for widget design. In a follow-up post we'll continue to look at widget design through the eyes of the GWT compiler.

Finally, I hope you join us at Google I/O where we will have a number of sessions dedicated to GWT and plenty fellow developers to talk to, both on the conference room floor and in the developer sandbox.
 

Come hear about GWT at the Googleplex tomorrow night (June 16, 2009)

8:36 pm - June 15, 2009 in Google Web Toolkit Blog

For those of you in and around Silicon Valley, I'd like to invite you to see my Google Web Toolkit presentation titled "GWT Overview and Feature Preview" at the Silicon Valley Web Java User Group. I'll start with an overview of current GWT features and functionality. Towards the end I'll cover some of the features you can expect to see in GWT 2.0, many of which you can try out now if you don't mind creating your own builds. Of course there will be plenty of time for Q&A and some time to network with other developers in the community.

The meeting will be in the usual place on the Google campus. Please register here (http://www.meetup.com/sv-web-jug/calendar/10012641/). If you can't make this particular meeting, you can catch up on GWT when you have a moment by watching any of the Google I/O GWT session videos and slides you missed. If you live further away, you could always start a local Google Technology User Group.

Hope to see you there.
 

Introducing the Debug Panel for GWT

6:57 pm - July 15, 2009 in Google Web Toolkit Blog

The primary intent of the Debug Panel for the Google Web Toolkit (GWT) is to provide the developer of a GWT application performance data about the application as well as tools to debug the client side application code. Web applications built with GWT run mainly in the client's environment, over which the developer has little control or access. The Debug Panel provides tools to the developer to help lift the shroud over the client environment to help diagnose problems, help tune and improve performance as well as assist with application testing.

As with any application, testing and quality assurance is important to a GWT application. Because a GWT application is user facing, performance testing is very important. However, measuring the performance of an application running in a browser is not easy. With all the moving parts of the client code - RPCs, DOM updates, etc. - and the fact that with GWT you are no longer writing JavaScript, it can be hard to locate bottlenecks. Automating the performance tests and getting accurate numbers on RPC response time is even harder. This is where the Debug Panel for GWT comes into the picture. It is an external library that can easily be added to any GWT Web application and will provide you with that performance data, an insight into what goes on behind the scenes and help you automate the whole thing, too.

Here is a sample screenshot of the Debug Panel in action:



Here, the Debug Panel shows us the statistics of an invocation of the EchoService as well as the startup times. It is clear from the example that RPC finished quickly. It shows that the slowest component was waiting for the server to respond at 121ms. While serializing the request and deserializing the response both took 19ms, updating the UI with the data returned from the server only took 2ms. These are the kinds of numbers you would want to see!

Here is another example screenshot of the Debug Panel:



This time, the application was run in Hosted Mode and there was an exception during the RPC. Once you compile your application to JavaScript, the stack trace will be a JavaScript stack trace of course. The exception panel in the Debug Panel is also an example of the extensibility of the Debug Panel. As a GWT application developer, you can add your own panels to the Debug Panel that are customized to your application. The Debug Panel provides you with a framework to display your application's debug data as well as a lightweight component to add to your main application, so it can communicate the relevant data to the Debug Panel, without affecting runtime performance much.

In fact, you can plug the Debug Panel into an existing application without changing the application's code. This also means that there is no change required in the compiled JavaScript. Therefore, you can serve your GWT web application both with the Debug Panel enabled, to internal IP's for example, or disabled for everybody else.

Check out an online example of the Debug Panel, check out the example's source to see how easy it is to use or check out the Google Code project for more information.

Pascal Muetschard, Software Engineering Team


 

GWT for Enterprise Developers

12:48 am - August 13, 2009 in Google Web Toolkit Blog
Do you use GWT -or are thinking seriously about using it- to develop your internal or public facing web applications? Do you work in a corporate setting or otherwise collaborate with multiple developers on a single web app? If their answer is yes to either of these questions perhaps we can share.

I'd like to share with you
I will be giving a talk called Google Web Toolkit for the Enterprise Developers at JBoss World 2009 in Chicago, September 1-4. I hope to share practical tips and lesser known, yet really useful features in GWT. While the talk will focus primarily on corporate development scenarios, the content will most certainly be useful if you're the most valuable member of a one person team. I hope to see you there. Don't forget to bring your questions.


Will you share with us?
Not everyone develops the same. In fact the same people may adopt different development styles as they move between teams. Different tools also work differently depending on the team and the project. I'd like to get to know your teams a little bit better and understand how GWT development happens for you. If you're willing to share with me please send me an email.

 

Hydro4GE — a PaaS built with GWT

7:41 pm - September 2, 2009 in Google Web Toolkit Blog

Introduction

From time to time we like to share experiences from fellow developers with you. It's a pleasure to present you today with this guest blog post by Geoff Speicher, Chief System Architect of Hydro4GE.

Overview

Hydro4GE (pronounced hy-dro-forge) is a Platform-as-a-Service (PaaS) for building online database applications. Building a powerful tool for developers itself requires a powerful toolkit to meet developers' expectations of a development environment: a highly-interactive, rich user interface (UI) with emerging features such as database schema visualization via interactive, scalable graphics. This article describes our experience in using GWT to rewrite our old HTML+AJAX UI to deliver all of these features with a polished look and solid performance.

Building the UI

When we set out to rewrite the UI using GWT, a quick inventory of available widgets was in order. Our initial reaction was similar to what some others have expressed: that the native GWT widget library did not have quite the same breadth or flair as some third-party libraries such as ExtJS or SmartGWT. However, experimentation with these libraries proved that they are also fairly heavy in weight, and noticeably impacted the application's performance both in its initial download and its interactive responsiveness.
The reason is simple: these generic JavaScript libraries, though highly optimized, are still just that — generic. It is unrealistic for these libraries to achieve the same level of efficiency as code that is produced by the GWT compiler. For this reason, we wanted to avoid the use of external JavaScript libraries when possible.
After some careful consideration and a more detailed analysis of our needs, we discovered that we only needed a small handful of widgets that GWT didn't already provide, and all but one of those (covered in the next section) were easily built using Composite. There is already an excellent blog entry for building Composites, so we will not cover that topic here. The visual styling of both the native and Composite widgets was easy to customize thanks to GWT's liberal and logical use of CSS classnames.
As a quick demonstration, it's pretty impressive what a difference you can achieve by building a few simple Composite widgets and tweaking some of the default styles. Compare the default styling of an input form with one modified by a few simple customizations:

GWT Default Styles & Widgets
Customized for Hydro4GE
If you have not already jumped on the bandwagon, Firefox+Firebug is an indispensable tool for inspecting HTML and tweaking CSS. Thanks to this and the flexibility of the GWT library, we were able to achieve the polished look that we wanted without much work and without sacrificing performance.

Building a Widget from an External Library

What about the one widget that we couldn't build using Composite? We want to use vector graphics to generate scalable diagrams depicting database structure and user interaction for systems you build with Hydro4GE. There are a small handful of vector graphics libraries out there for GWT, but all of them require concessions that we are not willing or able to make. The Google Web Toolkit Incubator's GWTCanvas does not support text rendering (due to a limitation of HTML canvas), and although projects such as abstractcanvas attempt to overcome this limitation, text cannot be rotated and precisely scaled.
In this section, we will show you how to integrate with Raphael, a lightweight JavaScript library for cross-platform vector graphics. Raphael side-steps the HTML canvas issue by using SVG on supported platforms, and Microsoft VML on Internet Explorer. Raphael does everything we need to build our diagrams, except for one thing: integrate directly with our GWT code.
We achieved this integration through two levels of abstraction: (1) a JavaScript Overlay Type to provide a zero-overhead interface to the underlying JavaScript API, and (2) a GWT Widget to wrap the overlay with a more Java-friendly API, resulting in a first-class Widget that will operate side-by-side with native GWT Widgets. Let's have a look at the details for this two-part implementation, starting with the Overlay class.

The Overlay

The RaphaelJS class is nearly an exact replica of the underlying Raphael API. This is made necessary by the restrictions that GWT enforces on JavaScriptObject types, so the implementation is fairly uncreative: one method per Raphael method. Many of these methods appear in the nested class Shape, which represents the type returned by most of the native Raphael methods. The basic idea for the class is:
class RaphaelJS extends JavaScriptObject {
  protected static class Shape extends JavaScriptObject {
    public final native Shape rotate(double degree, boolean abs) /*-{
      return this.rotate(degree, abs);
    }-*/;
    public final native Shape scale(double sx, double sy) /*-{
      return this.scale(sx, sy);
    }-*/;
    public final native Shape translate(double dx, double dy) /*-{
      return this.translate(dx, dy);
    }-*/;
    // ...
  }

  /**
   * factory method
   */
  static public final native RaphaelJS create(Element e,
      int w, int h) /*-{
    return $wnd.Raphael(e, w, h);
  }-*/;

  public final native Element node() /*-{
    return this.node;
  }-*/;

  public final native Shape circle(double x, double y, double r) /*-{
    return this.circle(x,y,r);
  }-*/;

  public final native Shape rect(double x, double y,
      double w, double h) /*-{
    return this.rect(x, y, w, h);
  }-*/;

  // ...
}

The Widget

The Overlay bridges the gap between GWT and Javacript, but the Widget is what truly makes the library useful to our application. Since the Widget does not have the restrictions of the JavaScriptObject Overlay, we have the freedom to define our own API as an adaptor to the Overlay.
public class Raphael extends Widget {
  private RaphaelJS overlay;

  public class Shape extends Widget {
    protected RaphaelJS.Shape rs;
    protected Shape(RaphaelJS.Shape s) {
      setElement(s.node());
      rs = s;
    }
    public Shape rotate(double degree, boolean isAbsolute) {
      rs.rotate(degree, isAbsolute);
      return this;
    }
    public Shape scale(double sx, double sy) {
      rs.scale(sx, sy);
      return this;
    }
    public Shape translate(double dx, double dy) {
      rs.translate(dx, dy);
      return this;
    }
    // ...
  }

  public class Circle extends Shape {
    public Circle(double x, double y, double r) {
      super(overlay.circle(x, y, r));
    }
  }

  public class Rectangle extends Shape {
    public Rectangle(double x, double y, double w, double h) {
      super(overlay.rect(x, y, w, h));
    }
    public Rectangle(double x, double y, double w, double h, double r) {
      super(overlay.rect(x, y, w, h, r));
    }
  }

  public class Text extends Shape {
    public Text(double x, double y, String str) {
      super(overlay.text(x, y, str));
    }
  }

  // ...

  public Raphael(int width, int height) {
    Element raphaelDiv = DOM.createDiv();
    setElement(raphaelDiv); 
    overlay = RaphaelJS.create(raphaelDiv, width, height);
  }  
}
This implementation defines separate classes that represent the different types of objects (Circle, Text, Rectangle) developers can append to a drawing. A possible alternative implementation might simply expose the underlying JavaScript API as a native GWT widget — in the end, you can write an API that suits your needs.
We chose this implementation because it allows us to implement scalable drawings through inheritance, resulting in custom classes that can be instantiated and appended to any Panel. For example, to create a fullscreen drawing that contains a single, centered circle of radius 20:
public class MyDrawing extends Raphael {
  public MyDrawing(int width, int height) {
    super(width, height);
    Circle c = new Circle(width/2, height/2, 20);
    // Raphael automatically appends the Circle to this drawing
  }
}

public class MyApp implements EntryPoint {
  public void onModuleLoad() {
    MyDrawing d = new MyDrawing(Window.getClientWidth(),
        Window.getClientHeight());
    RootPanel.get().add(d);
  }
}
This is a trivial example, but it clearly demonstrates the simplicity that can be achieved by integrating an external JavaScript library as a Widget. To the consumers of this library, there is no difference between using it (a third-party Javascript library) and the native GWT widget library. That's a powerful statement, and a testament to the GWT design team.

Communicating with the server

With the UI visually complete, it was time to move on to integration with the backend. Our existing backend was implemented in PHP, and we did not want to rewrite it in Java just to support GWT-RPC. Without native support for GWT-RPC calls to a PHP backend, we needed a flexible and efficient communication framework to accomplish the equivalent task. We chose JSON for its simplicity and solid support in both GWT and PHP, but ultimately we learned that regardless of the efficiency of the encoding, it's still easy to make design mistakes that will lead to inefficient communications.
First, we need to get the client and server talking to each other. Making JSON-encoded client requests from GWT is made trivial by using the RequestBuilder class in conjunction with JSONObject, and handling JSON on the server with PHP is easily accomplished using Zend Framework, which provides the Zend_Json class for encoding/decoding JSON, and Zend_Controller for handling and routing requests. This provides the framework we need to tie into our PHP code running on the server.
Having addressed the encoding and handling of requests, our attention turned to dealing with the size and frequency of requests. The whole point of making AJAX requests was to transfer little bits of data instead of re-sending an entire HTML document, but we found a break-even point where the payload became so small that the request frequency was the limiting factor. At one point, we had gotten so carried away breaking up information into atomic pieces that the overhead of each request was exceeding 90% of the total time to complete the request, leaving less than 10% of the time to actually process and transfer the payload.
The reason this can happen is pretty straightforward. Over any network connection, there is a minimum amount of time necessary for the HTTP request/response to live its lifecycle. This is compounded by the two-connection browser limit plus overhead imposed by the network stack and connection latency. The net effect of all this is that if you dispatch one hundred requests in rapid succession, each of which contains only a few hundred bytes of payload data, it would take nearly one hundred times as long to complete all one hundred requests as it would take to transfer the entire payload (tens of kilobytes) in one request. In terms of real-world figures, this translates to a 300 or 400 millisecond time for completion, as opposed to 30 or 40 seconds!
This lesson reminds us that when you write software, you must always design for the limitations of the platform, even when you have great tools at your disposal. In this case, to write efficient web software with GWT, you need to make every HTTP request reach its fullest potential by maximizing its effects.
We achieved this by modeling each request as a collection of atomic commands. In this simple model, each command can return a set of data, and is associated with one or more response data handlers. The commands are processed on the server within a database transaction so that the entire request either succeeds or fails as a single unit without leaving the database in an inconsistent state.
This abstraction allows us to queue up many physical database operations into one logical JSON request, not only improving performance but also allowing us to handle the results in a modular way that involves less code than a typical GWT request callback. In this sense we have actually managed to reduce the complexity of the asynchronous HTTP request for this specialized case. For example, take the code that handles selection of user roles from the Hydro4GE database:
  public class SelectRoleHandler implements DatabaseRequest.Handler {
    public void handle(DatabaseRequest.Result result) {
      for (int row=0; row < result.getRowCount(); row++) {
        JSONObject data_row = result.getRowValues(row);
        Role r = new Role(data_row);
        // process role...
      }
    }
  }
Compare this to the code that you would typically write for an HTTP request callback:
  public class SelectRoleCallback implements RequestCallback {
    public void onError(Request request, Throwable exception) {
      Window.alert("Couldn't retrieve JSON");
    }

    public void onResponseReceived(Request request, Response response) {
      if (200 == response.getStatusCode()) {
        JSONArray data_set =
            JSONParser.parse(response.getText()).isArray();
        if (data_set != null) {
          for (int row=0; row < data_set.size(); row++) {
            JSONObject data_row = data_set.get(row).isObject();
            Role r = new Role(data_row);
            // process role...
          }
        }
      } else {
        Window.alert("Couldn't retrieve JSON ("
            + response.getStatusText() + ")");
      }
    }
  }
Besides being easier to understand (and half as many lines!), the Handler code has the advantage over the Callback in that multiple independent handlers can be attached to a single request in order to achieve separation of responsibility in handling each response. In addition, each handler is isolated from the results of other commands in the same request, so that there is no confusion over which results you are handling. This example does not even introduce the complexity of handling multiple command responses in the typical RequestCallback code, but the Handler code supports it implicitly by its nature.
These concepts can and should be applied to GWT-RPC or any other communications encoding. The implementation details are different, but the spirit is the same: make every HTTP request really count.

Conclusion

The techniques I have demonstrated here can be used equally effectively in both new and existing projects. Whether you are trying to build a slick UI, wrap an external library, or talk to a server, I have only scratched the surface of what is possible with GWT. I am especially looking forward to GWT 2.0 for continued improvements on some of the topics covered here, made possible by some exciting upcoming features such as UiBinder and CssResource.
In short, I am pretty excited about GWT and Hydro4GE, and I hope you are too. Be sure to check out the sneak peek of Hydro4GE to see a demo of our GWT UI in action!
Geoffrey C. Speicher, MS is a Software Engineer at Software Engineering Associates and the Chief System Architect of Hydro4GE.
 

Delivering faster, richer GWT applications to your users

10:25 pm - September 22, 2009 in Google Web Toolkit Blog
GWT has always been about providing a better experience for your users. Today GWT received a helping hand with the release of an early version of Google Chrome Frame, an open source plug-in that brings HTML5, a faster JavaScript engine and other open web technologies to Internet Explorer.

You're probably wondering how your users can take advantage of Google Chrome Frame. Simply add the following tag to the <head> section of your application's HTML page, just like you would for any other web application:
  <meta equiv="X-UA-Compatible" content="chrome=1">

As you probably know GWT automatically builds a different version of your application for each major browser. It uses a special selection script to launch the version which has been specifically optimized for the user's browser and personal settings.

Now you might be wondering how your existing apps will behave when your IE users with Google Chrome Frame installed visit your site. Will GWT try to launch the IE version or the WebKit version of your application?

GWT's selection script detects your browser's rendering engine so that it can launch a version of your app which is optimized for your browser. When the Google Chrome Frame plug-in is installed and the meta tag is present the WebKit rendering engine is used instead of the IE rendering engine. Since your app's existing selection script already recognizes WebKit based browsers it will know to launch a version of your app which has been optimized for Google Chrome Frame. If you don't include the meta tag or if your users don't have Google Chrome Frame installed the GWT selection script will still know to launch the IE version of your app.

In other words, your existing GWT apps are already setup to work with Google Chrome Frame. All you have to do is add the meta tag to your HTML pages.

If you like'd to encourage your IE users to install Google Chrome Frame or would simply like to learn more you can checkout the Google Chrome Frame developer docs.

 

Riding the Google Wave

8:45 pm - September 30, 2009 in Google Web Toolkit Blog

Today our colleagues down under began inviting the first 100,000 users to preview Google Wave. We are very proud of the work that they have done and are quite pleased that GWT has helped make Google Wave a reality. You can read more in yesterday's Google Wave Backstage - Q&A with Dhanji Prasanna at InfoQ.

In fact the Wave team has told us that they would have not been able to build the user interface you see today without GWT. That's a great testament to our mission statement which reflects our focus on developer productivity and user performance, delivering a great AJAX experience across all major browsers. Also, with only 10-15% additional effort GWT allowed the team to build a user interface dedicated for mobile devices browsers.

Of course there's still much to do before Google Wave rolls out for everyone. If you weren't one of the developers who participated in the developer preview or helped build one of the many samples perhaps there's an extension you would like to build. Check out the Google Wave API Documentation to find out how you can get started with GWT and Google Wave.

Congratulations to the Google Wave team on achieving this milestone and we look forward to continuing  to work together.
 
 
 
 
 
 
It's All About Search | © clsc.net |
2012.05.1821:48
Tech used here: Valid HTML - Valid CSS - Valid RSS - JavaScript - PHP - Smarty - MySQL - and a partridge in a pear tree.