IgorShare Thoughts and Ideas

Consulting and Training

Building fat GWT web clients [Intro] – How to create a GWT RPC client?

Posted by Igor Moochnick on 05/18/2009

After months of working (mainly fighting with quirks of Java) with GWT I’ve accumulated so much knowledge on the topic so, I feel, it starts spilling over. I’m planning to convert this spill into a series of articles on how to build fat REST-full GWT web fat clients both on Java and .NET.

Here is the list of topics I’ll cover:

  1. Building GWT fat client
  2. Java REST-full Web services
  3. .NET REST-full Web services
  4. Internationalization and localization
  5. IOC/DI
  6. Unit testing and integration testing of all the components of the system
  7. Build automation
  8. and much, much more …

Here is a draft list of technologies I’ll be using:

  1. GWT
  2. Eclipse
  3. Spring
  4. Jersey
  5. Tomcat
  6. XStream
  7. AJAX
  8. JSON/XML
  9. WCF
  10. JUnit/TestND/NUnit
  11. Selenium
  12. Ant
  13. TeamCity
  14. and much, much more …

For starters, let’s see how to create a simple GWT fat client that talks to the REST-full Web services. As an example,

let’s think about contact management scenario where we’re going to create a web client that will be used to browse all your existing contacts.

We’re going to use:

  1. GWT 1.6 + GWT RPC
  2. Eclipse Ganymede + GWT Eclipse plugin

After creating a basic GWT project (in Eclipse you can use “Create GWT Project” icon on the toolbar), create a simple client (see the attached source code).

The client I’ll be using in my examples is very simple, but there are a couple of key points you should note. To make the GWT client to connect to the back end via GWT RPC you need to create 3 different classes:

  1. ContactManagerService – Client side RPC stub
  2. ContactManagerServiceAsync – The asyncronous counterpart of GreetingService
  3. ContactManagerServiceImpl – The server side implementation of the RPC service
package com.igorshare.client;
@RemoteServiceRelativePath("contacts")
public interface ContactManagerService extends RemoteService {
	List getContacts(String filter);
}

package com.igorshare.client;
public interface ContactManagerServiceAsync {
	void getContacts(String filter, AsyncCallback<List> callback);
}

package com.igorshare.server;
public class ContactManagerServiceImpl extends RemoteServiceServlet implements
		ContactManagerService {
	public List getContacts(String filter) { ... }
}

Note that only serializable types can go over the wire. To make your own structure serializable, inherit it from IsSerializable interface. This will notify GWT generator to create a JSNI representation for this structure and an appropriate proxy.

This is how the ContactInfo class looks like:

package com.igorshare.client;
public class ContactInfo implements IsSerializable {
	
	public String FirstName;
	public String LastName;
	public String Company;
	
	...
}

This is as much ceremony as need to make sure that there is a REST-full communication between the server side and the client side.

To make a call to our new server, on the client side, a reference to the server proxy is needed as well as definition an asynchronous callback which  will handle a success and a failure of the execution. In our example the failure is not really handled – only an error message logged. On success – the contact table is cleaned and populated with the new data that came from the server.

private final ContactManagerServiceAsync greetingService = GWT
		.create(ContactManagerService.class);

...

// Add a handler to send the search criteria to the server
sendButton.addClickHandler(new ClickHandler() {
	/**
	 * Fired when the user clicks on the sendButton.
	 */
	public void onClick(ClickEvent event) {
		sendNameToServer();
	}

	/**
	 * Send the name from the nameField to the server and wait for a
	 * response.
	 */
	private void sendNameToServer() {
		greetingService.getContacts(filterField.getText(),
				new AsyncCallback<List>() {
					public void onFailure(Throwable caught) {
						// Show the RPC error message to the user
						GWT.log("Remote Procedure Call - Failure", caught);
					}

					public void onSuccess(List result) {
						contacts = result;
						updateContactTable();
					}
					
					private void updateContactTable()
					{
						// Clean contacts table
						for(int i=contactsTable.getRowCount()-1; i>0; i--)
							contactsTable.removeRow(i);
						
						// Fill the table with the data from the server
						for(ContactInfo contact : contacts)
						{
							int row = contactsTable.getRowCount();
							contactsTable.setText(row, 0, contact.FirstName);
							contactsTable.setText(row, 1, contact.LastName);
							contactsTable.setText(row, 2, contact.Company);
						}
					}
				});
	}
});

 

One more thing you should remember is that the relative path to the service (See the  @RemoteServiceRelativePath("contacts")  annotation on the ContactManagerService) should correspond to the path in the web.xml file:

	contactsServlet
	com.igorshare.server.ContactManagerServiceImpl


	contactsServlet
	/contactmanager/contacts

 

On the next post I’ll show how to make this GWT client to talk to a JAX-RS REST-full web service. I’ll use Jersey to enable our back-end service.  Stay tuned …

3 Responses to “Building fat GWT web clients [Intro] – How to create a GWT RPC client?”

  1. […] Building fat GWT web clients [Intro] – How to create a GWT RPC client? […]

  2. Danilla said

    Спасибо за статью оказалась очень полезной.

  3. Hmmm … I have always considered GWT a thin client technology. Especially with REST.

    — Come unto me, all ye who are weary of fat and heavy clients, and I will give you REST.

Leave a comment