ByeBye
ByeBye

Reputation: 6946

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?

Upvotes: 11

Views: 18994

Answers (2)

Bampfer
Bampfer

Reputation: 2220

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.

Upvotes: 1

Hemant Patel
Hemant Patel

Reputation: 3260

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.

Upvotes: 3

Related Questions