Spring Boot: read list of objects from yaml using @ConfigurationProperties is always returning null

Viewed 604

I want to create a yaml file from which I get my constants

constantsConfiguration.yml

constants:
 myList:
   -
     id: 11
     name: foo1
     firstName: bar1
     allowed: true
   -
     id: 22
     name: foo2
     firstName: bar2
     allowed: false

the configuration class looks like this:

@Data
@Component
@PropertySource("classpath:constantsConfiguration.yml")
@ConfigurationProperties(prefix = "constants")
public class ConstantProperties {

    private List<User> myList;

    @Data
    public static class User{
        private String id;
        private String name;
        private String firstName;
        private Boolean allowed;

    }
}

and this is a dummy example of how I want use it

@Service
@RequiredArgsConstructor
public class MyService{

   private final ConstantProperties constantProperties;

   public Boolean isEmptyList(){
       return CollectionUtils.isEmpty(constantProperties.getMyList());
   }
}

constantProperties.getMyList() is always null I am using spring boot : 2.5.12 and java 11

1 Answers

The root cause is that the new SpringBoot will not parse the properties file as yaml properties.

You need add a Yaml PropertiesSourceFactory class first. Like below:

import java.io.IOException;
import java.util.Properties;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
}

Then in the class of: ConstantsProperties, you need specify the Factory class explicitly. like:

import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import lombok.Data;

@Data
@Component
@PropertySource(value = "classpath:constantsConfiguration.yml", factory = YamlPropertySourceFactory.class)
@ConfigurationProperties(prefix = "constants")
public class ConstantProperties {
    private List<User> myList;

    @Data
    public static class User {
        private String id;
        private String name;
        private String firstName;
        private Boolean allowed;

    }

}

Finally, Please pay attention to your yaml file format. Each separator should be 2 ' ' blank chars.

Please try it , it should work now.

Related