Saturday, March 28, 2009
Introduction to GWT for Developers
Monday, December 29, 2008
One RIA Framework to Rule Them All
With Silverlight I really liked developing in Visual Studio, it was intuitive and fast. I also liked that fact that I could use XAML to markup the layout, then back it up with C# for the event handling.
Flex looks good too. I especially like the fact that you can mark up your presentation in an XML format (MXML), similar to XAML. I am not a fan of ActionScript though, but I will have to see how east the IDE makes editing the code when I get that far.
Then there is GWT. Well, I liked that so much that I wrote a book about it. I like the fact that I can used my editor of choice (Eclipse), code in Java, and it is open and free.
I once used Ext-JS on a large project, and although it looked great it was extremely painful. When I got done the code was completely unmaintainable.
I have also dealt with Scriptaculous, Prototype, DWR, and other tools over the years, but for smaller projects that probably can't be considered RIAs.
Then there is Wicket, Echo2, blah, blah, blah... so many to choose from!
So which is best? I am partial to GWT, mostly because I know it the best, and it is free and has a great community. On the other hand, I could get used to Silverlight (although the cost can be prohibitive).
If you have an opinion I would like to hear it.
Tuesday, April 22, 2008
GWT-Ext vs. Ext-GWT
For us GWT developers there is a project that wraps the Ext-JS library for GWT, namely GWT-EXT (GWT before Ext). The initial release was in July of 2007, and since then it encapsulates most of the functionality of Ext-JS.
Now just yesterday something happened that could undermine this project. The same team that developed Ext-JS has now released an initial beta of Ext-GWT (Ext before GWT).
This has got to be a blow to Sanjiv Jivan of the GWT-Ext project, who has undoubtedly given up a lot of his free time for the development of the library. But perhaps it does not have to mean an end for GWT-Ext. The first thing it has going for it is that there are already a lot of developers using it, who may not want to switch to an entirely different set of APIs just because it is the "official" version. Also, on taking a quick glance at Ext-GWT, I already see at least one feature that is missing, and that I can not do without.
For me, I am not sure where I stand. I think that for now I am going to stick with Sanjiv's GWT-Ext, at least until Ext-GWT comes out of beta. And then I will decide based on the stability of each, and which provides the features I need.
What do you think? Is an "official" Ext-GWT really what we needed?
Monday, December 31, 2007
GWT Widget Library Close to a 0.1.6 Release
New Canvas widget
George Georgovassilis added a Canvas widget to the library that uses VML on Internet Explorer and the canvas tag on Firefox, Opera, and Safari. After the launch of the initial implementation you can expect to see incremental enhancements down the road.
Calendar Widgets
The existing CalendarPanel has had some performance improvements including one that can cut the rendering time in half. In addition to this there is a new SimpleCalendar widget that builds on the CalendarPanel by providing controls for navigating. The SimpleCalendar is accompanied by several stylesheets to make it easy to use out of the box.
Depending on the timing you may also see the addition of an EventCalendar. The EventCalendar widget will display one or more calenders with a list of events below the calendars. A single set of controls will be provided to advance the series of calenders. So for example you may display three calendars to represent the quarter, then be able to navigate forward and back full quarters.
HTMLInclude Widget
You can think of the HTMLInclude widget as the core HTML widget with one small difference, you supply the URL of the content instead of in-lining the content in your application. The benefit is that your code is no longer cluttered with long strings of HTML content, and you can change the content without needing to recompile your application.
Beyond this there has been a reasonable amount of house cleaning and bug fixing, including providing an updated Maven 2 POM file to make it easy to download and compile the library from the source.
There is no schedule, but I hope to have this released no later than the end of January. If you interested in a sneak peak please feel free to download and build from the source, the trunk is always kept in a fairly stable condition.
Library Home Page
Subversion Repository
Friday, December 28, 2007
Presentation: GWT Tools Panel
You can find this presentation and others from the conference on YouTube.
Sunday, December 09, 2007
GWT Patterns: Simplifying Structure Through Events
I am a pretty avid Spring programmer and Spring has an application wide event system. It consists of three classes, ApplicationContext, ApplicationEvent, and ApplicationListener. The context is shared between all classes in the container, just like the application scope on a Java servlet. Using the context any class may register a listener, typically itself, to receive application events. Any class with access to the context may then create events and publish them to all listeners.
In Spring these events are published synchronously, meaning that the first listener needs to finish processing before the second listener gets to even see the event. This also means that the caller that published the event will block until all listeners have had a chance to handle the event. This model suits us fine for GWT since JavaScript is single-threaded anyway.
Time to look at some code, starting with the context.
import java.util.Vector;
public class ApplicationContext
{
private static Vector listeners = new Vector();
public static void addApplicationListener (ApplicationListener listener)
{
listeners.add(listener);
}
public static void removeApplicationListener (ApplicationListener listener)
{
listeners.remove(listener);
}
public static void publishEvent (ApplicationEvent event)
{
for (int i = 0; i < listeners.size(); i++) {
((ApplicationListener)listeners.get(i))
.onApplicationEvent(event);
}
}
}
In Spring the context would normally be injected into our classes, but as GWT lacks built-in support for dependency injection we simply make all of the methods static so that we can use it as a singleton. We have three methods; one to register a listener, one to unregister, and one to publish an event. Nothing fancy here, just the minimum required.
Next we need a listener interface and an abstract event base class.
public interface ApplicationListener
{
void onApplicationEvent (ApplicationEvent event);
}
public abstract class ApplicationEvent
{
}
I could have made the ApplicationEvent an interface, but my expectation that is at some point I may find it useful to add some helper methods in the future. Making it a n abstract class allows me to add functionality without altering the subclasses.
Now that we have all of the working parts it is time to start using it. In order to publish events we need to create classes that inherit the ApplicationEvent abstract class. In my case I decided to use fine-grained applications events, so I ended up with more than a few of them.
In the application I decided to have the entry-point class implement the listener interface, and registered it as a listener on start-up. In this application the entry-point class (acting as a controller) is the only the controller was listening to events published by various parts of the system.
Here are the two of the event class implementations used to create a new game or load an existing one.
public class CreateChessGameEvent extends ApplicationEvent
{
public CreateChessGameEvent () {
}
}
public class LoadChessGameEvent extends ApplicationEvent
{
private String gameId;
public LoadChessGameEvent (String gameId) {
this.gameId = gameId;
}
public String getGameId ()
{
return gameId;
}
}
Notice that the constructors of the specific events contain details that will be needed by the receiver of the events. Both of these events are triggered by clicking buttons in the user interface. Following is the code in the controller that receives the event and handles it based on the type of event.
public void onApplicationEvent (ApplicationEvent event)
{
if (event instanceof CreateChessGameEvent) {
service.createGame();
}
else if (event instanceof LoadChessGameEvent) {
service.loadGame(((LoadChessGameEvent)event).getGameId());
}
else if (...etc...) {
}
}
What isn't explicitly shown here is that service.createGame() and service.loadGame() both trigger asynchronous requests of the server. In the callbacks for each they simply send event notifications instead of handling the business logic themselves, which means the controller handles these events as well. The event used in the RPC callbacks is the ChessGameReceivedEvent, which includes the model for the specific game as part of it's properties.
So you might be thinking, why not just call the service methods directly from the button click handler and callback methods instead of sending an events back to a controller. If you are one of those people, consider this point. By using application events the user-interface and remote service calls have been completely decoupled from the controller and business logic. Decoupling is a good thing as it allows me to change the implementations of the service, user-interface, and controller independently.
Decoupling the view from the business logic results in cleaner code that is easier to maintain. In my case it simplified complex code, making it easy to refactor. For me it was a big win.
Saturday, December 08, 2007
Reminiscing the GWT Conference
Some of the more notable characters there were David Geary and Billy Hoffman. David is a veteran author, with his last book being one on GWT (of course I would still recommend GWT in Action!). It was great talking with David, and his presentation was really well done. His experience shows, and he knows how to entertain a crowd. Outside of his duties he was pretty easy to spot, he was the only one wearing shorts.
Billy Hoffman, a hacker, security researcher, and recently author, gave a talk on Ajax Security. He is extremely passionate about his work, and it really showed in his presentation. He covered a ton of material, and could have covered a ton more if given more time for his presentation. In talking with Billy, he had indicated that Ajax is very scary from a security standpoint. This is partially because the code examples that you find in developer documentation are riddled with security problems. His book was the only one I picked up during the conference, and although I just started reading it, it looks like it will provide me with a lot of useful knowledge.
Some of the others there were Bruce Johnson, Ryan Dewsbury, Rob Jellinghaus, Joel Webber, Scott Blum, and the list goes on and on and on. The best art is that none of them were there to push their books, promote Google, or push their products. Instead it was about furthering GWT, finding out how GWT has solved real world problems, and providing information to those new to GWT. Each night of the conference we would hold a free-form session to discuss ideas and talk about GWT.
In between sessions I was able to talk with a lot of interesting people and see some of their GWT work. And now that I have seen some of these real products using GWT I am completely blown away with what can be accomplished with GWT. For at least a couple of them, using GWT to build their project was their second or third try at getting it to work. It was both enlightening and encouraging.
So, without going on and on, let me say a few things. First, it was fantastic to finally meet in person those who I had only known over email. Second, it was great to meet all of you who had read my book or used the GWT-WL, and had nice things to say about it. I don't do this sort of stuff for money, so it was very encouraging and makes me want to do more. Third, we need to do it again soon! The conference was fantastic and we need to do this more often. And if you didn't make it to this one I hope to meet you at the next one.
Thursday, July 26, 2007
Some Thoughts on Commercial GWT Components
Is this a good business plan?
In my day-to-day work I do a lot of Java development, and sometimes I will be working with a commercial Java library for which the source is not provided. Often this causes delays in development because it makes it harder to work with the library. To combat this I simply installed a JAD (Java decompiler) plug-in into Eclipse, and now it only takes a single key stroke to see the source of the compiled classes.
From a customer service point of view it is frustrating to me, the customer, that I need to go out of my way to see the source. I own the product, so why can't I use it? Also note that not distributing the source didn't stop me from looking at it.
This is similar to what the record industry is doing. They want to add DRM to all of their music so that you can't "steal" it. In reality it gets stolen anyway, so all the DRM really does is stop the paying customers from using the music they bought in the manner that they want.
Personally, I feel that if you need to hide the source code from your customers, you are likely taking the wrong route. You will end up making your customers unhappy, and the code will be stolen anyway.
Is piracy good for business?
Did you know that in China it is a good thing to have your music pirated? If it is pirated, then it means that people like it, and the free marketing of piracy is what gets you to the top.
It has been said that Adobe Photoshop at one time wasn't the only product out there for professional image manipulation, but it was the easiest to pirate. I have heard it said that piracy is what made Photoshop the standard.
Microsoft Windows is perhaps the most pirated application that I know of. The part that is interesting about it is that it hasn't stopped them from becoming the most successful software company in the world. The question is, are they as successful because their operating system was pirated, or in spite of it?
The bottom line
In my opinion, if your business plan requires that you protect your intellectual property through the use of DRM or obfuscation, then I think that it is a bad plan.
If you take a look around you will find that many companies have become successful by purposely following a different route. Magnatune sells their music without DRM, and has the tagline "we are not evil". eMusic, also DRM free, it the second largest (I believe) music seller on the Internet. JBoss provides the source of their application server for free, and still makes money. OpenNMS, a monitoring tool, does the same. Add to this Interface 21 (think Spring), and many others.
The bottom line is that you should provide value to your customers, and don't inhibit their use of the product they bought.
I look forward to hearing any thoughts on this.
Monday, July 09, 2007
Appearing at OpenNMS Dev-Jam
It is nice to see adoption of GWT by such a well known application, and since OpenNMS is open-source, perhaps we will see some new open-source widgets released as well.
Friday, July 06, 2007
Hey Borders, GWT Isn't About Search!
I went right over to the shelf filled with books about web programming, perhaps my most visited shelf in the store, and began a visual search for the book. I didn't see it, so I scanned the adjacent shelves as well. I thought that perhaps they were out of stock.
I went over to the in-house computer to do a lookup for GWT in Action, and the computer said that it was on shelf A030, and likely to be in the store. I went back to the other Ajax books I saw, but couldn't understand why the computer said shelf A030 when the other Ajax books were on shelf F050.
I started following shelf numbers down the isle, and then I finally saw the book. They had positioned GWT in Action at the very beginning of the Computer books, a section that I rarely visit. The shelf was labeled "Web Search/Directories". They put the book somewhere between a book on search engine optimization, and "Google Hacks".
Ugh.
So if you happen to visit your local borders, be sure to check out GWT in Action, right next to your other favorite search related books.
Thursday, June 28, 2007
GWT (and me) Unveiled on The Server Side
GWT in Action: TheServerSide Tech Brief
The posting as drummed up some lively conversation. Perhaps the best quote in the comments so far is, "GWT style programming is for cowards". I am not sure how using GWT makes me a coward, perhaps not writing code directly in assembler makes me a coward as well. As the immortal Popeye once said, "I am what I am".
Wednesday, June 27, 2007
YeeeeHaaaa! See Y'all at the Java Ranch!
The Java Ranch forum is quite a bit different them the GWT developers forum. Most of the questions revolve around the discussion of what GWT can do, how it compares to similar technologies, and what are its shortcomings. It is a lot of fun, and is letting Adam and I us spread the word about GWT to Java developers that aren't using it yet.
Sunday, June 17, 2007
GWT announced as the new iPhone SDK
First, let me provide some background information. In case you missed it, Apple held its World Wide Developers Conference last week, and as usual Steve Jobs stood up on the big stage to deliver the keynote address. The keynote is the highlight of WWDC, and even if you weren't there you could find out what Steve was talking about by watching the many real-time blog posts covering the presentation.
As part of the keynote Steve announced the SDK for the iPhone, as was rumored, but what Steve announced isn't what the attendees expected. Steve announced that the SDK for the iPhone is the rich Internet application. That's right, the new SDK is the same SDK that Web 2.0 developers have been working with for the past few years, including GWT. This is made possible because the iPhone uses the full Safari browser.
As most developers I would expect, I was a befuddled by the announcement. Big deal I thought, but then it hit me. What Steve announced was not just about the iPhone, it was about all computing devices. You don't need to have an SDK for your mobile device anymore, all you need is a capable browser, and an Internet connection. As a web developer I find this exciting, and I see a very good future for our industry.
Of course Steve Jobs is not omniscient, but the fact that he announced the SDK in the way he did is a huge step in what I believe is the right direction. The only tools we need for this to become a reality is free wifi everywhere (or something similar), the actual hardware devices, the maturation of rich Internet applications, and a little imagination. As web developers we have held up our part of this, building web applications that can compete with traditional desktop applications, and the latest hardware is getting close to where we need it as well. All we need to do now is wait for everywhere wifi and then many of us will be able to leave the laptop at home in favor of a pocket browser.
In summary, GWT + iPhone = the future of mobile computing.
Thursday, June 07, 2007
GWT a Year Later
Recently I was speaking with Dietrich Kappe of Ajaxian, and commented that I thought that review of GWT was a little unfair, especially since it was posted only a few days after GWT was released. Dietrich in turn offered Adam Tacy an I an opportunity to answer some of the questions raised by the original article as review of GWT one year later after its launch.
GWT a Year Later: Was it the correct level of abstraction?
Thursday, May 24, 2007
Free Chapters from GWT in Action
Chapter 2, "Creating the default application", is a 30 page getting started guide. If you are new to GWT and having some difficulties getting started, this chapter will walk you through it. It covers the tools, the code they generate, and how to set to import the project into your IDE.
Chapter 10, "Communicating with GWT-RPC", is the first of four chapters in the book that cover browser-server communication. This chapter covers the GWT-RPC mechanism in detail, including prerequisite information about asynchronous communication and browser security restrictions.
Adam and I picked these two chapters because we thought that they would provide the most benefit to new developers trying out GWT without them needing to buy the book. Don't misunderstand, we really enjoy book sales, but we also like being able to give away something that is useful to others.
Hopefully more than a few of you will find these chapters useful.
Saturday, May 12, 2007
GWT in Action is #3 at JavaOne
So, to everyone who bought our book at JavaOne, Thank You! It was really great to see this sort of feedback.
If you weren't able attend JavaOne and wanted to pick up a copy, you won't need to wait much longer. From what we understand the book will start shipping at the end of this month, so it will be in stores soon.
Thanks again.
Saturday, April 28, 2007
GWT in Action: It's a baby book!

