Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prefix for nested configuration properties in spring

Spring boot 2.0.0.RELEASE

I have properties class:

@Configuration
@ConfigurationProperties(prefix="person")
public class PersonProperties {

    private AddressProperties addressProperties;

    public AddressProperties getAddressProperties() {
        return addressProperties;
    }

    public void setAddressProperties(final AddressProperties addressProperties) {
        this.addressProperties = addressProperties;
    }

    public static class AddressProperties {

        private String line1;

        public String getLine1() {
            return line1;
        }

        public void setLine1(final String line1) {
            this.line1 = line1;
        }
    }

}

And application.yml:

person:
  address:
    line1: line1OfAddress

It is not binding properly as my AddressProperties object is null. When a class has the same name as yml properties AddressProperties -> Address it is working well. I tried to add Qualifier or ConfigurationProperties with a prefix address but it is not working. Unfortunately, I cannot find useful information about this case in spring docs.

How to specify a prefix for nested properties?

like image 686
ByeBye Avatar asked May 15 '18 08:05

ByeBye


People also ask

What is prefix in @ConfigurationProperties?

@ConfigurationProperties works best with hierarchical properties that all have the same prefix; therefore, we add a prefix of mail. The Spring framework uses standard Java bean setters, so we must declare setters for each of the properties.

What is @configuration spring boot?

One of the most important annotations in spring is @Configuration annotation which indicates that the class has @Bean definition methods. So Spring container can process the class and generate Spring Beans to be used in the application. This annotation is part of the spring core framework.

What is @value annotation in spring?

Spring @Value annotation is used to assign default values to variables and method arguments. We can read spring environment variables as well as system variables using @Value annotation. Spring @Value annotation also supports SpEL.

What does @configuration do in spring?

@Configuration annotation indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.


2 Answers

Property defined in yaml / property file should match with the variables defined in class. Either change yaml file as

person:
  # addressProperties will also work here
  address-properties:
    line1: line1OfAddress

Or define your bean as

@Configuration
@ConfigurationProperties(prefix = "person")
public class PersonProperties {

    // here variable name doesn't matter, it can be addressProperties as well
    // setter / getter should match with properties in yaml
    // i.e. getAddress() and setAddress()
    private AddressProperties address;

    public AddressProperties getAddress() {
        return address;
    }

    public void setAddress(AddressProperties address) {
        this.address = address;
    }
}

If you want to get all properties under address without defining them in separate bean you can define your PersonProperties class as

@Configuration
@ConfigurationProperties(prefix = "person")
public class PersonProperties {

    private Map<String, Object> address;

    public Map<String, Object> getAddress() {
        return address;
    }

    public void setAddress(Map<String, Object> address) {
        this.address = address;
    }
}

Here PersonProperties#address will contain {line1=line1OfAddress}

Now All properties under address will be in the Map.

like image 104
Pratapi Hemant Patel Avatar answered Nov 06 '22 17:11

Pratapi Hemant Patel


You could simply un-nest the two classes, allowing each to have it's own prefix. First class:

@Configuration
@ConfigurationProperties(prefix="person")
public class PersonProperties {

    private AddressProperties addressProperties;

    public AddressProperties getAddressProperties() {
        return addressProperties;
    }

    public void setAddressProperties(final AddressProperties addressProperties) {
        this.addressProperties = addressProperties;
    }
}

Second class:

@Configuration
@ConfigurationProperties(prefix="person.address")
public class PersonAddressProperties {

    private String line1;

    public String getLine1() {
        return line1;
    }

    public void setLine1(final String line1) {
        this.line1 = line1;
    }
}

Edit: As was pointed out in the comments, you'd have to inject both of these classes if one block of code needed to refer to both sets of properties.

like image 45
Bampfer Avatar answered Nov 06 '22 16:11

Bampfer