New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@ConfigurationProperties locations #6726

Closed
Delwing opened this Issue Aug 23, 2016 · 10 comments

Comments

Projects
None yet
@Delwing

Delwing commented Aug 23, 2016

Question

Hey,
Before Spring Boot 1.4 I've been using @ConfigurationProperties to configure simmilar beans with different properties.
Example:

@Configuration
public class TagConfiguration {

    @Bean(name = "restrictive")
    @ConfigurationProperties(locations = "classpath:whitelist-restrictive.yml")
    public TagProviderConfiguration tagProviderConfigurationLevel0() {
        return new TagProviderConfiguration();
    }

    @Bean(name = "basic")
    @ConfigurationProperties(locations = "classpath:whitelist-basic.yml")
    public TagProviderConfiguration tagProviderConfigurationLevel1() {
        return new TagProviderConfiguration();
    }

}

Now, not only this code does not compile, since prefix is duplicated, but also locations param is deprecated.

So is there any way to achieve similar result but without using prefixes? I just want to have very similar configuration files to configure multiple beans.

@snicoll

This comment has been minimized.

Member

snicoll commented Aug 23, 2016

We want to promote the use of a consistent Environment. You could have both the restrictive.* and basic.* keys to be defined in the environment. There's really no need to have separate files for that.

If, for some reasons, you want to have that configuration separate in custom files, you can use the spring.config.location attribute to define where Spring Boot should load its configuration.

We don't think that having one bean tied to one source file is a good thing. There's some nice content in this comment as well: #6220 (comment)

@Delwing

This comment has been minimized.

Delwing commented Aug 23, 2016

This is very inconvenient, since configuration like white-lists can be very long and adding keys feels like "polluting" config file. I guess PropertiesConfigurationFactory with YamlPropertiesFactoryBean will do the trick in that case.

@OrangeDog

This comment has been minimized.

OrangeDog commented Feb 7, 2017

I have one single class that loads its data from an external yaml file, unrelated to the application environment. @ConfigurationProperties(location = ) was perfect for this.

What exactly am I supposed to replace this with, without polluting the global environment or exposing the implementation requirements of this class?

@snicoll

This comment has been minimized.

Member

snicoll commented Feb 7, 2017

This issue is closed and I think I already replied to that question. If that's not enough, please ask on stackoverflow.

@gabrieledarrigo

This comment has been minimized.

gabrieledarrigo commented Apr 1, 2017

@OrangeDog how do you solved?

@Zubastick

This comment has been minimized.

Zubastick commented Jun 15, 2017

That's how I fixed it:

public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        return name != null ? new PropertySourcesLoader().load(resource.getResource(), name, null) : new PropertySourcesLoader().load(
                resource.getResource(), getNameForResource(resource.getResource()), null);
    }

    private static String getNameForResource(Resource resource) {
        String name = resource.getDescription();
        if (!StringUtils.hasText(name)) {
            name = resource.getClass().getSimpleName() + "@" + System.identityHashCode(resource);
        }
        return name;
    }
}

Mark your properties class:

@PropertySource(value` = "classpath:someyml.yml", factory = YamlPropertySourceFactory.class)
@ConfigurationProperties("prefix")

That's to make load YML at all. Since spring boot 1.5.4 it doesn't work at all.

@fanyaoxuan

This comment has been minimized.

fanyaoxuan commented Dec 7, 2017

@Zubastick I want to get the array through @value,But they never get it
@Value("${shiro.oauths}") private String[] oauths;

@Tianhao25

This comment has been minimized.

Tianhao25 commented Dec 8, 2017

I still don't get this...Why using locations in configurationproperties is bad? It took me so much time to find an alternative solution...

@MisterSpicy

This comment has been minimized.

MisterSpicy commented Feb 27, 2018

I get the desire to reduce code smell and advocate for a clean environment, but few of us work in such nice environments, and often we don't get to choose how our configurations are handed to us.

I really hope Spring brings it back in a future release!

@kaifuu

This comment was marked as off-topic.

kaifuu commented Aug 29, 2018

Hi,@Zubastick

If your convenient, could your help me take a look? many thanks.
I used YamlPropertySourceFactory, it need to append spring-boot.1.5.4.RELEASE in pom.xml.
When the program is run, the following exception occurs.

2018-08-29 16:49:14.644 ERROR [main] org.springframework.boot.SpringApplication:771 - Application startup failed                
java.lang.NoClassDefFoundError: org/springframework/boot/context/properties/bind/Binder
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment