Posted in gwt, Information Technology, javascript

Why is GWT still relevant?

Introduction

Google Web Toolkit (GWT) is an AJAX toolkit that allows development of AJAX based web application wit the use of Java Programming.

Advantages

1. Most coding problems are caught during compile time.

2. Runs on all platforms

3. Runs on all browsers

4. When created Java code is compiled, specific AJAX code is generated for every browser (Write one set of code that can run on all browsers).

5. GWT includes a lot of pre-built components.

6. GWT is Object Oriented because it is based from Java which converts it to JS(JavaScript)

7. IDEs like Eclipse makes coding with Java easier by allowing quick coding, shortcuts, code generation, and code analysis.

8. The compiler removes dead code and minifies it. The code is split into separate JavaScript files that helps the application load gradually as you visit new screens.

9. Manages static resources. CSS and images in code requires explicit declaration in the Java code.

10. Have an inbuilt structure for server-side component.

GWT started off well as a framework that converts Java into JavaScript, but it did not stay like that for long. One of the big developers had with GWT was the initiate learning curve specially for people that did not use Java language before. It took people months to learn GWT properly and see and effective return on time investment, and even with months of learning it did not seem like it was worth their time to learn more about GWT.

Disadvantages

1. Requires Browser plugin for development. The browser is not being maintained to work with newer browsers. This made it difficult for developers to adopt this framework.

2. Every time you change coding from the client side you are required to recompile. This made developing with GWT slower compared to other frameworks. Developers are used to just quickly refreshing the browser to see the changes.

3. The UI for GWT was initially good but as time passed GWT did not improve, rather they stayed stagnant on the UI development side. This made it difficult to choose GWT over other frameworks.

4. The last update for GWT was October 19, 2017. This means that the developers of this framework have stopped trying to improve this framework (basically abandoned it).

The world was also moving towards cloud-based web applications. Google tried to bring back GWT to life by putting in enough resources to trying and evolve the GWT framework.

Evolution

1. In 2012 2.5.0 was released which laid the foundation for the SuperDev mode. SuperDev mode works better for the modern browsers which makes compiling and seeing the results faster.

2. History management — which allows the user to navigate in the application using the browser’s back and forward buttons.

3. Made the SuperDev mode the default for application building.

Challenges for teams initially

1. There is no standardization of framework — This can lead to confusing for the team on which one to choose.

2. If you want to improve the look and feel of the website/s the team creates you have to either create your own CSS or use CSS frameworks instead of using GWT’s UI design since it looks old and outdated.

3. Since there are only a few people and companies using GWT now most developers/companies will choose to use other frameworks.

Screenshot from: https://trends.builtwith.com/framework/Google-Web-Toolkit [1]

Conclusion

There are currently 43.360 websites using Google Web Toolkit (GWT)[1]. GWT was a good framework that converts Java into JavaScript but it had problems with keeping up with other frameworks that kept on evolving to what the developer needs and wants. Since after Google stopped developing GWT themselves the framework’s improvement have slowed down and that is when GWT started its decline in popularity. Most websites that are currently using GWT technology seem to be older websites because most developers will opt-out of using GWT as a framework because there are other frameworks that are better maintained and have kept up with the changes. It is best for developers to learn other frameworks than to learn GWT.

References

[1] “Google Web Toolkit Usage Statistics”, BuiltWith® Pty Ltd, https://trends.builtwith.com/framework/Google-Web-Toolkit

Accessed: 3/30/2019

[2] “Super Dev Mode” GWTProject.org, http://www.gwtproject.org/articles/superdevmode.html

Accessed: 3/30/2019

[3] “Overview” GWTProject.org, http://www.gwtproject.org/overview.html

Accessed: 3/30/2019

[4] “GWT is coming back … in 2015”, Blog.Xam.de, https://blog.xam.de/2014/02/gwt-is-coming-back-in-2015.html

Posted in gwt, Information Technology

GWT or Angular 2

The best answer to this could be, if you’re more into Java then choose GWT if you’re more into Javascript then choose Angular 2 (or whatever Angular version).

Choosing framework and tools mainly is based on which framework can help you bring a project to life (and for the most part, the fastest possible time)

We have Angular based apps that we’ve migrated to GWT, since when we build apps with Angular we were experimenting, and although it worked we are not able to to maintain it in the long run—so this is answers again the question for “when”, in our case GWT will be always better fit than Angular 2, but that will be different for other developers or teams.

Anyway, framework-wise, GWT is really a efficient compiler and framework that most of the time can allow you to build apps with fewer head count.

