Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure Dropwizard ObjectMapper for configuration to ignore unknown

With an ObjectMapper (com.fasterxml.jackson.databind) it's possible to specify that it should ignore unknown properties. This can either be done by adding @JsonIgnoreProperties(ignoreUnknown = true) on a class level or by setting it as default behavior in the mapper. However, when doing this in the initialize() method of Application<MyConfiguration> it doesn't seem to have an effect.

ObjectMapper mapper = bootstrap.getObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

It still fails for unknown properties in the configuration file. How does one configure Dropwizard to ignore unknown properties?

like image 489
Myone Avatar asked Dec 06 '17 13:12

Myone


2 Answers

The reason configuring DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES for bootstrap.getObjectMapper() doesn't have the desired effect is that ConfigurationFactory (the class later on used to parse the configuration) is enabling that particular feature of the object mapper in its constructor (see here):

public ConfigurationFactory(Class<T> klass,
                            Validator validator,
                            ObjectMapper objectMapper,
                            String propertyPrefix) {
    ...
    this.mapper = objectMapper.copy();
    mapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    ...
}

It's not possible to change the behaviour of ConfigurationFactory directly but Dropwizard provides means to override the factory that creates it, ConfigurationFactoryFactory, via Boostrap.setConfigurationFactoryFactory(). This allows to replace the real ObjectMapper with a proxy that doesn't allow to override the configuration and pass it to ConfigurationFactory:

  bootstrap.setConfigurationFactoryFactory(
      (klass, validator, objectMapper, propertyPrefix) -> {
          return new ConfigurationFactory<>(klass, validator,
              new ObjectMapperProxy(objectMapper), propertyPrefix);
      }
  );

The code for ObjectMapperProxy that ignores attempts to enable FAIL_ON_UNKNOWN_PROPERTIES it below:

private static class ObjectMapperProxy extends ObjectMapper {

    private ObjectMapperProxy(ObjectMapper objectMapper) {
        super(objectMapper);
    }

    private ObjectMapperProxy(ObjectMapperProxy proxy) {
        super(proxy);
    }

    @Override
    public ObjectMapper enable(DeserializationFeature feature) {
        // do not allow Dropwizard to enable the feature
        if (!feature.equals(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
            super.enable(feature);
        }
        return this;
    }

    @Override
    public ObjectMapper copy() {
        return new ObjectMapperProxy(this);
    }

}

Note that besides overriding enable to skip FAIL_ON_UNKNOWN_PROPERTIES copy is also implemented (together with an additional constructor) as ConfigurationFactory requires the object mapper to support copying.

While the solution above works it's obviously a workaround and I suggest upgrading to a newer Dropwizard version instead. The new Dropwizard makes ObjectMapper configuration easier to override (e.g. see this Dropwizard commit available in Dropwizard 1.1.x).

like image 112
raindev Avatar answered Sep 23 '22 20:09

raindev


You need to disable that feature with:

bootstrap.getObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

UPDATE: The feature disable works for the API resources but not for the configuration YAML. Instead, you need to add the annotation below (same as mentioned on the question) to the configuration class:

@JsonIgnoreProperties(ignoreUnknown = true)
like image 21
André Barbosa Avatar answered Sep 24 '22 20:09

André Barbosa