Fabry
Fabry

Reputation: 1650

SpringBoot Failed to bind properties under app

I have a SpringBoot 2.1.7.RELEASE project with gradle. I'm getting an error when I try to use @ConfigurationProperties

The property that I'm trying to bind is existing in my application-default.properties and if I run the project using Itellij I can see that the property is ingested in my component.

If I enable @EnableConfigurationProperties I got an error.

My application-default.properties

app.forwarding-endpoint=localhost:8080

My AppProperties.java

@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
@Validated
@Data
public class AppProperties {
   @NotBlank
   @Pattern(regexp = "^(.+):\\d+$")
   private String forwardingEndpoint;
}

My Application.java

@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class Application {
  public static void main(String[] args) {
      SpringApplication.run(Application .class, args);
  }
}

My component that is using the property:

 public MyComponent(@Value("${app.forwarding-endpoint}") String forwardingEndpoint) {
    log.info("Forwarding endpoint {}", forwardingEndpoint);
 }

The error that I get is:

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'app' to com.config.AppProperties failed:

Property: app.forwardingEndpoint
Value: null
Reason: must not be blank

What am I missing?

Upvotes: 6

Views: 64150

Answers (1)

Dmitry Ionash
Dmitry Ionash

Reputation: 821

The cause is in the order of initialization. You did not fill AppProperties but start to use it in components. You need to annotate this class also as a component but it's not a good approach from point of view of an architecture.

The concept of @ConfigurationProperties is quite raw for Spring and without some manipulations, you will quite difficult to force it to work correctly. I propose a simple 'trick' (or 'another approach'):

@Data
public class AppProperties {
   @NotBlank
   @Pattern(regexp = "^(.+):\\d+$")
   private String forwardingEndpoint;
}

(I think the place of @validated is not in the entitity/DO).

And place in your @Configuration next code:

@Bean
@ConfigurationProperties(prefix = "app", ignoreUnknownFields = false)
public AppProperties setAppProperties() {
    return new AppProperties();
}

And next, you can inject AppProperties bean in any component.

Upvotes: 4

Related Questions