In a JAX-RS web-app we make use of subresources:
@Path("/some/things")
public class ThingsListResource {
@Inject
SomeStorage store;
@GET
public List<Thing> getAllThings() {
return store.getAllThings();
}
@Path("{id}")
public ThingResource getThingResource(@PathParam("id") String id) {
return new ThingResource(id); // PROBLEMATIC
}
}
public class ThingResource {
@Inject
SomeOtherDependecy dep;
@Inject
SomeStorage store;
private final String id;
public ThingResource(String id) {
this.id = id;
}
@GET
public Thing getThisThing() {
return store.getThing(id);
}
@DELETE
public void removeThisThing() {
store.removeThing(id);
}
// following is a list of methods useful enough
// to make ThingResource a useable subresource
}
As you noticed, there are injections which are made with Guice and its GuiceResteasyBootstrapServletContextListener. The dependencies of root resources are injected without problems. The problematic line above is marked with PROBLEM: the subresource is created by-hand, which omits all Guice injections.
What is the elegeant way to inject dependencies with Guice into subresources? I can think of a few options here:
Inject the injector into the root resource and use it to create a subresource, probably with some
@Assistedmagic in the subresource:@Inject Injector injector // ... return injector.getInstance(ThingResource.class); // via some provider accepting id?but I can't wrap my head arround injecting the
idof the "thing" into the provider or@Assistedinjections. Also, it looks like a lot of Guice boilerplate is required here.Forget about Guice management of the subresource and pass every dependency to its constructor by hand from the root resource. Simple, yet very "dependency injection by hand"-like.
Make the subresource and inner class of
ThingsListResourceand thus let it have an access to the outer class (injected) fields. Not very extensible (e.g. if one want to have different subresources implementing the common interface), but simple...Forget about subresources and "upgrade" them to root resources. It's a bit breaking of DRY rule, as you will specify full URL paths to each resource.
Is there any other way to go or simpler way to realize the above ideas?