GWT is Java-based, so by nature it is Type-safe, it is a compile so your output is not only obfuscated but also optimized, runs faster than hand-written Javascript codes. If you pair GWT with complementary frameworks like Errai, you can build HTML-based templated web or mobile application using existing HTML, CSS UI. Errai also brings a “used to be server side technology” to the browser, namely CDI, like Observers which will allow you to build “reactive” applications.

GWT is a solid framework with solid support from many developers, join here to learn more: gwtproject/gwt

Posted in gwt, Information Technology

GWT Advantages / Disadvantages

 

Advantages

  1. Java is strongly typed and hence most coding problems get caught during compile time itself.
  2. Powerful IDEs like Eclipse are popular for Java and allow very quick coding, shortcuts, refactoring, and code analysis.
  3. Optimized JavaScript. The compiler inlines the methods, removes dead code, and minifies it. Further, the code is split into separate JavaScript files, and hence the application can load gradually as you visit new screens.
  4. Management of static resources. Referring static resources such as CSS and images in code requires explicit declaration in the Java code. It allows for a clean separation and also allows to easily locate the resource usage. Eclipse users, think using Ctrl+Shift+G to determine where all is an image referred in code!
  5. Has an inbuilt structure for server side component as well. That too comes with a super-optimized serialization for object transmission. Coders do not need to work on JSON – server and client talk classes and objects. And it still allows putting in your own serialization strategy, your own server-side components.

Now, all that is good… and GWT looked set to take hold in all development teams. Yes, it did start that way. Techies were excited to see that it could take the pain out of working on web development.

However, this hype did not last, and we, like many other teams, became apprehensive about going ahead with GWT.

The Bottlenecks

  1. Browser plugin required for development. The browser plugin was not being maintained to work with newer browser versions. This discouraged its adoption.
  2. Every change in the client side code required a recompilation. Coders were used to the speedy change-refresh-check method. Compilation slowed things down.
  3. UI look and feel. Though the initial version was great for its time, the look and feel did not move with time.
  4. Evolution of the toolkit itself slowed down. If you see the release versions:
    1. From launch in May-2006 to Aug-2008, significant improvements were brought about.
    2. Then after a year, in Aug 2009 we saw code splitting and deprecation of the plugin.
    3. Then there was a series of fixes-only releases till 2012.

So, during the time when the world was moving to cloud-based web applications, GWT was in slumber… or so it seemed. Numerous other web frameworks came and conquered the huge developer base now doing web applications. GWT missed this bus. Resultant “market share” of GWT slid hopelessly low.

However, Google turned it around later. It put in enough resources to bring GWT back to life.

Evolution

The relatively recent developments brought the trust back.

  1. Real-world applications using GWT like Google Inbox
  2. A major release in 2.5.0 in 2012. This laid the foundation of SuperDev mode – a giant leap for web development. We believe this is going to be the way to go for all web-app frameworks. Also, subsequently we have seen important releases in 2.5.1, 2.6.0, and then 2.7.0
  3. Frameworks like GWT MVP and GWTP standardized the application structure
  4. UI look and feel with gwt bootstrap3
  5. History management—allowing the user to navigate in the application using browser back and forward buttons
  6. Incremental compilation – re-compilation only compiles what has changed
  7. SuperDev by default – refresh now serves the new application. Though this is not as fast as others, the overall speed of development in Java makes it very fast
  8. Declarative UI in XML with UiBbinder

Statistics Say It

Some statistics from the Future of GWT survey 2015

  • Developers who use GWT rate it at a good 4.47 out of 5, with 82% rating it above 4.0.
  • 78% have been using GWT for more than 2 years. So it’s a framework that has actually stood the test of time.
  • 33% said that their GWT teams have grown.
  • 56% of these applications have more than 20 screens. It supports the fact that GWT is for large maintainable business applications on which users spend several hours in a day.
  • 85% would want to use GWT in their next project.
  • 43% and 35% respectively also considered using AngularJS and jQuery.

Challenges That a Team Might Face Initially

  1. Framework standardization – GWT MVP or GWTP or your own. When you are spoilt for choices and there is no clear answer, then the team is left confused. Our take is to go with GWTP.
  2. Widgets – Since bootstrap3 is not supported out-of-the-box, a project called gwtbootstrap3 does it. Now this support may not be complete and you may miss some widgets. Also, some other native JS+bootstrap widgets will not be directly available. However, GWT allows native JS as well. Or you might need to port some widgets to GWT.
  3. Current hands-on experience and biases of team will probably lean toward other frameworks.
  4. Designer shall need to understand at least UiBinder. Or you can have the coders do the UI once the hi-fidelity wireframes are done by the UX/UI team.

