2

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

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks for your answer but that didn't work for me
I just updated the answer. It should work now. Please try it. The new spring-boot need yaml propertysource factory to parse the yaml file.
0

@SeanH 's answer didn't work to me. The way I found to make it parse lists of objects from a yaml is using a list of a map. Then you will need to convert each map into the object you want:

First create YamlPropertySourceFactory as SeanH explained, and then in the ConstantProperties.class:

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

    public List<User> getUserList() {
        List<User> users = new ArrayList<>();
        myList.forEach(userInfo -> {
            User user = new User(userInfo.get("id"),
                                 userInfo.get("name"),
                                 userInfo.get("firstName"),
                                 Boolean.valueOf(userInfo.get("allowed")));
            users.add(user);
        });
        return users;
    }

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

        public User(String id, String name, String firstName, Boolean allowed) {
            this.id=id;
            this.name=name;
            this.firstName=firstName;
            this.allowed=allowed;
        }

        // Add Getters and Setters
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.