Check out my baby pictures! Isn't it the cutest book you ever saw?
If you are still reading, you might be asking yourself, “What is Rob’s point?” The point is that like having a baby (or so I am told), it was a lot of work to write this book, and now that it is done I feel both relieved and elated that it turned out to be something that I am proud of. And just like having a baby I want everyone to know.
Thanks to everyone who made the experience so great.…Now maybe I can get back to working on the GWT-WL!
P.S. - If you are going to JavaOne, look for GWT in Action on the shelves there. Manning is rush-printing a few copies that will be sold at the JavaOne book store. The general release of the book should be on target for early June.
Monday, March 26, 2007
A Sample GWT Application: The Dashboard
While Adam and I were writing GWT in Action, we generated a lot of mini-applications that were used as examples throughout the book. At some point it was decided that we wanted to tie all of the apps together, forming one large mega-app, that would add some continuity throughout the book. We call it the "Dashboard", and we hope it will be a useful concept to everyone that reads the book.Manning has been nice enough to allow us to host the sample application on their site, giving you a sort of interactive preview to what you can expect in the book.
Some of the Dashboard components include color picker, clock, Google search, video search, calculator, slideshow, server status, and others. Some concepts include JSON proxy to the Yahoo Search API, creating Flash-based components, populating menus from external XML, drag-and-drop, trapping image load errors, and others.
Some of the source for the Dashboard application has already trickled onto the GWT in Action book page and sometime soon the entire application will be available for download. We hope that you find both the sample application and source code useful.
Sunday, February 18, 2007
GWT-RPC: Customizing RPC in GWT
Who, What, and Why?
Before we get into the changes, I would like provide some history for this change so that we can better understand why this change is so important. Back on November 10th, George Georgovassilis posted bug report 389, which suggested changes for making the GWT-RPC mechanism easier to extend. If you aren't familiar with George's work, he is responsible for the GWTSpringController from the GWT-SL project, allowing a tight integration of GWT and Spring. The problem is that the current RemoteServiceServlet is nearly impossible to extend in a clean way, so George ended up needing to use CGLib, a code generation library that allows you to create classes at runtime. George's code does the trick, but it should be a lot easier to extend the RemoteService Servlet.
This bug report received very little attention until this post on the GWT Contributors list from Rob Jellinghaus.
Date: Fri, Jan 5 2007 10:23 pm
From: "Rob Jellinghaus"
Issue 389
http://code.google.com/p/google-web-toolkit/issues is listed as "low" priority, assigned to gwt.team.mmendez./detail?id=389
I am interested in working on this in order to facilitate a better GWT-to-JSF coupling. (Basically I want to be able to specify a JSF managed bean as the service endpoint for a GWT component via JSF, without needing to write a per-bean RemoteServiceServlet, or do CGLIB magic as in http://g.georgovassilis.googlepages.com/usingthegwtha . Just checked out the GWT source with an eye towards making a patch to support this.ndler
So my question is mainly for mmendez: is any active development underway on this that I am likely to collide with, or is this pretty much going to stay on the back burner for the next month or two? It'd be dispiriting to get it working only to find out someone else already got it into the latest release candidate :-)
Cheers!
Rob Jellinghaus
This got the ball rolling, and discussion ensued. Rob Jellinghaus did a bit more than just discuss the problem, he also coded the solution. So many thanks goes to Rob Jellinghaus for this patch that we should be seeing in the 1.4 release of GWT. So, not that we know the who, what, and why, lets take a look at the how.
RemoteServiceServlet - The OLD Way
As you already know, when your GWT code on the client calls the server, your custom servlet is executed, and your servlet extends the GWT RemoteServiceServlet. The execution starts with the doPost() method of the servlet being called, which in turn takes the serialized RPC request and passes it to processCall() for processing. The sequence diagram below shows the processing flow.
Inside of the processCall() method it does literally all of the work for handling the request. It passes the serialized request to the onBeforeRequestDeserialization(), allowing a subclass to perform some work on the serialized data prior to deserialization. It then checks that the target class implements the RemoteServiceInterface, deserializes the payload, invokes the RPC request, serializes the response, and finally calls onAfterResponseSerialized(). In short, the processCall() method does a LOT of work, allowing only a peek at the data before deserialization and after serialization of the response. It does not allow you to alter the process in any way unless you override and implement the entire processCall() method.
RemoteServiceServlet - The NEW Way
The changes to the RemoteServiceServlet in GWT 1.4 won't change the way you use GWT-RPC, but it does add a lot opportunities for customizing the handling of the RPC request. The sequence diagram below shows part of the picture. The two things that stand our are that the onBeforeRequestDeserialized() and onAfterResponseSerialized() methods are now outside of the processCall() method, and that there is now a new RPC class.
By moving the two "peek" methods out of processCall(), and moving all of the logic into a new RPC class simplifies the processCall() greatly. So great is this reduction that processCall() only consists of two lines of code! Below is the new processCallMethod().
public String processCall(String payload)
throws SerializationException {
RPCRequest rpcRequest = RPC.decodeRequest(payload, this.getClass());
return RPC.invoke(this, rpcRequest.getMethod(), rpcRequest.getParameters());
}
There are a few key points about this new mechanism.
1. All of the logic has been moved into public static methods of the RPC class. This makes it possible to write your own service that doesn't use the RemoteServiceServlet at all.
2. None of the methods in RPC access the HttpServletRequest or HttpServletResponse object. Besides simplifying testing, you could in theory write a service that doesn't even use a servlet container. In theory you could write a service that works over email, FTP, telnet, or pretty much anything. Any volunteers to be the first to try sending GWT-RPC messages over email?
3. The processCall() method is only two lines of code. This allows you to override the processCall() method without the hacking that was required previously.
Now lets take a closer look at the methods in the RPC class.
The New RPC Class
There are only a few public methods in the new RPC class, so we might as well look at them all.
public static RPCRequest decodeRequest(String payload, Class service)
You saw this method above in the processCall() method. You pass in the serialized RPC request, and the class that will accept the call. As a security precaution, the method will check that the service class implements the expected service interface as well as the RemoteService interface. The method then deserializes the request and returns a RPCRequest object. The RPCRequest class is new, and contains a Method object and and Object array of parameters. The Method class is part of Java's reflection API, and this object can be used to invoke the method.
public static RPCRequest decodeRequest(String payload)
This is the same as the first version of decodeRequest(), except that it will skip the check to see if the target service class implements the proper interface. Internally, calling this method is the same as calling decodeRequest(payload, null).
public static String invoke(Object target, Method serviceMethod, Object[] parameters)
The invoke method executes the method and returned a serialized response. The target is the object that the method will be called on. In the default processCall() method, that we saw in the code snippet above, the "this" object is passed, meaning that the servlet itself must implement the method. But because you can pass the object to the invoke method you could delegate the RPC call to some other class. This could be useful in frameworks like Spring, where you want to use dependency injection to allow for swapping out implementations. The serviceMethod parameter is the Method object that will be called, and parameters is an array of Objects that will be passed to the method.
public static String encodeSuccess(Method serviceMethod, Object returnValue)
The encodeSuccess() method is used internally by the invoke() method that we just discussed. Simply put, it takes the Method object that was invoked, and the Object result of the invocation, and serializes the result. Because this method is broken out of the invoke() method it allows you to replace the invoke() method with your own, and still be able to use the encoding facilities.
public static String encodeFailure(Method serviceMethod, Throwable cause)
Again, the envodeFailure() method is used by invoke() above, but if you need to write your own invoke() method you can still use this method to serialize an error.
The Sum of the Changes
As you can see, the changes are completely backwards compatible, yet allow for ease of extension. You can customize the handling of the processing of requests by overriding the processCall() method to add code to alter the serialized response before processing, modifying the serialized response before it goes back to the client, alter the way the method is invoked, and even delegate execution to some other class. I look forward to seeing further GWT integration on the back-end with Spring, JSF, EJB, and everything in between.
GWT ClippedImage - Optimizing Image Loading
What is ClippedImage, and what is it for?
ClippedImage allows you to show just a part of an image instead of the whole image, by hiding or "clipping", the rest. The ultimate purpose of this new image type is for optimizing the load time of your GWT appliciation. Curious as to why? Then read on...
First some background information...
We use images in web pages for icons, logos, art, photos, and to make the user-interface look beautiful. There is no escaping it, we like to use lots of images! As you might guess, the flip side of the coin is that lots of images means longer download times, but perhaps not for the reason you think. Of course the larger the image the longer the download time, but what about the overhead of the HTTP protocol? Due to the way browsers and HTTP works, there is a bit of overhead for each image downloaded, and although it is rather small, it can quickly add up if you have a lot of images.
As an example may I present a sample icon bar. The bar includes a set of 14 icons (12 shown in the image), each 22 pixels by 22 pixels, with the total size of all of the images a mere 15 kB.
To see how well the browser performs when loading these images I created a simple HTML page that included 14 image tags, one for each icon. I then put the images and the test HTML page on a web site and viewed it in the browser. I use the FireBug plug-in (a must have!) for Firefox, and it shows me that the total time to download the page and all of the images is a mere 610 milliseconds. In FireBug you can get a clue as to what is going on, the images don't all download at the same time, and as we will see, this is by design.
In section 8.1.4 of the HTTP 1.1 specification it states,
"Clients that use persistent connections SHOULD limit the number of simultaneous connections that they maintain to a given server. A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy."I think that this makes it clear why we see really much longer times for some of the images on the page even though they are roughly the same size. So if the problem is the connection limit that HTTP specifies, what is the solution? Considering this article is about the new ClippedImage class, I will bet you know what comes next. The solution is to reduce the number of external images that we need to load by combining all of out icon files into a single file.
In order to test this I created a single PNG image that contained all of the 14 icons, and reran the test. Below is the FireBug output for the single image, which is the same size as the 14 icons combined.
The results are pretty amazing, with a page load time of roughly 38% of the of the original. In our example the difference is less than 400 milliseconds, but if we needed to load more icons this could easily add several seconds to the time it takes for the page to load, which can be significant depending on the application.
Now that we have some background information, lets get on to using ClippedImage to increase load time.
Using ClippedImage
Using clipped image is very simple. You simply specify the X/Y coordinates of the top-left pixel of the part of the image where you want the clipping to occur, followed by the width and height of the image. The following code snipped shows the creation of four clipped images.
ClippedImage unlkIcon = new ClippedImage("icons.png", 0, 0, 22, 22);
ClippedImage timeIcon = new ClippedImage("icons.png", 22, 0, 22, 22);
ClippedImage warnIcon = new ClippedImage("icons.png", 44, 0, 22, 22);
ClippedImage recyIcon = new ClippedImage("icons.png", 66, 0, 22, 22);
In the code snippet we highlighted, we create a warning icon. The diagram below shows where the coordinate measurements come from. The top corner of the icon is 44 pixels from the left edge, and zero pixels from the top. The next two arguments are the width and height, both are 22 pixels.
Oh, and you might have noticed that we used a PNG in the example. It is a known issue that Internet Explorer 6 doesn't support the PNG alpha channel without having to jump though some hoops. The PNGImage class from the GWT Widget Library jumps through these hoops, and it is rumored that the new ClippedImage class will also support this.
In order to add ClippedImage into the GWT API there were some other modifications made. If you think about it, now that there is the old Image class, and the new ClippedImage class, it only made sense to add a parent class to hold shared functionality. This new class is called AbstractImage, and you guessed it, it is abstract. This super class includes mouse event handling, simplifying any subclasses a little.
Automatic bundling of images
Along with ClippedImage is the new ImageBundle. I won't cover ImageBundle, but if you want to read up on it, there is a ImageBundle design document. The ImageBundle is similar to the GWT internationalization support, except that it is for images. The idea is that you create an extention of the ImageBundle interface, with one method specified for each image, and each image being its own separate file. When you compile the GWT code the GWT complier will automatically grab all of the individual images and combine them into a single image. In the GWT code you then use the methods of the interface to get the image objects. The whole purpose is to make image clipping easy to do.
I hope you enjoyed this article. I am not sure what I might write about next as there are a lot of cool new things in GWT 1.4. The complete list of new features can be found in the GWT 1.4 Development Plan.
Attribution: The icons used in the sample images are from the Tango Icon Library.