javaspringspring-bootspring-mvcapplication.properties

value not injecting in @ReuqestBody POJO from application-dev.properties - SpringBoot Application


I am new to Java SpringBoot and I am trying to inject a default value from application-dev.properties file. Basically, the idea is to set default value to RequestObject's id property, default value being injected(/fetched) from application-dev.properties.

UseCase: In case, no data or blank data is being passed in request body of API, the code should set a default value (being injected/fetched from application-dev.properties).

Controller Code

@RequestMapping(value = PATH, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
private @ResponseBody ResponseEntity<ResponseBean<ResponseObject>> postController(
    final @Valid @RequestBody RequestObject request) throws Exception {
return serviceClass.service(request);
}

I did the following in RequestObject Class code

public class RequestObject {

    @Value("${package.default}")
    private String default_id;
    private String id = default_id;
    
    public String getId() {
     return id;
}

public void setId(String id) {
    this.id = !StringUtils.isBlank(id) ? id : default_id;
}

The above code is not working. Please help or suggest a better way to achieve the requirement.

Note: If I hardcode the id value like id="abcd" while defining & in setter method, the code is working.


Solution

  • You can inject stuff(default values from application properties, other beans, etc.) only in spring managed components - those are classes annotated with @Component, @Service etc.

    RequestObject, being a class you map request body to, is not, and should not be a component.

    In order to inject default value from application.properties you need custom deserializer, which is a bean, and register this deserializer with ObjectMapper.

    @Component
    public class RequestObjectDeserializer extends StdDeserializer<RequestObject> {
    
        @Value("${your.property.here}")
        private String defaultValue;
    
        public RequestObjectDeserializer() {
            super(RequestObject.class);
        }
    
        @Override
        public RequestObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
            //deserialize
        }
    }
    

    Then register it with already existing Objectmapper:

    @Autowired
    public void configObjectMapper(ObjectMapper objectMapper, RequestObjectDeserializer deserializer) {
        SimpleModule module = new SimpleModule();
        module.addDeserializer(RequestObject.class, deserializer);
        objectMapper.registerModule(module);
    }
    

    You can add above in any @Configuration class.

    I'd say keeping the default value as static field in RequestObject, and having the logic in setter, is better in this case.