How do you map multiple query parameters to the fields of a bean on Jersey GET request?

In Jersey 2.0, you'll want to use BeanParam to seamlessly provide what you're looking for in the normal Jersey style.

From the above linked doc page, you can use BeanParam to do something like:

@GET
@Path("find")
@Produces(MediaType.APPLICATION_XML)
public FindResponse find(@BeanParam ParameterBean paramBean) 
{
    String prop1 = paramBean.prop1;
    String prop2 = paramBean.prop2;
    String prop3 = paramBean.prop3;
    String prop4 = paramBean.prop4;
}

And then ParameterBean.java would contain:

public class ParameterBean {
     @QueryParam("prop1") 
     public String prop1;

     @QueryParam("prop2") 
     public String prop2;

     @QueryParam("prop3") 
     public String prop3;

     @QueryParam("prop4") 
     public String prop4;
}

I prefer public properties on my parameter beans, but you can use getters/setters and private fields if you like, too.


Try something like this. Use UriInfo to get all the request parameters into a map and try to access them. This is done inplace of passing individual parameters.

// showing only the relavent code
public FindResponse find( @Context UriInfo allUri ) {
    MultivaluedMap<String, String> mpAllQueParams = allUri.getQueryParameters();
    String prop1 = mpAllQueParams.getFirst("prop1");
}

You can use com.sun.jersey.spi.inject.InjectableProvider.

import java.util.List;
import java.util.Map.Entry;

import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;

import org.springframework.beans.BeanUtils;

import com.sun.jersey.api.core.HttpContext;
import com.sun.jersey.api.model.Parameter;
import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;

@Provider
public final class ParameterBeanProvider implements InjectableProvider<QueryParam, Parameter> {

    @Context
    private final HttpContext hc;

    public ParameterBeanProvider(@Context HttpContext hc) {
        this.hc = hc;
    }

    @Override
    public ComponentScope getScope() {
        return ComponentScope.PerRequest;
    }

    @Override
    public Injectable<ParameterBean> getInjectable(ComponentContext ic, final QueryParam a, final Parameter c) {

        if (ParameterBean.class != c.getParameterClass()) {
            return null;
        }

        return new Injectable<ParameterBean>() {

            public ParameterBean getValue() {
                ParameterBean parameterBean = new ParameterBean();
                MultivaluedMap<String, String> params = hc.getUriInfo().getQueryParameters();
                // Populate the parameter bean properties
                for (Entry<String, List<String>> param : params.entrySet()) {
                    String key = param.getKey();
                    Object value = param.getValue().iterator().next();

                    // set the property
                    BeanUtils.setProperty(parameterBean, key, value);
                }
                return parameterBean;
            }
        };
    }
}

In your resource you just have to use @QueryParam("valueWeDontCare").

@GET
@Path("find")
@Produces(MediaType.APPLICATION_XML)
public FindResponse find(@QueryParam("paramBean") ParameterBean paramBean) {
    String prop1 = paramBean.getProp1();
    String prop2 = paramBean.getProp2();
    String prop3 = paramBean.getProp3();
    String prop4 = paramBean.getProp4();
}

The provider will be automatically called.