users@jersey.java.net

[Jersey] Re: How Jersey dispatch request based on query parameter rather than path?

From: 王子剑 <nerther_at_gmail.com>
Date: Wed, 16 Nov 2011 22:20:26 +0800

Hi Pavel

Actually the return types are totally different, example:

@Path("{people}")
public People getPeople(@PathParam String people);

@Path("{people}?location")
public Location getLocation(@PathParam String people);

@Path("{people}?friends")
public List<People> getFriends(@PathParam String people);

......

Jersey dispatch incoming request base on path rather on query parameters,
but we can encode the expected query parameter to the path to implement it
transparently.

I write a ContainerRequestFilter to do this,

public class SubResourceMatchableRequestFilter implements
ContainerRequestFilter {

@Override
public ContainerRequest filter(ContainerRequest request) {
final String subResource = getFirstSubResource(request);
if (subResource == null) {
return request;
}
return new AdaptingContainerRequest(request) {
@Override
public String getPath(boolean decode) {
return new StringBuilder(super.getPath(decode))
.append(decode ? "?" : "%3F")
.append(subResource)
.toString();
}
};
}

private String getFirstSubResource(ContainerRequest request) {
String query = request.getRequestUri().getQuery();
if (query == null) {
return null;
}
int indexOfFirstAnd = query.indexOf("&");
return indexOfFirstAnd == -1 ? query : query.substring(0, indexOfFirstAnd);
}
}

The requirement can be archived, but I don`t know is there some hidden
trouble?

Looking forward to your reply, thanks.

Regards,
Zijian.

在 2011年11月16日 下午6:15,Pavel Bucek <pavel.bucek_at_oracle.com>写道:

> Yeah, you are right.
>
> It should be achievable by using reqexes, but I've tested this:
>
> @GET
> @Path("{people}")
> public String getPeople(@PathParam("people") String people,
> @QueryParam("location") String location) {
> if(location == null) {
> return location;
> } else {
> return people;
> }
> }
>
> and looks like it does what you need. location param here can be null
> ("?location" not present) or "" (empty string), thus you are able to
> decide what to return (you are using same return data type for both
> methods in you example so that shouldn't be a problem..
>
> Let me know if this works for you.
>
> Regards,
> Pavel
>
>
> On 11/16/11 2:39 AM, 王子剑 wrote:
> > Hi Pavel
> >
> > Thank you for your kind reply.
> >
> > The code: webResource.path("test?location").get(String.class); will
> > encode character *?* to *%3F*(url encode), that means the request url
> > will be *http://test.com/test%3Flocation* instead of
> > *http://test.com/test?location*.
> >
> > If someone use unencoded url like *http://test.com/test?location*,
> > Jersey will return 405 'MethodNotAllowed' response.
> >
> > Best regards.
> >
> > Zijian
> >
> > 2011/11/15 Pavel Bucek <pavel.bucek_at_oracle.com
> > <mailto:pavel.bucek_at_oracle.com>>
> >
> > Hi 王子剑,
> >
> > please use users_at_jersey.java.net <mailto:users_at_jersey.java.net>
> > mailing list, this one is for mailing list administration only.
> >
> > And about your issue - it can be achieved, you need to exclude
> > requests containing question mark from first method. See following:
> >
> > @GET
> > @Path("{people:[^\\?]*}")
> > public String getPeople(@PathParam("people") String people) {
> > return people;
> >
> > }
> >
> > @GET
> > @Path("{people}?location")
> > public String getLocation(@PathParam("people") String people) {
> > return "location:" + people;
> > }
> >
> > I verified this with following requests:
> >
> > responseMsg = webResource.path("test").get(String.class); //
> > matches getPeople
> > responseMsg = webResource.path("test?location").get(String.class);
> > // matches getLocation
> >
> > Regards,
> > Pavel
> >
> >
> >
> >
> >
> > On 11/15/11 11:10 AM, 王子剑 wrote:
> >> Hello All
> >>
> >> I am handling a legacy system and I cannot process the request by
> >> Jersey gracefully.
> >>
> >> API:
> >>
> >> *GET : http://test.com/{people}
> >> <http://test.com/%7Bpeople%7D> * Get people information
> >>
> >> *GET : http://test.com/{people}?location
> >> <http://test.com/%7Bpeople%7D?location>* Get people location.
> >>
> >>
> >>
> >> Code
> >>
> >> *_at_GET*
> >> *_at_Path("{people}")*
> >> *public People getPeopleInformation(String people);*
> >> *
> >> *
> >> *_at_GET*
> >> *_at_Path("{people}?location")*
> >> *public People getPeopleLocation(String people);*
> >> *
> >> *
> >>
> >> Jersey will not invoke the second method *getPeopleLocation *when
> >> the client request url: *http://test.com/{people}?location
> >> <http://test.com/%7Bpeople%7D?location>*, it always dispatch the
> >> incoming request which end with '?location' to the first method
> >> '*getPeopleInformation*'.
> >>
> >> Is there some way to let Jersey to dispatch request based on
> >> query parameters like this situation?
> >> *
> >> *
> >> *
> >> *
> >
> >
>
>