Skip to content

Binding fails in presence of a synthetic constructor #18670

Closed
@kazuki43zoo

Description

@kazuki43zoo

There are cases that configuration property binding does not work when integrating 3rd party configuration class and it deploy to the application server as war file(= When JndiPropertySource is enabled).

Versions

  • 2.2.0.RELEASE(2.2.0.M5+) ※2.2.0.M4 work fine

Details

For example, following properties class does not work. (As actually, MyBatis's configuration class matches this pattern...)

package com.example;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

@ConfigurationProperties(prefix = "my")
public class MyProperties {

  private String name;

  @NestedConfigurationProperty
  private ThirdPartyConfiguration configuration; // ### Third party class

  public void setName(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setConfiguration(ThirdPartyConfiguration configuration) {
    this.configuration = configuration;
  }

  public ThirdPartyConfiguration getConfiguration() {
    return configuration;
  }

}
package com.example;

public class ThirdPartyConfiguration {

  private String encoding;

  private boolean enabled;

  private final List<ResultMap> resultMaps = new ArrayList<>(); // ### Collection

  public void setEncoding(String encoding) {
    this.encoding = encoding;
  }

  public String getEncoding() {
    return encoding;
  }

  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }

  public boolean isEnabled() {
    return enabled;
  }

  public Collection<ResultMap> getResultMaps() {
    return resultMaps;
  }

  public void addResultMap(ResultMap rm) {
    resultMaps.add(rm);
  }

}
package com.example;

public class ResultMap {
  private String name;
  private String option;

  private ResultMap() { // ### Define private (If define public, this issue does not occurred)
  }

  public String getName() {
    return name;
  }

  public String getOption() {
    return option;
  }

  public static class Builder { // ### Builder class
    private final ResultMap resultMap;

    public Builder(String name) {
      resultMap = new ResultMap();
      resultMap.name = name;
    }

    public Builder option(String option) {
      resultMap.option = option;
      return this;
    }

    public ResultMap build() {
      return resultMap;
    }
  }
}

StackTrace

...
[INFO] [talledLocalContainer] Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'my.configuration.result-maps[0]' to com.example.ResultMap
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:337)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:297)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$null$1(Binder.java:385)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withSource(Binder.java:519)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.access$1000(Binder.java:486)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$2(Binder.java:386)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:106)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:86)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:71)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.CollectionBinder.bindAggregate(CollectionBinder.java:49)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.AggregateBinder.bind(AggregateBinder.java:56)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$3(Binder.java:388)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:543)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.access$200(Binder.java:486)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindAggregate(Binder.java:388)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:349)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:293)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:421)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:88)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:77)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:54)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:425)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:543)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:529)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.access$500(Binder.java:486)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:423)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:364)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:293)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:421)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:88)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:77)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:54)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:425)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:543)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:529)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.access$500(Binder.java:486)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:423)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:364)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:293)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:281)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:211)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:198)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:89)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:107)
[INFO] [talledLocalContainer]   ... 60 more
[INFO] [talledLocalContainer] Caused by: java.lang.IllegalStateException: Failed to extract parameter names for com.example.ResultMap(com.example.ResultMap$1)
[INFO] [talledLocalContainer]   at org.springframework.util.Assert.state(Assert.java:94)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.ValueObjectBinder$DefaultValueObject.parseConstructorParameters(ValueObjectBinder.java:178)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.ValueObjectBinder$DefaultValueObject.<init>(ValueObjectBinder.java:173)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.ValueObjectBinder$DefaultValueObject.get(ValueObjectBinder.java:218)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.ValueObjectBinder$DefaultValueObject.get(ValueObjectBinder.java:206)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.ValueObjectBinder$ValueObject.get(ValueObjectBinder.java:112)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.ValueObjectBinder.bind(ValueObjectBinder.java:51)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:425)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:543)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:529)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder$Context.access$500(Binder.java:486)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:423)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:364)
[INFO] [talledLocalContainer]   at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:293)

Related Issue

Reproduce project

How to reproduce

$ ./mvnw package corgo:run

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions