Skip to content
Christopher Viel edited this page Jan 6, 2015 · 17 revisions

This extension aims at making your resource interfaces (and annotations!) reusable by server implementations (DRY principle). To achieve this, the extension will generate a delegate that will wrap the call to the resource and to RestDispatch.

Setup

  1. Follow the setup instruction for Rest-Dispatch here.

  2. Add the jar to your classpath. If you are using maven:

    <dependency>
        <groupId>com.gwtplatform.extensions</groupId>
        <artifactId>dispatch-rest-delegates</artifactId>
        <version>${gwtp.version}</version>
        <scope>provided</scope>
    </dependency>
  3. Inherit the extension in your GWT module file:

    <inherits name="com.gwtplatform.dispatch.rest.delegates.ResourceDelegate"/>

Usage

Write resources

The way you write resources and sub-resources doesn't change. However, the return type of your end-point is no longer limited to RestAction<?> or a sub-resource. Your end-points can return any concrete class or primitives. The returned type must be the type of the expected result. ie:

@Path("/cars")
interface CarsResource {
    // You can use sub-resources:
    @Path("/{car-id}")
    CarResource car(@PathParam("car-id") long id);

     // You can return primitive or boxed types:
    @GET
    @Path("/count")
    int count();

    // You can return collections of concrete classes:
    @GET
    List<Car> allCars();

    // You can mix with methods that return RestAction<?>
    RestAction<Void> create(Car car);
}

interface CarResource {
    // You can return any concrete class, as long as they are serializable:
    @GET
    Car get();

    // Even void works:
    @DELETE
    void delete();
}

Use resources

If you want to call a resource method that returns something else than a RestAction<?> or a sub-resource, then you must use the following syntax. Note that this syntax is fully compatible with RestAction<?> and sub-resource. It is also easier to unit test, so you are encouraged to use it in all cases.

Basically the difference with vanilla Rest-Dispatch is that you won't inject both your resource and DispatchRest. Instead, you will inject a ResourceDelegate<R> where R is your resource type. Then, through a fluent interface, you will pass a callback and call your end-point. ie:

class MyClass {
    @Inject
    ResourceDelegate<CarsResource> carsDelegate;

    void loadCar(long carId) {
        carsDelegate
               .withCallback(new AsyncCallback<Car>() {
                    @Override
                    public void onSuccess(Car car) { /* snip */ }

                    @Override
                    public void onFailure(Throwable throwable) { /* snip */ }
                })
                .car(carId)
                .get();
    }
}

Note that you must call withCallback() or withoutCallback() to get access to the resource methods.

Additionally, you can pass a DelegatingDispatchRequest object to withDelegatingDispatchRequest() to get a reference of the underlying dispatch request. This may be useful if you make a long running call and may want to cancel it before it completes.

Write unit tests

TODO

Gotchas

So you may wonder why this is not included in the core of Rest-Dispatch. The reason is that by using the delegates, the type safety of your callback can no longer be verified at compile-time. For example, if your end-point returns a Car and your callback expects a Wheel, you won't know there's something wrong until this code is executed at runtime. This problem can be leveraged by consistently writing unit tests that covers your dispatch calls (which we encourage you to write anyways). So that's why we felt this was a potential source of errors for some users and made this feature and extension instead. But rest assured, we use this in many internal projects and, by having a good unit test coverage, this has never caused us issues.

Clone this wiki locally