Dr. Dobb's Journal - January 2008 - (Page 28) d01burn_p4ma 11/9/07 10:41 AM Page 28 Core Technology HANDS-ON GOOGLE WEB TOOLKIT When users type in a username and click the Next button, we need to retrieve the list of images and albums from the server. Flickr provides access to its data via an extensive web service API (www.flickr.com/services/ api). We created a proxy service to provide this data using GWT’s Remote Procedure Call (RPC) functionality (Figure 3). RPC services in GWT extend from the Java Servlet API, with built-in callbacks defined to make everything asynchronous. The objects returned are serializable POJOs Animation (Plain Old Java Objects), which we use to GWT does not currently provide a built-in store image and album metadata. animation or effects library (although develThe actual calls to Flickr are done in opers are working on one for an upcoming ImageService.java using Flickrj, an open-source release). Instead, you need to call out to a Java library that wraps Flickr’s REST-based API JavaScript library such as Script.aculo.us (flickrj.sourceforge.net). Listing Five shows the code to look up users, get a list of their photo sets, and transform the list into an array of lightweight Album data Figure 3: ImageService acts as a proxy between the client and Flickr. transfer objects. 28 Dr. Dobb’s Journal l www.ddj.com l January 2008 AlbumWidget is constructed using a number of simpler GWT-provided widgets, such as Button, Image, Label, RadioButton, and TextBox. These are all arranged on VerticalPanels and HorizontalPanels. (For documentation on these and more, see the references at the end of this article.) The advantage of using the widgets and panels provided by the toolkit is that they work the same way on all browsers. A prime example is the scrollable selector for choosing the photo in Figure 2. This would be difficult to implement in traditional HTML; but in GWT, it’s a simple Grid table contained within a ScrollPanel. That’s not to say all crossbrowser problems go away—we experienced a few quirks with Internet Explorer and Safari—but they are significantly fewer when compared to traditional Ajax development. ImageFlowWidget extends AbsolutePanel, which allows for absolute positioning and overlapping of widgets. Image widgets are placed in this panel and scaled to simulate perspective. The main image is always the largest and is positioned in the center of the window. Other pictures are stacked underneath and sized smaller and smaller the further they are from the center. When browsers display absolute positioned elements, they overlap elements that were added later on top of earlier ones. So we need to add images from the outside in (using AbsolutePanel.add()), with the main image last. Image positions, however, are calculated from the inside out to prevent smaller images from getting completely hidden. Listing Three presents the algorithm for handling this. Starting from the center image, it first calculates the size and position, recurses to the neighboring image, calls AbsolutePanel.add(), and finally returns to the caller. Figure 1: Users can select a photo service and username. Figure 2: List of albums is retrieved from the server and displayed in a scrollable grid. (script.aculo.us), YUI (developer.yahoo.com/ yui), or Rico (openrico.org). For GWTFlow, we chose the Effect class in the open-source GWT Widget Library. Using GWT’s JavaScript Native Interface (JSNI), it wraps the Script.aculo.us effects library, providing animation for moving, scaling, and fade effects. When users navigate to a new image, GWTFlow recalculates the new images and sizes, calls Effect.move() and Effect.scale() (provided by the GWT Widget Library), and lets Script.aculo.us work its magic. Listing Four presents the method called to animate the image movement. Getting Data From Flickr As in any Ajax application, client-side responsiveness is a primary concern. An RPC service lets us minimize the data sent across the wire and use the server’s processing power to retrieve image information. It also allows for a cleanly defined API that can be extended to support other image providers, such as Google’s Picasa Web Albums. However, RPC services typically require a servlet engine such as Tomcat or JBoss, adding complexity to deployment and limiting the number of hosting providers. One alternative we considered was JSON (JavaScript Object Notation), a data interchange format with support for native JavaScript web service requests. JSON data feeds are supported by a variety of providers, including Flickr and some Google services (although not Picasa). In the end, we decided against JSON, favoring RPC for performance, ease of debugging, and code maintainability. Fit and Polish Support for browser history has always been tricky in web applications, especially in the Ajax world (“please use my special previous arrow, not the big one you click everywhere else!”). Thankfully, GWT provides easy integration with browser history. As users navigate through their pictures, GWTFlow pushes entries onto the browser history stack. By implementing HistoryListener in the GWTFlow.java controller, the application receives notification of history events. This lets users navigate the application like a traditional website: Pushing the back button shows the previous image or dialog screen, not the previous website. http://Script.aculo.us http://developer.yahoo.com/yui http://developer.yahoo.com/yui http://openrico.org http://Script.aculo.us http://Script.aculo.us http://www.flickr.com/services/api http://www.flickr.com/services/api http://Script.aculo.us http://flickrj.sourceforge.net http://www.ddj.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.