7
votes

I have a problem similar to that described in Mapping list in Yaml to list of objects in Spring Boot except that I would like to vary the identifier of least one of the fields in my object from the corresponding key name used in YAML.

For example:

YAML File:

config:
    gateways:
        -
            id: 'g0'
            nbrInputs: 128
            nbrOutputs: 128
        -
            id: 'g1'
            nbrInputs: 128
            nbrOutputs: 128

Configuration Class:

@Configuration
@ConfigurationProperties(prefix="config")
public class GatewayConfig
{
    List<Gateway> gateways = new ArrayList<Gateway>();

    // Getter/Setter for gateways
    // ...

    public static class Gateway
    {
        private String id;

        @Value("${nbrInputs}")
        private int numInputs;

        @Value("${nbrOutputs}")
        private int numOutputs;

        // Getters and Setters
        // ...
    }
}

I was hoping that the @Value annotations would allow me to inject the corresponding property values, but this does not seem to work (injection of the 'id' field seems to work just fine).

Is there a way to do this with @Value (or any other annotation)?

Thank you.


Edit: Note that I am looking to determine whether I can force a correspondence between a YAML property and a field in the inner POJO without changing the name of either. There are several reasons why I might want to do this - e.g. I might not control the format of the YAML file and I would like to use a more descriptive identifier name in my POJO than was used by the author of the YAML file.

1
You don't need the @Value at all. Nested objects are taken into account automatically. Remove @Value and add getter/setter for num****Stephane Nicoll
Thank you for your quick response, Mr. Nicoll. I already have getters and setters for numInputs and numOutputs. What I cannot figure out is how to cause the value of 'nbrInputs' from the YAML file to get injected into 'numInputs' in the object (and 'nbrOutputs' into 'numOutputs'). I could, of course, change the fields in the Gateway class to 'nbrInputs' and 'nbrOutputs', but I am interested in knowing whether I can make it work without doing so. Thank you.Brandon E Taylor
No, you can't do that. The primary purpose of @ConfigurationProperties is to bind the environment to an object model, there is no "translation in between". Having said that, nobody prevents you from creating such object yourself and translate it to the "real" type.Stephane Nicoll

1 Answers

9
votes

As Stephave Nicoll mentioned, @Value annotation has nothing to do with @ConfigurationProperties. Just name fields in the inner POJO same as in configuration file and this should work:

@Configuration
@ConfigurationProperties(prefix="config")
@EnableConfigurationProperties
public class GatewayConfig
{
    List<Gateway> gateways = new ArrayList<Gateway>();

    // Getter/Setter for gateways
    // ...

    public static class Gateway
    {
        private String id;
        private int nbrInputs;
        private int nbrOutputs;

        // Getters and Setters
        // ...
    }
}

Reaction on comment:

With plain Spring/Spring Boot, I don't think you can map fields with different names and load it to the list of gateways. There would be option to use plain @Value annotation, but your gateway count would need to be hard-coded:

@Component
public class Gateway0{
    @Value("${config.gateways[0].id}")
    private String id;

    @Value("${config.gateways[0].nbrInputs}")
    private int numInputs;

    @Value("${config.gateways[0].nbrOutputs}")
    private int numOutputs;

    // Getters and Setters
    // ...
}