Skip to content

Nested object is not initialized if no matching property is defined with constructor binding #18917

@snicoll

Description

@snicoll

Consider the following example:

@ConfigurationProperties("acme")
@ConstructorBinding
public class AcmeProperties {

	private final Security security;

	public AcmeProperties(Security security) {
		this.security = security;
	}

	public Security getSecurity() {
		return this.security;
	}

	public static class Security {

		private final String username;

		private final String password;

		public Security(@DefaultValue("user") String username, String password) {
			this.username = username;
			this.password = password;
		}

		public String getUsername() {
			return this.username;
		}

		public String getPassword() {
			return this.password;
		}
	}
}

If this object is bound and no acme.security.* property is available in the environment, null is provided to the top-level constructor. If a matching property is found, the Security type is initialized and provided to the constructor.

This is consistent with what we do with JavaBean binding. The main difference here is that the object may have default values assigned to the constructor (here a default user). One solution would be to provide an instance no matter what. The alternative is for the user to check if the constructor provided a null instance and then create a default Security.

There are pros and cons for each:

  • If we create a default instance no matter what, we no longer have the signal that the user didn't provide any key for that nested Security object
  • If we don't care about that, we have to check for null and then create an instance with a copy paste of the @DefaultValue we already provided.

A middle-ground would be to make this configurable, perhaps using @Nullable as we do for actuator endpoints.

Metadata

Metadata

Assignees

Labels

status: noteworthyA noteworthy issue to call out in the release notestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions