javajerseyjacksonjax-rsjersey-2.0

Custom ObjectMapper with Jersey 2.2 and Jackson 2.1


I am struggling with a REST application with Grizzly, Jersey and Jackson, because Jersey ignores my custom ObjectMapper.

POM dependencies:

<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-servlet</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.1.4</version>
    </dependency>
</dependencies>

Resulting versions are: Grizzly 2.3.3, Jackson 2.1.4 and Jersey 2.2.

Main class (I want explicit registration of Jersey components):

public class Main {
    public static void main(String[] args) {
        try {
            ResourceConfig rc = new ResourceConfig();
            rc.register(ExampleResource.class);
            rc.register(ObjectMapperResolver.class);

            HttpHandler handler = ContainerFactory.createContainer(
                    GrizzlyHttpContainer.class, rc);

            URI uri = new URI("http://0.0.0.0:8080/");

            HttpServer server = GrizzlyHttpServerFactory.createHttpServer(uri);

            ServerConfiguration config = server.getServerConfiguration();
            config.addHttpHandler(handler, "/");

            server.start();
            System.in.read();

        } catch (ProcessingException | URISyntaxException | IOException e) {
            throw new Error("Unable to create HTTP server.", e);
        }
    }
}

ContextResolver for ObjectMapper:

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class ObjectMapperResolver implements ContextResolver<ObjectMapper> {

    private final ObjectMapper mapper;

    public ObjectMapperResolver() {
        System.out.println("new ObjectMapperResolver()");
        mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        System.out.println("ObjectMapperResolver.getContext(...)");
        return mapper;
    }

}

Neither ObjectMapperResolver constructor nor getContext get called. What am I missing? I would prefer to use Jersey 2.2 and Jackson 2.1, because it is a dependency for another lib.

A full example can be found on GitHub: https://github.com/svenwltr/example-grizzly-jersey-jackson/tree/stackoverflow


Solution

  • I found a solution. I had to instantiate the Jackson Provider by myself and set my custom ObjectMapper. A working example can be found on GitHub: https://github.com/svenwltr/example-grizzly-jersey-jackson/tree/stackoverflow-answer

    I deleted my ObjectMapperResolver and modified my main method:

    public class Main {
        public static void main(String[] args) {
            try {
                // create custom ObjectMapper
                ObjectMapper mapper = new ObjectMapper();
                mapper.enable(SerializationFeature.INDENT_OUTPUT);
    
                // create JsonProvider to provide custom ObjectMapper
                JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
                provider.setMapper(mapper);
    
                // configure REST service
                ResourceConfig rc = new ResourceConfig();
                rc.register(ExampleResource.class);
                rc.register(provider);
    
                // create Grizzly instance and add handler
                HttpHandler handler = ContainerFactory.createContainer(
                        GrizzlyHttpContainer.class, rc);
                URI uri = new URI("http://0.0.0.0:8080/");
                HttpServer server = GrizzlyHttpServerFactory.createHttpServer(uri);
                ServerConfiguration config = server.getServerConfiguration();
                config.addHttpHandler(handler, "/");
    
                // start
                server.start();
                System.in.read();
    
            } catch (ProcessingException | URISyntaxException | IOException e) {
                throw new Error("Unable to create HTTP server.", e);
            }
        }
    }