Spring version: 5.3.6 JDK: 16.0.1
It seems that spring-context-indexer library doesn't support Java records. If I declare a record as Spring bean:
@Component
public record ServiceManager() {}
then META-INF/spring.components doesn't contain entry for this type. And Spring fails to load it during startup. I looked into source code and the following blocks seem to responsible for that:
CandidateComponentsIndexer:
private static final Set<ElementKind> TYPE_KINDS =
Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS, ElementKind.INTERFACE));
IndexedStereotypesProvider:
@Override
public Set<String> getStereotypes(Element element) {
Set<String> stereotypes = new LinkedHashSet<>();
ElementKind kind = element.getKind();
if (kind != ElementKind.CLASS && kind != ElementKind.INTERFACE) {
return stereotypes;
}
Comment From: jhoeller
I wonder why you would want to declare a record as a Spring-managed bean to begin with? Our notion of a "managed bean" seems strongly bound to traditional object semantics, including instance identity and access to delegates. Are records ever a good fit there?
Now, if you're arguing that this is a mismatch between the indexer and runtime component scanning, we should indeed align the behavior there. Even if not a recommended choice of component type, consistently detecting annotated record classes is certainly better than inconsistent runtime behavior.
Comment From: jhoeller
I've locally refined those checks to (element.getKind().isClass() || element.getKind() == ElementKind.INTERFACE)
which seems generally sensible and implicitly includes records as well as enum types (even if the latter are not a typical managed bean choice either).
Comment From: sergey-morenets
@jhoeller Thank you for the quick response.
I guess Java records is rather new feature (which was declared stable only in JDK 16) so there' no so much best practices around it. What surprised me is that I can register Java record as Spring bean without spring-context-indexer but unable to register if I turn on spring-context-indexer.
Comment From: sergey-morenets
So I will understand if you remove Java records support at all. But it looks like inconsistent behavior now.