users@jersey.java.net

Re: [Jersey] common handling of path param

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 01 Mar 2010 16:50:15 +0100

On Mar 1, 2010, at 4:34 PM, Trolly Rogers wrote:

> Hi Paul - I guess I knew that I could use UriInfo to solve this
> problem, but I just couldn't figure out how to access the darn
> thing! I was looking at how to use the ContainerRequest instance
> passed to the ContainerRequestFilter's filter method and couldn't
> figure it out how to get UriInfo there. Now my java intuition tells
> me this would be the only safe place to handle per-request
> information like UriInfo because I can see that the container is
> creating a single instance of my resource filter factory and filter.
>
> But based on your last comment about using UriInfo, I slapped
> @Context UriInfo uriInfo; on my filter (didn't work), and then tried
> the same on the factory, this worked! :) ... Now I apologize, this
> is a little mind bending how this works since i'm storing per-
> request information in a member of an instance that handles many
> requests.
>
> Can you confirm this is a thread safe approach (i assume it is), and
> maybe shed a little light why it's safe?

It is thread-safe. A thread local proxy is injected. Jersey will set
the thread local instance before request processing starts. You will
get an IllegalStateException if you access the proxy outside of the
scope of a request e.g. in the constructor or a @PostConstruct
annotated method.


> I looked at the javadoc for ResourceFilterFactory and didn't see any
> info on how annotations can be used there.
>

Any "provider" component, something that Jersey is responsible for
instantiating as a singleton (one per-application) can be injected on.
The reason why injection did not work on the filters is because you
are responsible for instantiating the filters returned by
ResourceFilterFactory.

Paul.


> I'll start digging up info on AbstractSubResourceLocator, this one
> is new to me.
>
> As always, thanks for reading/responding!
>
>
> On Mon, Mar 1, 2010 at 8:33 AM, Paul Sandoz <Paul.Sandoz_at_sun.com>
> wrote:
>
> On Feb 25, 2010, at 11:26 PM, Trolly Rogers wrote:
>
>> Thank you kindly, Marc. This approach definitely works.
>>
>> Strictly from a design perspective... I just wish I could figure
>> out a way to completely decouple this and let my resources just be
>> concerned about being resources. This would also mean the solution
>> is reusable since other groups (where i work) who use {id} can just
>> configure the solution w/out impacting and/or dictating how they
>> design their resources.
>>
>> ResrouceFilter via custom ResourceFilterFactory seems like a great
>> fit, I just can't figure out how (or if it's possible) to get the
>> resolved path param value of a given request.
>>
>
> You can use UriInfo to get the map of path parameters currently in
> scope. See UriInfo.getPathParameters. Is that what you want?
>
> When using ResourceFilterFactory you can utilize
> AbstractSubResourceLocator, obtaine the PathValue, parse it using
> UriTemplate and then obtain the template variables or path parameter
> names. That way you may be able to avoid hardcoding path parameter
> names.
>
> Paul.
>
>>
>> On Thu, Feb 25, 2010 at 1:29 PM, Marc Hadley <Marc.Hadley_at_sun.com>
>> wrote:
>> One approach you could use is subresource locators. E.g.
>>
>> @Path("/users/{id}")
>> public class UserResource {
>>
>> public UserResource(@PathParam("id") String id) {
>> // do whatever common work is required
>> }
>>
>> @Path("some/sub/path/1")
>> public SomeSubPath1Resource getSubPath1Resource() {
>> // instantiate whatever kind of resource is appropriate
>> // based on work done in constructor
>> }
>>
>> ...
>> }
>>
>> The getSubPath1Resource method returns an instance of a resource
>> class to handles the actual request (e.g. a class with @GET, @POST
>> ect methods.
>>
>> Marc.
>>
>> On Feb 24, 2010, at 9:51 PM, Trolly Rogers wrote:
>>
>> > Hi All - Hope I'm not being a pest. I just can't figure out how
>> to handle some common logic needing to be applied to a common path
>> param (at least the way I'd like to). I have a bunch of resources
>> which all share a couple things I mentioned below. There's
>> basically one root resource, and a number of sub-resources exposed
>> via method and locator. Here's the two things they all have in
>> common...
>> >
>> > 1. part of thier URIs. They all begin with /users/{id}. The id is
>> not the user's user id exactly, but it is a unique way to identify
>> the user and provides a great piece of scoping info keeping my URIs
>> RESTful.
>> >
>> > 2. The {id} path param needs to be checked against the value of
>> HttpServletRequest's getUserPrincipal().getName(). This name is set
>> as part of our security infrastructure and ensure the {id} passed
>> to my resource is in fact the right user.
>> >
>> > I thought I was on to something when I was workin' on my own
>> ResourceFilterFactory impl. The thing I got hung up on was how to
>> get the value of the resolved {id} path param, is this possible in
>> a ContainerRequestFilter?
>> >
>> > The solution I have working now is basically having my resource
>> classes sub class "UserIdAuthBasedResource" which provides a
>> constructor forcing any sub classes to pass in the user id and
>> HttpServletRequest for the common checking (#2). There's obvious
>> disadvantages here (but it works), any suggestions?
>> >
>> > Thanks,
>> >
>> > Trolly
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>>
>
>