Skip to content

Missing metadata when using @Name with a constructor-bound property #46599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

prishedko
Copy link

Hello,

I'd like to suggest a fix for a bug that I've found while using @Name annotation with Type-safe Configuration Properties.

Problem description

When @Name annotation is used, the metadata items extracted from executable elements (like description and deprecation data) are missing. The following example demonstrates it:

Let's say we have record like this:

/**
 * @param namedPropertyExample this should be in the metadata description.
 */
@ConfigurationProperties(prefix = "example.properties")
public record ExampleProperties(
        @Deprecated
        @DeprecatedConfigurationProperty(reason = "Some reason")
        String namedPropertyExample) {}

Then it's generated metadata is:

{
  "groups": [
    {
      "name": "example.properties",
      "type": "org.some.example.ExampleProperties",
      "sourceType": "org.some.example.ExampleProperties"
    }
  ],
  "properties": [
    {
      "name": "example.properties.named-property-example",
      "type": "java.lang.String",
      "description": "this should be in the metadata description.",
      "sourceType": "org.some.example.ExampleProperties",
      "deprecated": true,
      "deprecation": {
        "reason": "Some reason"
      }
    }
  ],
  "hints": [],
  "ignored": {
    "properties": []
  }
}

But if @Name annotation is added:

/**
 * @param namedPropertyExample this should be in the metadata description.
 */
@ConfigurationProperties(prefix = "example.properties")
public record ExampleProperties(
        @Name("named.property")
        @Deprecated
        @DeprecatedConfigurationProperty(reason = "Some reason")
        String namedPropertyExample) {}

the metadata misses several attributes:

{
  "groups": [
    {
      "name": "example.properties",
      "type": "org.some.example.ExampleProperties",
      "sourceType": "org.some.example.ExampleProperties"
    }
  ],
  "properties": [
    {
      "name": "example.properties.named.property",
      "type": "java.lang.String",
      "sourceType": "org.some.example.ExampleProperties"
    }
  ],
  "hints": [],
  "ignored": {
    "properties": []
  }
}

Root cause and the fix descriptions

The root cause is the using Name#value for locating executable elements in org.springframework.boot.configurationprocessor.PropertyDescriptorResolver#extracted:

		String name = getPropertyName(parameter);
		TypeMirror type = parameter.asType();
		ExecutableElement getter = members.getPublicGetter(name, type);
		ExecutableElement setter = members.getPublicSetter(name, type);
		VariableElement field = members.getFields().get(name);
		RecordComponentElement recordComponent = members.getRecordComponents().get(name);

...

	private String getPropertyName(VariableElement parameter) {
		return getPropertyName(parameter, parameter.getSimpleName().toString());
	}

	private String getPropertyName(VariableElement parameter, String fallback) {
		AnnotationMirror nameAnnotation = this.environment.getNameAnnotation(parameter);
		if (nameAnnotation != null) {
			return this.environment.getAnnotationElementStringValue(nameAnnotation, "value");
		}
		return fallback;
	}

For the example above it means searching record component with name named.property. I'd like to suggest using parameter name for locating the executable elements:

		String parameterName = parameter.getSimpleName().toString();
		TypeMirror type = parameter.asType();
		ExecutableElement getter = members.getPublicGetter(parameterName, type);
		ExecutableElement setter = members.getPublicSetter(parameterName, type);
		VariableElement field = members.getFields().get(parameterName);
		RecordComponentElement recordComponent = members.getRecordComponents().get(parameterName);

When @name annotation is used on a property, metadata like javadoc and deprecation are not extracted. The root cause is that @Name.value is used for locating corresponding code element, and it can find something only @Name.value is the same as the code element name. This commit fixes the root cause.

Signed-off-by: Bohdan Pryshedko <[email protected]>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 30, 2025
@wilkinsona wilkinsona changed the title Using @Name annotation leads to a missed items in metadata. Missing metadata when using @Name with a constructor-bound property Jul 31, 2025
@wilkinsona wilkinsona added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 31, 2025
@wilkinsona wilkinsona added this to the 3.4.x milestone Jul 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants