Skip to content

MetadataReader fails to read byte[] array from annotation #37083

Description

@gsruisch

Java version: 25.0.2
Spring version: 7.0.8

I am currently migrating one of my employer's applications to spring-boot 4, thereby over to spring-core 7.0.8, when I run in to the following regression:
Whenever their code attempts to load some byte array metadata from some annotation using spring-core's MetadataReader, it fails, where the same code has worked perfectly before.

Example code:

package com;

import org.springframework.core.type.classreading.MetadataReaderFactory;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;

@Example.TestAnnotation({1, 2, 3})
public class Example {
    @Retention(RetentionPolicy.RUNTIME)
    @interface TestAnnotation {
        byte[] value();
    }

    static void main() throws Exception {
        var factory = MetadataReaderFactory.create(Example.class.getClassLoader());
        var reader = factory.getMetadataReader(Example.class.getName());
        var mergedAnnotation = reader.getAnnotationMetadata()
                .getAnnotations()
                .get(TestAnnotation.class);
        byte[] expected = {1, 2, 3};
        /* Either:
        var actual = mergedAnnotation.synthesize().value();
        /*/// Alternatively:
        var actual = mergedAnnotation.getByteArray("value");
        //*/

        // Never reached, above always throws IllegalStateException
        assert Arrays.equals(actual, expected);
    }
}

Expected outcome:

  • The program runs to completion

Actual outcome:

Exception in thread "main" java.lang.IllegalStateException: Attribute 'value' in annotation com.Example$TestAnnotation should be compatible with [B but a [Ljava.lang.Byte; value was returned
	at org.springframework.core.annotation.TypeMappedAnnotation.adaptForAttribute(TypeMappedAnnotation.java:518)
	at org.springframework.core.annotation.TypeMappedAnnotation.adapt(TypeMappedAnnotation.java:447)
	at org.springframework.core.annotation.TypeMappedAnnotation.getValue(TypeMappedAnnotation.java:398)
	at org.springframework.core.annotation.TypeMappedAnnotation.getAttributeValue(TypeMappedAnnotation.java:380)
	at org.springframework.core.annotation.AbstractMergedAnnotation.getRequiredAttributeValue(AbstractMergedAnnotation.java:215)
	at org.springframework.core.annotation.AbstractMergedAnnotation.getByteArray(AbstractMergedAnnotation.java:63)
	at com.Example.main(Example.java:26)

To get my employer's application back up and running, I've come up with the following:

	byte[] actual;
	try {
		var source = mergedAnnotation.getSource();
		var accessor = source.getClass().getDeclaredMethod("annotation");
		accessor.setAccessible(true);
		var annotation = (Annotation) accessor.invoke(source);
		var data = (AnnotationValue.OfArray) annotation.elements().stream()
				.filter(element -> element.name().equalsString("value"))
				.map(AnnotationElement::value)
				.findAny()
				.orElseThrow();
		actual = new byte[data.values().size()];
		for (int i = 0; i < data.values().size(); i++) {
			actual[i] = ((AnnotationValue.OfByte)data.values().get(i)).byteValue();
		}
	} catch (Exception ex) {
		throw new IllegalStateException("Failed to reflectively read annotation data", ex);
	}

But as you can imagine, I'm very much looking forward to a less hair raising fix from You.

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions