How to check if unsupported parameter is contained in REST request?

You can do it by ContainerRequestFilter feature which is added from JavaEE 7 that lets you access the resource class and resource method matched by the current request and make you to do your desire action when that have not been matched.

You can read more here :

https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/ResourceInfo.html

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.QueryParam;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Provider;

@Provider
public class RequestParamFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        Set<String> acceptedParamList = new HashSet<String>();
        Method method = resourceInfo.getResourceMethod();
        for (Annotation[] annos : method.getParameterAnnotations()) {
            for (Annotation anno : annos) {
                if (anno instanceof QueryParam) {
                    acceptedParamList.add(((QueryParam) anno).value());
                }
            }
        }

        MultivaluedMap<String, String> queryParams = requestContext.getUriInfo().getQueryParameters();
        for (String param : queryParams .keySet()) {
            if (!acceptedParamList.contains(param)) {
                requestContext.abortWith(Response.status(Status.BAD_REQUEST).entity("Unexpected paramter found : "+param).build());
            }
        }
    }

}

P.N : Filters are cost in your application speed most of the times, Specially if you have complex chains in it!

I recommend to use it in this case (and similar cases) because of most of the those requests should not be reached to the server application at all.

I hope this helps you and Happy coding! =)


In this case you required HandlerInterceptor or HandlerInterceptorAdapter, override the preHandle method

@Override
public boolean preHandle(HttpServletRequest request,
        HttpServletResponse response, Object handler) throws Exception {
           //request param validation validation
            return true; //or throw exception 
}

ServletRequest.getParameterMap() returns a map of key-values of the request parameters.


As far as I know, you cannot simply disallow parameters using Spring. Honestly, this issue is rather questionable and unnecessary and I think it's an antipattern.

However, Spring provides with each mapping the HttpServletRequest and HttpServletResponse objects to the controller method signature. Use the method HttpServletRequest::getParameterMap to receive the Map of the passed parameters for the further iteration and validation.

@RequestMapping("/hello")
public String hello(RequestParam(value = "name") String name, HttpServletRequest request, HttpServletResponse response) {
    final Map<String, String[]> parameterMap = request.getParameterMap();
    // logics
}

Passing those object to only to the @RequestMapping("/hello") allows performing the validation only to the selected mapping. If you want to define this behavior globally, I suggest you use HandlerInterceptor::preHandle as answered here.

If you make the hello parameter required=true, then you can just check the size of the Map whether is equal to 1 or not.