2

I'd like to have spring load some properties on startup and convert them into the proper types.

application.yml:

base:
  security:

    scopes:
      - name: read
        descripton: read some nice things

      - name: write
        description: write some nice things

    authorities:
      - name: ROLE_ADMIN
        scopes:
          - read
          - write

      - name: ROLE_USER
        scopes:
          - read 

To load these properties into types I used the following @ConfigurationProperties: BaseProperties.java

@Setter
@Getter
@Configuration
@ConfigurationProperties(prefix="base.security")
public class BaseProperties {

    private Set<ScopeProperty> scopes = new HashSet<>();
    private Set<AuthorityProperty> authorities = new HashSet<>();

    @Getter
    @Setter
    public class AuthorityProperty {
        private String name;
        private List<String> scopes;
    }

    @Getter
    @Setter
    public class ScopeProperty {
        private String name;
        private String description;
    }
}

Everything I get is a BindException as follows:

Caused by: org.springframework.boot.context.properties.bind.UnboundConfigurationPropertiesException: The elements [base.security.authorities[0].name,base.security.authorities[0].scopes[0],base.security.authorities[0].scopes[1],base.security.authorities[1].name,base.security.authorities[1].scopes[0]] were left unbound.
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.assertNoUnboundChildren(IndexedElementsBinder.java:136)
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:113)
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:86)
    at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:71)
    at org.springframework.boot.context.properties.bind.CollectionBinder.bindAggregate(CollectionBinder.java:49)
    at org.springframework.boot.context.properties.bind.AggregateBinder.bind(AggregateBinder.java:56)
    at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$2(Binder.java:293)
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:429)
    at org.springframework.boot.context.properties.bind.Binder$Context.access$100(Binder.java:372)
    at org.springframework.boot.context.properties.bind.Binder.bindAggregate(Binder.java:293)
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:254)
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:214)

solution:

Either mark the classes as static or create them as seperate classes:

    @Getter
    @Setter
    public static class AuthorityProperty {
        private String name;
        private List<String> scopes;
    }

    @Getter
    @Setter
    public static class ScopeProperty {
        private String name;
        private String description;
    }
Chris
  • 566
  • 1
  • 8
  • 20
  • 1
    Use Delombok to avoid similar issues in the future :) – Nikolas Charalambidis Dec 21 '19 at 21:54
  • @Nikolas why one would use Lombok in 2020? Yes, in 2012 it was cool, but now we have Kotlin, anyway the problem was in class hierarchy not in the properties – Boris Treukhov Dec 21 '19 at 21:58
  • even without lombok it's not working, same exception – Chris Dec 21 '19 at 22:01
  • @BorisTreukhov: I said "similar", not "exact". I haven't check the root of the problem but raised a hint. The probem might be or might not be related to Lombok, I don't know. The author have tried to run it even without Lombok which implies there exists a *possibility* Lombok causes a problem hidden behind. Yet, it still doesn't work even without it is a whole different story. – Nikolas Charalambidis Dec 21 '19 at 22:08
  • 1
    thanks to you both then :-) I've lost some hours on this issue. :-D – Chris Dec 21 '19 at 22:12

2 Answers2

1

Your classes are inner classes which require an instance of outer class BaseProperties to be constructed, which is not supported by Spring Properties.

You can mark your classes with keyword static which is supposed to work

@Getter
@Setter
public static class AuthorityProperty {
    private String name;
    private List<String> scopes;
}
Boris Treukhov
  • 17,493
  • 9
  • 70
  • 91
0

i've just figured out the cause of this issue. It seems, spring can't process this with inner classes declaring the type for the Property Sets. I extracted the classes into separate ones and no it works.

Chris
  • 566
  • 1
  • 8
  • 20
  • great, that works. Thank you. And even with lombok. Can you please post it as response, then I'll mark it as solved. – Chris Dec 21 '19 at 22:05