Further Reading

Posted in gwt, Software Engineering

7 Tips for Exception Handling in GWT | Summa Blog – Mozilla Firefox

7 Tips for Exception Handling in GWT | Summa Blog – Mozilla Firefox.

Exception handling best practices in Java are pretty straight-forward by now, and for the most part this carries over into the world of GWT (since GWT is, from the end developer’s perspective, just Java!). There are, however, a few tricks and gotchas that are important to be aware of. In this blog post I’ll describe a few that I’ve encountered, but please feel free to share your own.

Starting with the client tier and working my way to the server, here we go…

1. Handle all uncaught client-side exceptions

The first thing and simplest thing to do is to ensure that all unhandled exceptions bubbling out of the client tier are caught. You can accomplish this by registering an UncaughtExceptionHandler, like this:

  1. public class Example implements EntryPoint {  
  2.   public void onModuleLoad() {  
  3.     GWT.setUncaughtExceptionHandler(new   
  4.       GWT.UncaughtExceptionHandler() {  
  5.       public void onUncaughtException(Throwable e) {  
  6.         // do exception handling stuf  
  7.     }  
  8.     // do module loading stuff  
  9.   }    

Pretty straight-forward. What happens if you don’t set the UncaughtExceptionHandler in your application? Well, in hosted mode, the default handler will conveniently log the exception and stack trace to the console. In web mode, however, the handler is null, and so exceptions “escape” to your browser, which is likely not the user experience you’re looking for (though it does provide the opportunity to use a Javascript debugger for further diagnosis).

Also, be aware that your custom UncaughtExceptionHandler only takes effect the onModuleLoad() returns. In other words, if there was an exception raised where the comment “do module loading stuff” is in the example above, this exception would be handled using your custom UncaughtExceptionHandler that you just defined. This is a known issue, and will not be resolved. As a work-around, if you expect exceptions could be thrown within onModuleLoads(), then you can extract the guts of onModuleLoad() to another method, and invoke it using a DeferredCommand:

  1. public class Example implements EntryPoint {  
  2.   public void onModuleLoad() {  
  3.     GWT.setUncaughtExceptionHandler(new   
  4.       GWT.UncaughtExceptionHandler() {  
  5.       public void onUncaughtException(Throwable e) {  
  6.         // do exception handling stuff  
  7.       }  
  8.     });  
  9.     DeferredCommand.addCommand(new Command() {  
  10.       public void execute() {  
  11.         onModuleLoad2();  
  12.       }  
  13.     });  
  14.   }  
  15.   
  16.   private void onModuleLoad2() {  
  17.     // do module loading stuff  
  18.   }  
  19. }  

2. Unravel GWT’s UmbrellaException

Once your UncaughtExceptionHandler is set, you may notice that some of the exceptions caught are instances of GWT’s UmbrellaException, rather than the actual exception thrown within your code. GWT uses UmbrellaExceptions to wrap exceptions in certain cases (loops, etc.), and it nests the root exception within it. For the purpose of easier debugging and more accurate error handling, it’s often helpful to unwrap these exceptions, like this:

  1. GWT.setUncaughtExceptionHandler(new   
  2.   GWT.UncaughtExceptionHandler() {  
  3.   public void onUncaughtException(Throwable e) {  
  4.     Throwable unwrapped = unwrap(e);  
  5.     // do exception handling stuff  
  6.   }    
  7.     
  8.   public Throwable unwrap(Throwable e) {   
  9.     if(e instanceof UmbrellaException) {   
  10.       UmbrellaException ue = (UmbrellaException) e;  
  11.       if(ue.getCauses().size() == 1) {   
  12.         return unwrap(ue.getCauses().iterator().next());  
  13.       }  
  14.     }  
  15.     return e;  
  16.   }  
  17. }  

3. Log exceptions on the client

Now that you have a handler catching your rogue client side exceptions and also a handy method to unravel them to their root causes, you’ll want to actually useful with these exceptions to help developers more easily diagnose and resolve the underlying problems. While the appropriate action may differ per application (e.g. present an error dialog, email the support team, etc.), at the very least the exception should be logged. Fortunately, GWT delivers a simple but powerful solution for client-side logging, piggy-backing off of the standard java.util.logging package. Plugging a logger into the UncaughtExceptionHandler is easily accomplished:

  1. public class Example implements EntryPoint {  
  2.   
  3.   private Logger logger = Logger.getLogger(“”);  
  4.   
  5.   public void onModuleLoad() {  
  6.    GWT.setUncaughtExceptionHandler(new   
  7.      GWT.UncaughtExceptionHandler() {  
  8.      public void onUncaughtException(Throwable e) {  
  9.         logger.log(Level.ERROR, “Ex caught!”, e);  
  10.     }  
  11.     // do module loading stuff  
  12.   }    
  13. }  

Leveraging a helpful set of handlers that GWT provides, loggers can write to a number of different channels: development mode window, console, in-window pop-up, Firebug, and, the coup-de-gras, to the server(which I’ll cover in a bit). These channels are easily configurable via your .gwt.xml file:

  1. <inherits name=”com.google.gwt.logging.Logging” />  
  2. <set-property name=”gwt.logging.logLevel”   
  3.   value=”INFO” />            
  4. <set-property name=”gwt.logging.enabled”   
  5.   value=”TRUE” />   
  6. <set-property name=”gwt.logging.developmentModeHandler”   
  7.   value=”ENABLED” />    
  8. <set-property name=”gwt.logging.systemHandler”   
  9.   value=”DISABLED” />  
  10. <set-property name=”gwt.logging.popupHandler”   
  11.   value=”DISABLED” />  
  12. <set-property name=”gwt.logging.consoleHandler”   
  13.   value=”ENABLED”/>   
  14. <set-property name=”gwt.logging.firebugHandler”   
  15.   value=”ENABLED” />  

Logging in GWT is very well documented, so there’s no need to retread here.

4. Log exceptions on the server

The majority of the logging handlers write to the client side, however in a production environment this often isn’t much help to you. When your users stumble upon an error, it’s unlikely (and actually unsafe from a security perspective!) to expect them to look in client-side log files to help you diagnose the problem. Instead, your application should do this work for you, by logging all unexpected exceptions to the server. Fortunately, remote logging of this sort is as simple as enabling it in the .gwt.xml config file:

  1. <set-property name=”gwt.logging.simpleRemoteHandler”   
  2.     value=”ENABLED” />    

…and then defining the remote logging servlet in your web.xml file:

  1. <servlet>  
  2.   <servlet-name>remoteLogging</servlet-name>  
  3.   <servlet-class>com.google.gwt.logging.server.RemoteLoggingServiceImpl</servlet-class>  
  4. </servlet>  
  5. <servlet-mapping>  
  6.   <servlet-name>remoteLogging</servlet-name>  
  7.   <url-pattern>/your-gwt-module-name/remote_logging</url-pattern>  
  8. </servlet-mapping>  

Now, with one simple call to the log() method in your UncaughtExceptionHandler, the exception is sent automatically to your server log. Note, however, that by default it’s assumed that you’re using java.util.logging, which may not necessarily be the case. To hook these logs into, say, Log4J, check out SL4J.

Finally, it’s possible that instead of using GWT’s remote logging, you may want to implement a simple custom RPC to log (and possibly do other things – e.g. send email, etc.) when an unexpected exception is encountered. For example:

  1. GWT.setUncaughtExceptionHandler(new   
  2.   GWT.UncaughtExceptionHandler() {  
  3.   public void onUncaughtException(Throwable e) {  
  4.     myService.handleException(e);  
  5.   }  
  6. }  

Seems straight-forward, right? Be careful! First, not all exceptions are serializable or follow the rules of serializable (ugh!). For example, GWT’s JavascriptException inherits Serializable, but doesn’t implement a public no-arg constructor, so when you try to send this over the wire via your RPC, a run-time Serialization exception is thrown. And since this exception would be thrown inside your exception handler, it would effectively swallowed. Second, the stack trace within an exception is transient, and so is lost from client to server (so if you need it on the server side, send it as a separate parameter). Which leads me to the next tip…

5. Consider logging exception stack traces

Of course knowing that an exception occurred isn’t usually helpful unless you know exactly where it was thrown from! On the server side we take this for granted, since stack traces are typically logged by default with our exceptions. On the client side with GWT side, however, it’s not so easy. When Java code gets compiled into Javascript, it is both shrunk and obfuscated. This is obviously useful for performance and security, but from the perspective of supporting applications, it makes things much trickier. For example, instead of seeing a stack trace with method/class names and line numbers, you might get something like this:

 Unknown.Jq(Unknown Source) 
 Unknown.Tm(Unknown Source) 
 Unknown.Sm(Unknown Source)

Not too helpful! Fortunately, there are different options for how GWT compiles into Javascript which provide different amounts of information for debugging. Of course nothing in life is free; the trade-offs are security and performance. If you wanted nice clean Javascript that resembles your Java code and that produces nice clean stack traces, then you can flip the GWT compiler “style” flag to either “pretty” or “detailed”, however this would obviously increase the size the Javascript (and thus take longer to download)…and any user could more easily grock your client side code. There’s a nice compromise though, which is to provide file names and/or line numbers in your stack traces, but to keep the source code obfuscated. This can be configured in your .gwt.xml file:

  1. <set-property name=”compiler.stackMode”   
  2.      value=”emulated” />  
  3. <set-configuration-property name=”compiler.emulatedStack.recordLineNumbers”   
  4.      value=”true”/>   
  5. <set-configuration-property name=”compiler.emulatedStack.recordFileNames”   
  6.      value=”true”/>   

Note, again, that this does increase the size of your Javascript bundle. For one application I worked on, I found that just turning on the emulatedStack increased the Javascript by 30%, and turning on emulatedStack plus line numbers increased it by 100% (i.e. doubled the size!). Depending on the performance requirements of your application, this may or may not be acceptable.

Finally, it’s helpful to know that even with the obfuscated stack traces, there is still hope for hunting down mysterious exceptions. What seems like jibberish is just obfuscated code, and you can manually translate the obfuscated method names (e.g. “Jq”, “Tm”, or “Sm” from the above example) to the Java method names using the symbolMaps file that GWT generates. If only there were a way to do this programmatically…

6. Use the StackTraceDeobfuscator

GWT provides a utility class called the StackTraceDeobfuscator which (as it advertises!) deobfuscates stack traces, translating the condensed, jibberish stack trace (like above) into a one that you would expect. If you’re using GWT’s remote logger, then it helpfully uses this by default, with one caveat: it knows where to find the symbolMaps file. GWT places this in the “WEB-INF/deploy/your-app/symbolMaps” directory, and you can instruct the RemoteLoggerService to look there accordingly:

  1. <init-param>  
  2.   <param-name>symbolMaps</param-name>  
  3.   <param-value>your-app/symbolMaps</param-value</param-value>  
  4. </init-param>  

You could also call the StackTraceDeobfuscator manually, if, for example, you had your own RPC service that handled exceptions in some custom way. I wrote a simple subclass of the StackTraceDeobfuscator, and called it like this:

  1. public class LogServiceImpl extends LogService {   
  2.   public void logError(Throwable t, String stackTrace) {  
  3.     StackTraceElement[] sts = stackTraceDeobfuscator.deobfuscateStackTrace(t.getStackTrace());  
  4.     t.setStackTrace(sts);  
  5.   
  6.     LOG.logError(“An error happened”, t);  
  7.   }  
  8. }  

7. Throw exceptions explicitly in RPC Services

Now, to the server side (which, thankfully, is much less tricky!). Imagine you have a simple RPC service that throws a custom exception, MyRuntimeException, which extends from RuntimeException. For example:

  1. public class MyServiceImpl extends MyService {   
  2.   public void foo() {   
  3.     throw new MyRuntimeException();  
  4.   }  
  5. }  

By Java’s rules, there is no obligation that you explicitly declare (either in the impl or interface) that foo throws MyRuntimeException. For the sake of simplicity, you may choose not to, however you might be surprised then to find that when you catch this exception in your AsyncCallback

  1. myService.foo(new AsyncCallback<Void>() {   
  2.   public void onSuccess(void v) {  
  3.   }  
  4.   
  5.   public void onFailure(Throwable t) {  
  6.     if(t instanceof MyRuntimeException) {   
  7.       // do something  
  8.     }  
  9.   }  
  10. }  

…the object t will not be an instance of MyRuntimeException, but rather an UnexpectedException. This is because GWT did not know to compile MyRuntimeException into Javascript, and so the client code does not know of this type. To remedy, make sure you explicitly throw MyRuntimeException in your service interface (but not in your Async interface!):

  1. public interface MyService {   
  2.   void foo() throws MyRuntimeException;  
  3. }  

Note that if you threw some subclass of MyRuntimeException, the instanceof check work, however be aware that GWT would then compile all concrete subclasses of MyRuntimeException, which could slow build time.

Whew…that’s it. Please share any tips you have, or let me know if you see anything awry with what I’ve written. Thanks!

 
Posted in gwt, Software Engineering, Uncategorized

GWT CellTable Example (Using AsyncDataProvider)

http://www.mytechtip.com/2010/11/gwt-celltable-example-using_8168.html

GWT CellTable Example (Using AsyncDataProvider)

GWT version 2.1 has finally been released with the anticipated business level data presentation widgets and other interesting features. CellTable is one of the new widgets that supports pagination. Therefore, there no need to usePagingScrollTable in the gwt incubator or implementations in other third-party libraries.

From the Google official document on how to use data presentation widgets, you can get some examples of using these cell widgets including CellTable. It also includes a simple example of using CellTable with SimplePager to implement pagination. That example uses ListDataProvider which requires all the data that needs to be paged to be set at the client (browser) side. However, in realty, the common practice is to load only one page of data from the server (mostly pulled from a database) to the browser in order to save the bandwidth and improve the response time.

Of course the document indicates there are ways to implement the asynchronized page data loading from remote server.

To illustrate how to use AsyncDataProvider, I modified a simple example from GWT below.

Please note the example do not actually calls the server to get the data. It should be quite easy to modify the example to do so as illustrated in the next code snippet.

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;

public class CellTableExample implements EntryPoint {

/**
   * A simple data type that represents a contact.
   */
private static class Contact {
private final String address;
private final Date birthday;
private final String name;

public Contact(String name, Date birthday, String address) {
this.name = name;
this.birthday = birthday;
this.address = address;
}
}

/**
   * The list of data to display.
   */
@SuppressWarnings("deprecation")
private static final List<Contact> CONTACTS = Arrays.asList(
new Contact("John", new Date(80, 4, 12), "123 Abc Avenue"),
new Contact("Joe", new Date(85, 2, 22), "22 Lance Ln"),
new Contact("Tom", new Date(85, 3, 22), "33 Lance Ln"),
new Contact("Jack", new Date(85, 4, 22), "44 Lance Ln"),
new Contact("Tim", new Date(85, 5, 22), "55 Lance Ln"),
new Contact("Mike", new Date(85, 6, 22), "66 Lance Ln"),
new Contact("George", new Date(46, 6, 6),"77 Lance Ln"));

public void onModuleLoad() {
// Create a CellTable.
final CellTable<Contact> table = new CellTable<Contact>();
// Display 3 rows in one page
table.setPageSize(3);

// Add a text column to show the name.
TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
@Override
public String getValue(Contact object) {
return object.name;
}
};
table.addColumn(nameColumn, "Name");

// Add a date column to show the birthday.
DateCell dateCell = new DateCell();
Column<Contact, Date> dateColumn = new Column<Contact, Date>(dateCell) {
@Override
public Date getValue(Contact object) {
return object.birthday;
}
};
table.addColumn(dateColumn, "Birthday");

// Add a text column to show the address.
TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
@Override
public String getValue(Contact object) {
return object.address;
}
};
table.addColumn(addressColumn, "Address");

// Associate an async data provider to the table
// XXX: Use AsyncCallback in the method onRangeChanged
// to actaully get the data from the server side
AsyncDataProvider<Contact> provider = new AsyncDataProvider<Contact>() {
@Override
protected void onRangeChanged(HasData<Contact> display) {
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
end = end >= CONTACTS.size() ? CONTACTS.size() : end;
List<Contact> sub = CONTACTS.subList(start, end);
updateRowData(start, sub);
}
};
provider.addDataDisplay(table);
provider.updateRowCount(CONTACTS.size(), true);

SimplePager pager = new SimplePager();
pager.setDisplay(table);

VerticalPanel vp = new VerticalPanel();
vp.add(table);
vp.add(pager);

// Add it to the root panel.
RootPanel.get().add(vp);
}
}

To make remote calls to retrieve table data from the server, The code snippet should look like the following.

// Associate an async data provider to the table
AsyncDataProvider<Contact> provider = new AsyncDataProvider<Contact>() {
@Override
protected void onRangeChanged(HasData<Contact> display) {
final int start = display.getVisibleRange().getStart();
int length = display.getVisibleRange().getLength();
AsyncCallback<List<Contact>> callback = new AsyncCallback<List<Contact>>() {
@Override
public void onFailure(Throwable caught) {
Window.alert(caught.getMessage());
}
@Override
public void onSuccess(List<Contact> result) {
updateRowData(start, result);
}
};
// The remote service that should be implemented
remoteService.fetchPage(start, length, callback);
}
};