Jersey - Changing the query parameters from a request.

2,156 views
Skip to first unread message

Dev

unread,
Jul 16, 2015, 11:03:07 AM7/16/15
to dropwiz...@googlegroups.com

Not a pure dropwizard question this! Hope you guys answer.


Is there a way to change the existing query parameters using a jersey filter. I have clients passing in id's like this

/v1/path?id=1,2,3

What I would like is for them to show up as a list in my resource class //Resource class

public List<Something> getFilteredList(@QueryParam("id") List<String> ids) {//

Right now, the ids list contains 1 string which is 1,2,3. I would like to apply a filter and change any comma separated query parameters into multivalued parameters so that the resource method gets a list instead.

Is this at all possible? I tried a filter but the query params given by Jersey's

ContainerRequestContext.getUriInfo().getQueryParameters() 

is immutable.

What's a good way to solve this problem?

Jonne Jyrylä

unread,
Jul 16, 2015, 11:45:58 AM7/16/15
to dropwizard-user
You can create an injection annotation @ListQueryParam that can be applied to resource method parameters.

In your resource class:

@GET
@Path("/test")
public Response test(@ListQueryParam("list") List<String> list)
{
    return Response.ok(list.toString()).build();
}


Add this in your application's run method:

environment.jersey().register(new AbstractBinder()
{
    @Override
    protected void configure()
    {
        bind(ListQueryParamValueFactoryProvider.class).to(ValueFactoryProvider.class).in(Singleton.class);
        bind(ListQueryParamInjectionResolver.class).to(new TypeLiteral<InjectionResolver<ListQueryParam>>() {}).in(Singleton.class);
    }
});


ListQueryParamValueFactoryProvider.java:

public class ListQueryParamValueFactoryProvider extends AbstractValueFactoryProvider
{
    @Context
    private HttpServletRequest request;
   
    @Inject
    public ListQueryParamValueFactoryProvider(MultivaluedParameterExtractorProvider mpep, ServiceLocator injector)
    {
        super(mpep, injector, Parameter.Source.UNKNOWN);
    }
   
    @Override
    protected Factory<?> createValueFactory(final Parameter parameter)
    {
        Class<?> classType = parameter.getRawType();
       
        if (classType == null || (!classType.equals(List.class)))
        {
            return null;
        }
       
        return new ValueFactory(parameter);
    }
   
    private class ValueFactory extends AbstractContainerRequestValueFactory<List<String>>
    {
        private final Parameter parameter;
       
        public ValueFactory(Parameter parameter)
        {
            this.parameter = parameter;
        }
       
        @Override
        public List<String> provide()
        {
            ListQueryParam annotation = parameter.getAnnotation(ListQueryParam.class);
           
            if (annotation == null)
            {
                throw new IllegalStateException("parameter has no ListQueryParam annotation");
            }
           
            String parameterValue = request.getParameter(annotation.value());
           
            if (parameterValue == null)
            {
                return Collections.emptyList();
            }
           
            return Arrays.asList(parameterValue.split(","));
        }
    }
   
    public static class ListQueryParamInjectionResolver extends ParamInjectionResolver<ListQueryParam>
    {
        public ListQueryParamInjectionResolver()
        {
            super(ListQueryParamValueFactoryProvider.class);
        }
    }
}


ListQueryParam.java:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ListQueryParam
{
    String value();
}


Now a request to GET /test?list=1,2,3 returns [1, 2, 3]

--
You received this message because you are subscribed to the Google Groups "dropwizard-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dropwizard-us...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Jonne Jyrylä
jaa...@gmail.com

jpl...@gmail.com

unread,
Jul 17, 2015, 10:27:24 AM7/17/15
to dropwiz...@googlegroups.com
Another option is to use Dropwizard's built-in parameters (http://www.dropwizard.io/manual/core.html#parameters), to do something like:

public class ListLongParam extends AbstractParam<List<Long>> {


    public ListLongParam(String input) {

        super(input);

    }


    @Override

    protected List<Long> parse(String input) throws Exception {

        if (Strings.isNullOrEmpty(input)) {

            return ImmutableList.of();

        }


        final Iterable<String> splitter = Splitter.on(',').omitEmptyStrings()

                .trimResults().split(input);


        final ImmutableList.Builder<Long> builder = ImmutableList.builder();

        for (String value : splitter) {

            try {

                builder.add(Long.parseLong(value));

            } catch (NumberFormatException ignore) {

                // ignore invalid numbers

            }

        }

        return builder.build();

    }

}


-Justin

Reply all
Reply to author
Forward
0 new messages