Maor Hamami
Maor Hamami

Reputation: 37

spring boot 2 properties configuration

I have some code that works properly on spring boot prior to 2 and I find it hard to convert it to work with spring boot 2.

Can somebody assist?

public static MutablePropertySources buildPropertySources(String propertyFile, String profile)
{
    try
    {
        Properties properties = new Properties();
        YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

        // load common properties
        PropertySource<?> applicationYamlPropertySource = loader.load("properties", new ClassPathResource(propertyFile), null);
        Map<String, Object> source = ((MapPropertySource) applicationYamlPropertySource).getSource();

        properties.putAll(source);

        // load profile properties
        if (null != profile)
        {
            applicationYamlPropertySource = loader.load("properties", new ClassPathResource(propertyFile), profile);

            if (null != applicationYamlPropertySource)
            {
                source = ((MapPropertySource) applicationYamlPropertySource).getSource();

                properties.putAll(source);
            }
        }

        propertySources = new MutablePropertySources();
        propertySources.addLast(new PropertiesPropertySource("apis", properties));
    }
    catch (Exception e)
    {
        log.error("{} file cannot be found.", propertyFile);
        return null;
    }
}

public static <T> void handleConfigurationProperties(T bean, MutablePropertySources propertySources) throws BindException
{
    ConfigurationProperties configurationProperties = bean.getClass().getAnnotation(ConfigurationProperties.class);

    if (null != configurationProperties && null != propertySources)
    {
        String prefix = configurationProperties.prefix();
        String value = configurationProperties.value();

        if (null == value || value.isEmpty())
        {
            value = prefix;
        }

        PropertiesConfigurationFactory<?> configurationFactory = new PropertiesConfigurationFactory<>(bean);
        configurationFactory.setPropertySources(propertySources);
        configurationFactory.setTargetName(value);
        configurationFactory.bindPropertiesToTarget();
    }
}

PropertiesConfigurationFactory doesnt exist anymore and the YamlPropertySourceLoader load method no longer accepts 3 parameters.

(the response is not the same either, when I have tried invoking the new method the response objects were wrapped instead of giving me the direct strings/integers etc...)

Upvotes: 2

Views: 3520

Answers (3)

Sebastian
Sebastian

Reputation: 878

Since there is no accepted answer yet, i post my full solution, which builds upon the answer from @nationquest:

private ConfigClass loadConfiguration(String path){
    MutablePropertySources sources = new MutablePropertySources();
    Resource res = new FileSystemResource(path);
    PropertiesFactoryBean propFactory = new PropertiesFactoryBean();
    propFactory.setLocation(res);
    propFactory.setSingleton(false);

    // resolve potential references to local environment variables
    Properties properties = null;
    try {
        properties = propFactory.getObject();
        for(String p : properties.stringPropertyNames()){
            properties.setProperty(p, env.resolvePlaceholders(properties.getProperty(p)));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    sources.addLast(new PropertiesPropertySource("prefix", properties));
    ConfigurationPropertySource propertySource = new MapConfigurationPropertySource(properties);
    return new Binder(propertySource).bind("prefix", ConfigClass.class).get();
}

The last three lines are the relevant part here.

Upvotes: 2

notionquest
notionquest

Reputation: 39226

The PropertiesConfigurationFactory should be replaced with Binder class.

Binder class

Sample code:-

ConfigurationPropertySource source = new MapConfigurationPropertySource(
                loadProperties(resource));
Binder binder = new Binder(source);
return binder.bind("initializr", InitializrProperties.class).get();

We were also using PropertiesConfigurationFactory to bind a POJO to a prefix of the Environment. In 2.0, a brand new Binder API was introduced that is more flexible and easier to use. Our binding that took 10 lines of code could be reduced to 3 simple lines.

YamlPropertySourceLoader:-

Yes, this class has been changed in version 2. It doesn't accept the third parameter profile anymore. The method signature has been changed to return List<PropertySource<?>> rather than PropertySource<?>. If you are expecting single source, please get the first occurrence from the list.

Load the resource into one or more property sources. Implementations may either return a list containing a single source, or in the case of a multi-document format such as yaml a source for each document in the resource.

Upvotes: 4

Related Questions