-
Notifications
You must be signed in to change notification settings - Fork 10
Resource Delegates
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
.
-
Follow the setup instruction for Rest-Dispatch here.
-
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>
-
Inherit the extension in your GWT module file:
<inherits name="com.gwtplatform.dispatch.rest.delegates.ResourceDelegate"/>
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();
}
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.
TODO
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 an extension. But rest assured, we use this in many internal projects and, by having a good unit test coverage, this has never caused us issues.