Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding included provider in Jersey

I need to make a custom ExceptionMapper in Jersey to handle the JsonProcessingException returned by Jackson.

The Jackson library already includes ExceptionMapper providers for this exception in the form of JsonMappingExceptionMapper.java and JsonParseExceptionMapper.java (link).

If I add a new provider for this exception mapper in "my.package" I get unpredictable results regarding the selected provider. Sometimes it will select the provider in "my.package" and sometimes it will select the provider in the Jackson library. The code I'm using to scan the packages is below.

PackgesResourceConfig packagesResourceConfig = new PackgesResourceConfig("com.fasterxml.jackson.jaxrs", "my.package");

Proposed Solution

Currently I am getting around this by filtering out the provider in the Jackson library manually. But what I really want to know is whether there is a more acceptable and supported way of doing this.

First I extend PackagesResourceConfig.

public class FilteredPackgesResourceConfig extends PackagesResourceConfig {

    private Set<Class<?>> classesToFilter = new HashSet<Class<?>>();

    public FilteredPackgesResourceConfig(String... packages) {
        super(packages);
    }

    public FilteredPackgesResourceConfig(Map<String, Object> props) {
        super(props);
    }

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = super.getClasses();

        if (classes != null && classesToFilter != null) {
            classes.removeAll(classesToFilter);
        }

        return classes;
    }

    public Set<Class<?>> getClassesToFilter() {
        return classesToFilter;
    }

    public void setClassesToFilter(Set<Class<?>> classesToFilter) {
        this.classesToFilter = classesToFilter;
    }
}

This I use this class to filter out the specific providers I don't want.

FilteredPackgesResourceConfig packagesResourceConfig = new FilteredPackgesResourceConfig("com.fasterxml.jackson.jaxrs", "my.package");
classesToFilter.add(com.fasterxml.jackson.jaxrs.json.JsonMappingExceptionMapper.class);       
classesToFilter.add(com.fasterxml.jackson.jaxrs.json.JsonParseExceptionMapper.class);
packagesResourceConfig.setClassesToFilter(classesToFilter);

This solution gives me the desired result of only using the providers I specified. Is there a more correct way of achieving the same result?

like image 453
Andrew Avatar asked Apr 13 '13 15:04

Andrew


1 Answers

I also came across this problem, in my case I solved it by instead of registering com.fasterxml.jackson.jaxrs.json package I only registered the class I wanted, which in my case was com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.

There are several ways to do this, I did it using web.xml like so:

<servlet>
  <servlet-name>jersey-serlvet</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>
         my.own.package
         my.other.package
      </param-value>
  </init-param>
  <init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
      com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider
    </param-value>
  </init-param>
    <init-param>
      <param-name>jersey.config.disableMoxyJson</param-name>
      <param-value>true</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

Note: I'm using Jersey 2.0, in 1.x the property names and servlet class are diferent but the same config is possible.

like image 193
pns Avatar answered Sep 30 '22 16:09

pns