Spring Checked Boot 1.5 ConfigurationProperties

Go to the ground for motivating and solving the problem!

During the upgrade from Spring Boot 1.4

to 1.5

I read (source: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes#upgrading-from-spring-boot-14 )

If you have @ConfigurationProperties classes that use JSR-303 constraint annotations, you must now additionally annotate them with @Validated. The currently existing check will continue, however a warning will be logged. In the future, classes without @Validated will not be validated at all.

So, diligently, I add @Validated

to all the properties of my configuration. Now I have a specific use case that breaks, otherwise the property is not loaded anymore (I generalize first and then add code).

If I use a template property defined in the file application.properties

and then try to override the value for certain profiles, then the application won't start.

Here is some sample code to play (related files):

build.gradle

buildscript {
    ext {
        springBootVersion = '1.5.1.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

      

application.properties

: demo.prop=${profile.prop}

application-demo.properties

: profile.prop=demo

DemoApplication.java

package package;

import javax.validation.constraints.NotNull;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @org.springframework.web.bind.annotation.RestController
    public static class RestController {

        @Autowired
        private DemoProperties properties;

        @GetMapping
        public String get() {
            return properties.prop == null ? "null" : properties.prop;
        }
    }

    @Component
    @ConfigurationProperties(prefix = "demo")
//  @Validated
    public static class DemoProperties {

        @NotNull
        private String prop;

        public void setProp(String prop) {
            this.prop = prop;
        }

        public String getProp() {
            return prop;
        }
    }
}

      

In a way, my application outputs the expected output when run with -Dspring.profiles.active=demo

curl "http://localhost:8080"
demo

      

however, uncommenting //@validated

and running the application, as before, will produce

curl "http://localhost:8080"
null

      

The complete app is available at https://github.com/ThanksForAllTheFish/boot-props (including a test case showing that the definition profile.prop

in config/application.properties

also does not work with @Validated

but succeeds without).

I am guessing this is a bug in Spring Boot, but it may not be clear to me, so SoF first (as hinted at in Spring Boot Issue Manager on github).

This github issue seems to be related: https://github.com/spring-projects/spring-boot/issues/8173

+3


source to share


1 answer


As I found a solution to my problem (some time ago, but added as an explanation in the question itself), I figured it might be more helpful to copy my results here.

The problem with my example code is that it @Validated

wraps the real class with a proxy so that validation questions can be injected, so return is properties.prop == null ? "null" : properties.prop;

actually trying to access the prop

proxy field . Switching to getProp () is the fix. It's pretty obvious that one day it came to light.



As for the production code: the issue was related to https://github.com/spring-projects/spring-boot/issues/8173 , more specifically https://github.com/spring-cloud/spring-cloud-commons/ issues / 177 as we are using spring-cloud. Basically, BeanPostProcessor

there was a conflict between spring-cloud

and spring-boot

(details in the ticket on github), which was resolved in Dalston.RELEASE

of spring-cloud

. Just updating the dependency in our project solved the issue in production as well. Lots of digging and testing just to change the 7 characters in our codebase.

+1


source







All Articles