Hi,
I'd like to get your input/ideas on how to pass information down to
sub-resources. Given URI:
/company/{companyId}/users/{name}/messages
Here are the requirements:
1. Pass information down to sub-resources without binding it to a
specific parent type. In other words, we want to push information down
instead of pulling it from a known parent.
2. Immutable resources. This implies the use of constructor injection
and/or final fields. We are not allowed to use setters to pass
information down.
3. The resulting code should be easy to read and maintain.
Here is what I discovered so far:
1. We can use ExtendedUriInfo.getMatchedResources() to look up parent
resources from the child.
2. We can use HttpServletRequest.setAttribute()/getAttribute() to pass
information from parent to sub-resources. The downside is that it's not
type-safe.
3. We can construct the sub-resources using "new" (passing down
dependencies as needed), using ResourceContext.getResource(Class) or
using Guice AssistedInject.
4. If we use ResourceContext.getResource(Class) we need to use an
external mechanism for passing user variables, such as
HttpServletRequest.setAttribute(). I dislike the lack of type safety,
but it sounds like the easiest approach to read and maintain.
5. In my experience, Guice AssistedInject is harder to read and
maintain. You need to edit user parameters in two places (constructor
and factory), and register the factory.
6. Finally, we can inject dependencies into the top-level resource, then
pass them down to sub-resources manually when we invoke "new". A slight
variation of this is injecting "Injector" and passing it down instead.
I favor the last approach, simply passing "Injector" down to
sub-resources created using "new". I know that the Guice crowd
discourages this, but I argue this use-case is different. Normally
Guice's footprint is limited to an @Inject annotation. In theory you
could invoke the same constructor without Guice and it would function
like a normal POJO. In our case, however, AssistedInject requires us to
write and maintain quite a bit more code *and* Guice is very much in our
face. One would be hard-pressed to invoke AssistedInject-oriented code
without Guice. Since we're forced to go down this road anyway, we might
as well just interact with Injector directly.
I'd really like to hear from you. What do you think? Is there a better way?
Thanks,
Gili