jsonjacksonjava-8restlet-2.0

How to register Jackson Jdk8 module in Restlet


Is it possible to register the jackson-datatype-jdk8 module in the Restlet org.restlet.ext.jackson extension package? I need to take advantage of the new Optional feature. My guess is that it should be accessible through the converter services (getConverterService()) but I can't find anything in the documentation that suggests exactly how setting a module is possible.


Solution

  • I eventually pieced together from a variety of sources an answer that works with Restlet 2.3. My guess is that this will be refactored for Restlet 3 and it won't work for versions < 2.3 so be aware that this solution will most likely have a limited shelf life.

    First step is to create a custom Jackson converter that implements any custom requirements you have:

    public class CustomJacksonConverter extends JacksonConverter { 
        @Override 
        protected <T> JacksonRepresentation<T> create(MediaType mediaType, T source) { 
            ObjectMapper mapper = createMapper(); 
            JacksonRepresentation<T> jr = new JacksonRepresentation<T>(mediaType, source); 
            jr.setObjectMapper(mapper); 
            return jr; 
        } 
    
        @Override 
        protected <T> JacksonRepresentation<T> create(Representation source, Class<T> objectClass) { 
            ObjectMapper mapper = createMapper(); 
            JacksonRepresentation<T> jr = new JacksonRepresentation<T>(source, objectClass); 
            jr.setObjectMapper(mapper); 
            return jr; 
        } 
    
    
        private ObjectMapper createMapper() { 
            JsonFactory jsonFactory = new JsonFactory(); 
            jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false); 
            ObjectMapper mapper = new ObjectMapper(jsonFactory); 
            mapper.registerModule(new Jdk8Module()); 
            return mapper; 
        } 
    
    } 
    

    You then need to create a way of replacing the default Jackson converter with a copy of your new one:

    static void replaceConverter(
                Class<? extends ConverterHelper> converterClass,
                ConverterHelper newConverter) {
    
            ConverterHelper oldConverter = null;
    
            List<ConverterHelper> converters = Engine.getInstance().getRegisteredConverters();
            for (ConverterHelper converter : converters) {
                if (converter.getClass().equals(converterClass)) {
                    converters.remove(converter);
                    oldConverter = converter;
                    break;
                }
            }
    
            converters.add(newConverter);
        }
    

    You can now replace the converter in your inbound root:

    replaceConverter(JacksonConverter.class, new CustomJacksonConverter());