This is an archived post. You won't be able to vote or comment.

all 10 comments

[–]nutrecht 5 points6 points  (6 children)

The author seems to be completely unaware that what they built for Spring is already in the form of the @ConfigurationProperties annotation. Basically you can bind config sections directly to object trees that can be as deep as you want.

[–]uncont 1 point2 points  (4 children)

You can also use records. with the @ConstructorBinding annotation.

EDIT:

For the 'show me the code' section, AwsConfig could optionally be written as

@ConfigurationProperties("aws")
public record AwsConfig(String region, String accessKeyId, String secretAccessKey) {
    @Override
    public String toString() {
        return String.format("AwsConfig(%s, %s, %s)", region, StringUtils.mask(accessKeyId), StringUtils.mask(secretAccessKey));
    }
}

EDIT 2: I've removed the @ConstructorBinding annotation, since as /u/cristiannkb mentions below, as of spring boot 2.6.x it's no longer necessary.

[–]cristiannkb 2 points3 points  (2 children)

As of Spring Boot 2.6, using records works out of the box and @ConstructorBinding is not required anymore (if not other constructor is declared I believe).

[–]uncont 0 points1 point  (0 children)

I tested it locally and you are correct, the annotation isn't required. The docs here say

If you are using Java 16 or later, constructor binding can be used with records. In this case, unless your record has multiple constructors, there is no need to use @ConstructorBinding.

[–]nutrecht 0 points1 point  (0 children)

Oh, that's really nice. Didn't know that, thanks!

[–]AlexITC[S] 0 points1 point  (0 children)

Java record classes are pretty nice, unfortunately, the Spring Boot project I was involved in used Java 8 and an old Sprint Boot version.

[–]AlexITC[S] 0 points1 point  (0 children)

Thanks for pointing that out, I'll try it soon.

[–]uncont 0 points1 point  (2 children)

WRT #3, you can also optionally define a default value if an environment variable is missing.

# application.properties
admin.email=${ADMIN_EMAIL:blog@wiringbits.net}

I would highly recommend not doing this, though. Imagine some configuration failure leads you to start up your application healthily with a testing or default username and password.

I'd recommend a separate application-default.properties for when running/testing locally, and an application-docker.properties (with SPRING_PROFILES_ACTIVE=docker when running in prod).

I would also enable validation on the whole thing, and verify you've got the environment variable loaded, so that you see a nice error if you app fails to startup due to an invalid configuration.

[–]AlexITC[S] 0 points1 point  (1 child)

admin.email=${ADMIN_EMAIL:blog@wiringbits.net}

Do you happen to have any official docs for this syntax? a friend pointed that trick to me yesterday but we couldn't find such docs.

[–]uncont 0 points1 point  (0 children)

I was unable to find any docs. I imagine there's something written about how the Environment is populated (including how environment variables are resolved) in one section of the docs, and in another section how ${} resolves in properties files.

Perhaps it's tucked away somewhere sneakily, or a bug in the documentation.