First application
Introduction
This first application illustrates how to develop a Restlet application that combines several editions of the Restlet Framework : GAE, GWT, Android and Java SE. It explains the benefits of annotated Restlet interfaces and of the ConverterService that offers transparent serialization between Restlet representations and Java objects, usable between a server application and several kind of clients.
Table of contents
- Requirements
- Scenario
- Archive content
- Common classes
- GAE server part
- GWT client
- Android client
- Java SE client
Requirements
It is based on the following editions of the Restlet Framework : Google App Engine (GAE), Google Web Toolkit (GWT) and Android. It has been tested with the following environments:
- Restlet Framework 2.0 (latest snapshot from 04/23/2010)
- Google App Engine (GAE) 1.2.1 to 1.3.0
- Google Web Toolkit (GWT) 1.7 to 2.1 (probably previous versions as well)
- Android 1.6 to 2.1 (probably previous versions as well)
Each edition of the Restlet Framework you use must be downloaded as a separate Zip or Windows installer file from this page.
Scenario
The server application is hosted on the Google App Engine (GAE) platform. For the sake of simplicity it serves only one resource named "contact", with the following characteristics:
- its relative URI is "/contacts/123"
- it supports the GET, PUT and DELETE methods.
- it represents a simple "contact" object.
The "contact" object has the following attributes:
- firstname
- lastname
- age
- home address (actually an instance of a "Address" class): line1, line2, zipcode, city and country
This resource will be requested fro several kind of clients:
- GWT client page
- Android application
- Java SE client
Archive content
The full source code is available here: serializationFullSource. (application/force-download, 10.0 MB, info)
It contains the full source code of three Eclipse projects with:
- Project that contains both the GAE server and the GWT client code
- Project that contains the source code of the Android client
- Project that contains the source code of the Java SE client
Common classes
The following classes are available on the three project. They are used by the server and the clients in order to produce the serialized representation of the Contact object and to deserialize incoming representations.
- Contact
- Address
- ContactResource.
ContactResource is an interface annotated with Restlet annotations:
public interface ContactResource {
@Get
public Contact retrieve();
@Put
public void store(Contact contact);
@Delete
public void remove();
}
It represents the contract passed between the client and the server.
GAE server part
We propose to host the server application on the GAE platform. The server project relies on the following JAR files:
- org.restlet.jar: core archive (GAE edition)
- org.restlet.ext.gwt.jar: GWT server-side extension to convert Java objects to a GWT-specific serialization format (GAE edition)
- org.restlet.ext.servlet: Servlet extension to deploy the Restlet application in GAE (GAE edition)
- org.restlet.ext.jackson: Jackson extension used to generate JSON representations of the contact resource (GAE edition)
The server-side resource implements the annotated interface.
/**
* The server side implementation of the Restlet resource.
*/
public class ContactServerResource extends ServerResource implements ContactResource {
private static volatile Contact contact =
new Contact("Scott", "Tiger", new Address("10 bd Google", null, "20010", "Mountain View",
"USA"), 40);
@Delete
public void remove() {
contact = null;
}
@Get
public Contact retrieve() {
return contact;
}
@Post
public void store(Contact contact) {
ContactServerResource.contact = contact;
}
}
This resource is then exposed by the server application:
@Override
public Restlet createInboundRoot() {
Router router = new Router(getContext());
getConnectorService().getClientProtocols().add(Protocol.FILE);
// Serve the files generated by the GWT compilation step.
Directory dir = new Directory(getContext(), LocalReference.createFileReference(new File("war/")));
router.attachDefault(dir);
router.attach("/contacts/123", ContactServerResource.class);
return router;
}
GWT client part
The GWT client relies only on the core Restlet JAR (org.restlet.jar) provided in the GWT edition.
In order to get the Contact object, a proxy class is required. This is an interface that inherits on a specific interface (delivered by the GWT edition of the Restlet Framework):
public interface ContactResourceProxy extends ClientProxy {
@Get
public void retrieve(Result<Contact> callback);
@Put
public void store(Contact contact, Result<Void> callback);
@Delete
public void remove(Result<Void> callback);
}
This interface looks like the ContactResource interface, expect that it adds a callback to each declared methods, due to the asynchronous nature of the GWT platform and the underlying AJAX mechanism offered by web browsers.
The type of the callback is not limited to the Result interface of the Restlet Framework, it can also be the usual AsyncCallback interface provided by GWT. Thus it allows you to easily migrate an existing GWT-RPC code base to GWT-REST with Restlet.
Then, the following code allows you to request and handle the Contact resource:
ContactResourceProxy contactResource = GWT.create(ContactResourceProxy.class);
// Set up the contact resource
contactResource.getClientResource().setReference("/contacts/123");
contactResource.getClientResource().getClientInfo().getAcceptedMediaTypes().add(new
Preference<MediaType>(MediaType.APPLICATION_JAVA_OBJECT_GWT));
// Retrieve the contact
contactResource.retrieve(new Result<Contact>() {
public void onFailure(Throwable caught) {
// Handle the error
}
public void onSuccess(Contact contact) {
// Handle the contact, for example by updating the GWT interface
// Contact fields
cTbFirstName.setText(contact.getFirstName());
cTbLastName.setText(contact.getLastName());
cTbAge.setText(Integer.toString(contact.getAge()));
}
});
Here is a screenshot of the GWT client page once the user has clicked on the GET button.
| Click to enlarge |
In order to update the contact, simply complete your contact object and invoke the "store" method as specified by the proxy interface:
contactResource.store(contact, new Result<Void>() {
public void onFailure(Throwable caught) {
// Handle the error
}
public void onSuccess(Void v) {
// Display a dialog box
dialogBox.setText("Update contact");
textToServerLabel.setText("Contact successfully updated");
dialogBox.center();
closeButton.setFocus(true);
}
});
Android client part
The Android client project relies only on the core Restlet JAR (org.restlet.jar) provided by the Android edition of the Restlet Framework.
The contact object will be serialized between the GAE server and the Android client (in both directions) using the standard Java serialization process. No additional interface is required except the ContactResource interface furnished by the server.
// Initialize the resource proxy.
ClientResource cr = new ClientResource("http://restlet-example-serialization.appspot.com/contacts/123");
ContactResource resource = cr.wrap(ContactResource.class);
// Get the remote contact
Contact contact = resource.retrieve();
In order to update the client, simply use this instruction:
resource.store(contact);
Here is a screenshot of the Android user interface.
Java SE client
Get the full Contact object
The same code used on the Android application allows you to get the full Contact object:
ClientResource cr = new ClientResource("http://restlet-example-serialization.appspot.com/contacts/123");
// Get the Contact object
ContactResource resource = cr.wrap(ContactResource.class);
Contact contact = resource.retrieve();
if (contact != null) {
System.out.println("firstname: " + contact.getFirstName());
System.out.println(" lastname: " + contact.getLastName());
System.out.println(" nage: " + contact.getAge());
}
This code produces the following ouput on the console:
firstname: Scott lastname: Tiger age: 40
Get a JSON representation
In case the Contact class is not available, you can still retrieve a JSON representation by setting the client preferences when retrieving the resource's representation:
cr.get(MediaType.APPLICATION_JSON).write(System.out);
which produces the following output:
{"age":40,"firstName":"Scott","homeAddress":{"country":"USA","city":"Mountain View","line1":"10 bd Google","line2":null,"zipCode":"20010"},
"lastName":"Tiger"}



I saw the code of the example provided, but I wanted to call the Post operation. My interface has the following method defined :@Post
public void makeCallSessionRequest(String inputCall, Result<String> callback);
In my client, I am calling as :
contactResource.makeCallSessionRequest
("<makeCallSessionRequest><callingId>tel:4049869141</callingId><calledId>tel:6785913788</calledId></makeCallSessionRequest>",new Result<String>() { ....}
I get the error : The constructor ObjectRepresentation<String>(String, SerializationStreamFactory) is ambiguous
Your help is really appreciated .. Thanks AB
http://www.restlet.org/community/issues