Request and Response Filters in Dropwizard

When constructing a Dropwizard application, there may be some pre-processing or post-processing you’d like to do on Resource methods. It’s fairly easy to add request and response filters in Dropwizard through the implementation of ContainerRequestFilter, ContainerResponseFilter, and ResourceFilterFactory, and adding them to the environment.

Request and Response Filters

The container filters will review every request and response, and can review properties of the request or response to determine behavior. For example, say we want to validate a specific query parameter when its present:

public class MyCustomRequestFilter implements ContainerRequestFilter {
    @Override
    public ContainerRequest filter(ContainerRequest request) {

        if (request.getQueryParameters().containsKey("validateMeParam")) {
            List paramValues = request.getQueryParameters().get("validateMeParam");

            /* validation logic */
        }

        // finished validation
        return request;
    }
}

Then, add that filter to the environment in your Application.

environment.getJerseyResourceConfig().getContainerRequestFilters().add(MyCustomRequestFilter.class);

Remember, this runs on every request and response, so be sure you want to run whatever checks you are running.

Filter Factories

Implementing the ResourceFilterFactory allows you to programmatically add request and response filters. The filters will then only run when applicable. Continuing in the validating of a specific parameter, let’s assume I have the annotation ValidateParams, which can be applied at the method or class level. The following implementation will look at each resource method when the application starts, and run the create method. If the annotation is present, the aforementioned MyCustomRequestFilter will be used.

public class MyCustomResponseFilterFactory implements ResourceFilterFactory {
    @Override
    public List<ResourceFilter> create(AbstractMethod am) {

        List<ResourceFilter> filtersAppliedToMethod = new ArrayList<ResourceFilter>();

        // get the annotation from the method
        ValidateParams ann = am.getAnnotation(ValidateParams.class);

        // if the method does not have the annotation, check the class
        if (ann == null) {
            ann = am.getMethod().getDeclaringClass().getAnnotation(ValidateParams.class);
        }

        // if the annotation is present, add the filter to the method
        if (ann != null) {
            filtersAppliedToMethod.add(new ValidateParamFilter());
        }

        return filtersAppliedToMethod;
    }

    /**
     * A factory object for creating ResponseFilters.
     */
    protected class ValidateParamFilter implements ResourceFilter {

        @Override
        public ContainerRequestFilter getRequestFilter() {
            return new MyCustomRequestFilter();
        }

        @Override
        public ContainerResponseFilter getResponseFilter() {
            // no response filter needed
            return null;
        }
    }
}

Then, add this factory to the environment in your Application.

environment.getJerseyResourceConfig().getResourceFilterFactories().add(ResponseProducerFactory.class);