Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring configuration properties recursive type

I am trying to create a configuration properties class that has a recursive class, structured similarly to a linked list. I'm using Spring boot 2.0.6.RELEASE, and the class is being autowired using @EnableConfigurationProperties({EnginealConfig.class}).

The issue I am having is that only one the first level will be bound to the Test object, x.test will never get set.

Using the following application.properties file:

engineal.x.value: "Test1"
engineal.x.test.value: "Test2"
engineal.x.test.test.value: "Test3"

And the following configuration properties class:

@ConfigurationProperties(prefix = "engineal")
public class EnginealConfig {

    static class Test {

        private String value;
        private Test test;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public Test getTest() {
            return test;
        }

        public void setTest(Test test) {
            this.test = test;
        }

        @Override
        public String toString() {
            return "Test{" +
                    "value='" + value + '\'' +
                    ", test=" + test +
                    '}';
        }
    }

    private Test x;

    public Test getX() {
        return x;
    }

    public void setX(Test x) {
        this.x = x;
    }

    @Override
    public String toString() {
        return "EnginealConfig{" +
                "x=" + x +
                '}';
    }
}

the object will print EnginealConfig{x=Test{value='Test1', test=null}}. Unfortunately the recursion is not working.

After messing around trying different things to get this to work, I tried changing EnginealConfig#Test.test from private Test test; to private List<Test> test;, along with the getters and setters. Then by using lists with one element, this recursion works.

The following application.properties with the List<Test> change:

engineal.x.value: "Test1"
engineal.x.test[0].value: "Test2"
engineal.x.test[0].test[0].value: "Test3"

will output EnginealConfig{x=Test{value='Test1', test=[Test{value='Test2', test=[Test{value='Test3', test=null}]}]}}. I can then access the next element by using test.get(0).

So it appears as if recursion is supported only if the recursive type is in a collection.

While this workaround is ok, I would prefer to use my first way of doing it. Are/should recursive classes be supported without needing a collection? Thank you for your help!

like image 543
engineAL Avatar asked Oct 20 '18 14:10

engineAL


People also ask

What is @configuration in spring boot?

Spring @Configuration annotation is part of the spring core framework. Spring Configuration annotation 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.

What is the use of @ConfigurationProperties?

@ConfigurationProperties provides validation of properties using the JSR-303 format. This allows all sorts of neat things.

Where should spring properties be placed?

properties in default location. Spring Boot loads the application. properties file automatically from the project classpath. All you have to do is to create a new file under the src/main/resources directory.


1 Answers

Just set your inner class as an individual class, then everything would work well.

application.yml

simple:
  value: aa
  myTest:
    value: lower

config class

@ConfigurationProperties(prefix = "simple")
@Data //It is for getter setter
public class SimpleConfig {

    private String value;

    private MyTest myTest;
}

the recursion class

@Data
public class MyTest {
    private String value;
    private MyTest myTest;
}

Test case

@Resource
private SimpleConfig simpleConfig;

@Test
public void myTest(){

    String value = simpleConfig.getValue();
    System.out.println("outerValue : " + value);
    String innerValue = simpleConfig.getMyTest().getValue();
    System.out.println("innerValue :" + innerValue);
}

result

outerValue : aa
innerValue :lower
like image 77
wl.GIG Avatar answered Sep 19 '22 12:09

wl.GIG