3

According to Spring Boot documentation, properties can be grouped and a property may appear in more than one group. But at the moment when we create a property class marked with @ConfigurationProperties(prefix="test1") the group name will be the prefix which is test1. Now if I have another property class for example with prefix as "test2" how can I say this latter one has a property from the group test1?

--- UPDATE --- Added nested class but it's not working

@Configuration
@Profile({"wmx"})
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "myapp.wmx", locations = {"classpath:application-wmx.properties", "classpath:myapp-env.properties"})
public class WmxProperties {

    /**
     * The WMX implementation to be loaded.
     */
    @NotNull(message = "Must be configured.")
    private ProfileEnum profile;

    //@ConfigurationProperties(locations = "classpath:myapp-env.properties")
    public static class Env {
        /**
         * Host name for WMX.
         */
        private String host;
        /**
         * Port number for WMX.
         */
        //@Pattern(regexp = "^[1-9]\\d*$", message = "Positive port number only.")
        private Integer port;
        /**
         * Provider name.
         */
        @NotBlank
        private String providerName;

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public Integer getPort() {
            return port;
        }

        public void setPort(Integer port) {
            this.port = port;
        }

        public String getProviderName() {
            return providerName;
        }

        public void setProviderName(String providerName) {
            this.providerName = providerName;
        }
    }

    public ProfileEnum getProfile() {
        return profile;
    }

    public void setProfile(ProfileEnum profile) {
        this.profile = profile;
    }
}

The commented annotation @ConfigurationProperties on the inner class is done after failing my tests. Spring doesn't load those properties with or without the annotation unless they are in the same property file, in this case application-emx.properties. Why is that? I want to separate these properties

=== RESOLVED ==== I noticed that I had to add a field of type the nested class with getter/setter methods otherwise Spring won't load the properties in the nested class

1
  • I'm not sure what properties do you have. Could you give an example of your properties and what you tried so far with ConfigurationProperties? Commented Dec 3, 2015 at 9:02

2 Answers 2

4

You can compose them with help of inner classes:

Property file

test1.property1=...
test1.test2.property2=...
test1.test2.property3=...

Java/Spring mapping:

import javax.validation.constraints.NotNull;

import lombok.Getter;
import lombok.Setter;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Getter
@Setter
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(locations = "classpath:myapp.properties")
public class ApplicationProperties {

    private String property1;
    private Test2 test2;

    @Getter
    @Setter
    @ConfigurationProperties(prefix = "test2")
    public static class Test2 {
        @NotNull
        private String property2;
        @NotNull
        private String property3;
    }
}

We had success with this approach, because java composition mimics structure of property file. Also properties are validatable, so you can fail fast if configuration is not right.

Downside of this approach is that properties are mutable.

If your properties file is getting too big, your application most probably has wider problems.

4
  • Thanks. This is fine but what if the Test2 properties are not directly related to Test1. So we want to group them for documentation reason. For example, a set of properties for RabbitMQ configuration and another set for a callback mechanism. Now each set has a url property which want them to be grouped in Environmental Properties. we want to use this format to generate documentation for our clients
    – xbmono
    Commented Dec 3, 2015 at 22:47
  • Just curious, are you able to validate properties at compile time? I have added spring-boot maven plugin but it doesn't validate properties and the validation occurs at deploy time.
    – xbmono
    Commented Dec 3, 2015 at 23:11
  • Validating properties at compile time doesn't make sense to me. If your properties wouldn't change since compilation, why externalize them at all?
    – luboskrnac
    Commented Dec 4, 2015 at 9:50
  • A lot of modern cloud envs strongly recommend this: 12factor.net/config. That is why compile time validation doesn't make sense.
    – luboskrnac
    Commented Dec 4, 2015 at 9:52
1

The annotation processor automatically considers inner classes as nested properties. Make sure you have getters and setters defined.

@ConfigurationProperties(prefix="server")
public class ServerProperties {

    private String name;

    private Host host;

    // ... getter and setters !!!

    public static class Host {

        private String ip;

        private int port;

        // ... getter and setters !!!

    }

}

The same effect can be achieved with non-inner class but you should use the @NestedConfigurationProperty annotation on a field to indicate that a regular (non-inner) class should be treated as if it were nested.

@ConfigurationProperties(prefix="server")
public class ServerProperties {

    private String name;

    @NestedConfigurationProperty
    private Host host;

    // ... getter and setters !!!

}

public class Host {

    private String ip;

    private int port;

    // ... getter and setters

}

Not the answer you're looking for? Browse other questions tagged or ask your own question.