RestyGWT User Guide
RestyGWT is a GWT generator for REST services and JSON encoded data transfer objects.
- Generates Async Restful JSON based service proxies
- Java Object to JSON encoding/decoding
- Easy to use REST API
RestyGWT Rest Services allow you to define an asynchronous Service API which is then implemented via GWT deferred binding by a RestyGWT generator. See the following listing for an example:
JAX-RS annotations are used to control how the methods interface map to HTTP requests. The
interface methods MUST return either
JsonpRequest. Each method must declare at least one callback argument.
Methods can optionally declare one method argument before the callback to pass via the request
or if using
REST.withCallback(..).call(..), you can reuse the same interface on the server side as well:
JAX/RS Subresource locators
RestyGWT supports JAX-RS subresource locator methods as synchronous methods on service interfaces. For instance:
This allows developers to decompose service interfaces into logical chunks and even reuse interfaces for multiple sections of the virtual
REST URL hierarchy. Currently only
@PathParam subresource locators are supported.
Java beans can be sent and received via JSON encoding/decoding. Here what the classes declarations
look like for the
OrderConfirmation in the previous example:
The JSON encoding style is compatible with the default Jackson Data Binding. For example,
PizzaOrder’s JSON representation would look like:
A GWT client creates an instance of the REST service and associate it with a HTTP resource URL as follows:
The request dispatcher intercepts all requests being made and can supply
additional features or behavior. For example, RestyGWT also supports a
CachingRetryingDispatcher which will automatically retry requests if
To configure the
CachingRetryingDispatcher, you can configure it on
your service interface at either the class or method level. Example:
Creating Custom Request Dispatchers
You can create a custom request dispatcher by implementing the following
Your dispatcher implementation must also define a static singleton instance in a public
INSTANCE field. Example:
When the dispatcher’s
send method is called, the provided builder will already
be configured with all the options needed to do the request.
Configuring the Request Timeout
You can use the
@Options annotation to configure the timeout for requests
at either the class or method level. The timeout is specified in milliseconds,
For example, to set a 5 second timeout:
Configuring service root URLs
There are two ways to configure service root URLs which are appended with the
@Path annotation property
when building the final service URL. For single service root URL the
Defaults.setServiceRoot(String) method can be used. When several services with different service roots are used the
@Options annotation is equipped with
serviceRootKey property which can be set to read service root entries provided with the static
ServiceRoots.add(String, String) method.
Configuring the Expected HTTP Status Code
By default results that have a 200, 201, or 204 HTTP status code are considered
to have succeeded. You can customize these defaults by setting the
@Options annotations at either the class or method level of the service interface.
Content-Type and HTTP Headers
RestyGWT rest calls will automatically set the
and HTTP Headers to match the type of data being sent and the type of
data expected by the callback. You can override these default values
by adding JAX-RS’
@Consumes annotations to the method
Keep the Java Interface clean
If you need an attribute of your DTO to be part of the URL you can do it by adding the
@Attribute annotation alongside the
@PathParam references the placeholder in the
@Path as usual and the
@Attribute identifies the attribute/field of the DTO which shall be used for the replacement in the path.
Mapping to a JSONP request
If you need to access JSONP URl, then use the
@JSONP annotation on the method.
or if you have a
FlickrFeed value object
If you want to manually access the JSON encoder/decoder for a given type just define
an interface that extends
JsonEncoderDecoder and RestyGWT will implement it for you using
GWT deferred binding.
First you define the interface:
Then you use it as follows
In case you need to parse the JSON from a
the default date format is
and can be set in the
when setting it to
null then unix time will be used.
Customizing the JSON Property Names
If you want to map a field name to a different JSON property name, you
can use the
@Json annotation to configure the desired name. Example:
or with the Jackson annotation
Using read-only objects
If you want to declare final fields and initialize an object through its constructor,
you can use the
@JsonCreator and the
@JsonProperty annotations. Example:
Note that all the parameters of an annotated constructor should be annotated with the
As long as each property name matches the declared field names, the
order can be freely chosen.
Using gwt-jackson for JSON serialization and deserialization
NOTE: the gwt-jackson integration is still experimental, so
please give it trial and report bugs to resty-gwt and/or gwt-jackson as in the long run gwt-jackson will the default.
Add following to your GWT module XML file:
See also jackson support of gwt-jackson.
Custom Serializer Generators
RestyGWT allows you to add another encode/decoder-generator which is used with certain classes. There are three simple steps for enabling fully customized serializer generation:
org.fusesource.restygwt.rebind.JsonEncoderDecoderClassCreatorto create an external serializer generator that can be registered to handle values of certain types. You should override the
org.fusesource.restygwt.rebind.RestyJsonSerializerGeneratorand specify two things:
- your custom serializer generator class created in the first step (
- target class or its superclass to use this generator for (
- your custom serializer generator class created in the first step (
- Specify your
RestyJsonSerializerGeneratorcustom implementation fully qualified class name in the
org.fusesource.restygwt.restyjsonserializergeneratorconfiguration property in your GWT module XML file. This property is multi-valued so you can add multiple custom serializer generators. Example:
Custom Annotation Handler
Due to the functionality of GWT generators, a generator needs to be responsible
for the whole generation processing of a particular type. To give RestyGWT users
the flexibility to extend this generation process, you can register custom
Runtime Annotation Information
Whilst annotation-parsing and processing happens only in generation/compilation
process so far,
AnnotationResolver are able to compile extra information into the
org.fusesource.restygwt.client.RestService implementation, which will be
available inside a
org.fusesource.restygwt.client.Dispatcher and inside a
Transport of the Annotation information happens via
org.fusesource.restygwt.client.Method#addData(String key, String value)
The ability to use annotation information during runtime makes it really easy to implement own annotations which can be applied to
and cause a customized runtime behaviour later on.
One use case of such an extension of the annotation parsing is the following:
Model Change Events
Presenter wants to be informed about changes in the model, so a
reload of some data can be automatically triggered, whenever a particular
org.fusesource.restygwt.example.client.event.ModelChangeEvent is caught.
To have a central location where such
ModelChangeEvents are thrown, a
RequestCallback seems perfect. Usually – without custom
there would be no information about “what event for which domain type should be thrown”.
Solution is to have a
This class must be registered on RestyGWT’s generation process in your
Additionally assume the following
RestService interface definition
Now we will have information about our custom annotation inside the
… and inside the
A fully working example can be found in the integration-test:
The RestyGWT REST API is handy when you don’t want to go through the trouble of creating
The following example, will post a JSON request and receive a JSON response. It will set the HTTP
X-HTTP-Method-Override headers to the expected values.
It will also expect a HTTP 200 response code, otherwise it will
consider request the request is a failure.
All the standard HTTP methods are supported:
Calling one of the above methods creates a
Method object. You must create a new one
for each HTTP request. The
Method object uses fluent API for easy building
of the request via method chaining. For example, to set the user id and password
used in basic authentication you would:
You can set the HTTP request body to a text, XML, or JSON value. Unless the content type
is explicitly set on the method, the following methods will set the
Method object also allows you to set headers, a request timeout, and the expected
‘successful’ status code for the request.
Finally, once you are ready to send the HTTP request, pick one of the following methods based on the expected content type of the result. Unless explicitly set on the method, the following methods will set the
Accept header for you:
The response to the HTTP request is supplied to the callback passed in the
Once the callback is invoked, the
method.getRespose() method to get the GWT
if you are interested in things like the headers set on the response.
Polymorphic Sub Types
A common feature used in Object Oriented languages is to use polymorphism to represent
several specialist versions of a parent object. This structure is simple to serialise
using GWT’’s built-in RPC system as it represents the Java types via a specialist protocol.
Unfortunately the JSON spec doesn’t directly support this behaviour. However it can be added by including the type information in an extra JSON property. JSON parsers that are not aware of this special behaviour will see it as a regular JSON property.
RestyGWT supports polymorphic sub-types via two of the Jackson features –
@JsonSubTypes is used when you have perfect knowledge of all possible subtypes at coding time.
can be used in situations where you want to classpath-scan or use some other dynamic mechanism to determine
the possible subtypes at application assembly (GWT compilation) time.
The Jackson library (a JSON parser) supports this behaviour by adding a series of annotations to the
POJO classes will be serialised to JSON. RestyGWT can also use these annotations
to provide the same Jackson compatible behaviour.
In the below example we have a zoo that contains various different types of animals, each with their own specific properties. The super class that the other classes inherit must be an abstract class and annotated like the example below:
The sub class uses the
@JsonTypeInfo annotation to declare how the type information will
be included in the JSON. Only the
use methods are supported at present.
Class will use the full Java class name whereas
Name will use a name provided by the user
to represent each type.
@JsonSubTypes annotation provides a list of possible types which the JSON can be mapped
to. These must all be sub classes of this type or one of its sub classes. If the name method
is used the name can be optionally specified for each type. In the example above only the
class name is specified.
@JsonTypeName annotation can be used to specify the name the type will be mapped to. It must be
specified via this method or the
@JsonSubTypes annotation on the super class. If both are
specified the one on the
@JsonSubTypes is used.
Notice no additional information is needed to serialise the
Dog class as all its information
is specified on the
Animal super class.
Finally we can use the
Animal class as we would if it was a single concrete class. When the
POJO is used in the GWT code you can use the animal list the same as you would with any
polymorphic list. Usually by using the instanceof keyword and casting the object to the specific type.
In this example, suppose we have an abstract class
Animal, but we don’t know until we have all of the
jars assembled for the final application just what kinds of animal the application will be supporting. Resty
can handle this situation like this:
You may have a proper implementation of
AnimalResolver (which must implement
for use by Jackson elsewhere in your system (e.g. on the server to write out these objects properly in response to
REST calls). However, because the
TypeIdResolver interface does not offer an API that publishes all of the available subtypes, we
will need to implement an extension interface – namely
This is done as follows:
First, in your
*.gwt.xml, instruct Resty to add your implementation to the available
RestyJsonTypeIdResolvers available at compile time.
and then implement
AnimalRestyTypeIdResolver as follows:
‘AnimalRestyTypeIdResolver will be instantiated and interrogated at GWT compile time (deferred binding time, actually). This code will not be compiled itself into
You can optionally implement
RestyJsonTypeIdResolver on your
TypeIdResolver class, in which case you do not need to include the configuration property setting.
Reusing server interfaces.
If you’re using JAX-RS on the server-side as well, you might notice that you’re repeating yourself in the client and server interfaces, with only a minor change for the client interface (since the callback must be asynchronous). So if you would have a JAX-RS service that just lists files, implemented like this:
Your corresponding RestyGWT interface would be:
Now if on the server the interface would change, let’s assume a new
filter parameter would be added, your service call
will fail at runtime, without giving you a chance to know this API contract is now invalidated at compile time.
Using the new
REST.withCallback().call() API this issue is addressed. How does it work?
First you need now an interface that will extend the marker interface
DirectRestService (not simply
Secondly, your server will just implement it:
And third, client side, you will just declare it:
…and use it; since the calls are still async, you still need to provide a callback, and call it:
Because the service is called asynchronously, the response returned by the
listFiles() method – from
call(listFilesService).listFiles("/mypath") – will always be null, and in this example
is being assigned just to enforce the check by the compiler of the return type as well.
The parameters are the actual parameters sent to the service, and the response will be received by the callback.
Since the same interface is reused, this is extremely well fit to changes, including service path, response type or parameters changes. In case the API changes, the compilation will break.
Thus you basically have now statically typed JSON services, with JAX-RS/Jackson on the server side, and RestyGWT on the client side.