Skip to content

Commit b55a4d3

Browse files
committed
Prevent AOT from failing with spring-orm without JPA
This commit improves PersistenceManagedTypesBeanRegistrationAotProcessor so that it does not attempt to load JPA classes when checking for the presence of a PersistenceManagedTypes bean. To make it more clear a check on the presence for JPA has been added to prevent the nested classes to be loaded regardless of the presence of the bean. Closes gh-32155
1 parent db53586 commit b55a4d3

File tree

1 file changed

+31
-26
lines changed

1 file changed

+31
-26
lines changed

Diff for: spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java

+31-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -67,42 +67,34 @@
6767
@SuppressWarnings("unchecked")
6868
class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
6969

70-
private static final List<Class<? extends Annotation>> CALLBACK_TYPES = List.of(PreUpdate.class,
71-
PostUpdate.class, PrePersist.class, PostPersist.class, PreRemove.class, PostRemove.class, PostLoad.class);
72-
73-
@Nullable
74-
private static Class<? extends Annotation> embeddableInstantiatorClass;
75-
76-
static {
77-
try {
78-
embeddableInstantiatorClass = (Class<? extends Annotation>) ClassUtils.forName("org.hibernate.annotations.EmbeddableInstantiator",
79-
PersistenceManagedTypesBeanRegistrationAotProcessor.class.getClassLoader());
80-
}
81-
catch (ClassNotFoundException ex) {
82-
embeddableInstantiatorClass = null;
83-
}
84-
}
85-
70+
private static final boolean jpaPresent = ClassUtils.isPresent("jakarta.persistence.Entity",
71+
PersistenceManagedTypesBeanRegistrationAotProcessor.class.getClassLoader());
8672

8773
@Nullable
8874
@Override
8975
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
90-
if (PersistenceManagedTypes.class.isAssignableFrom(registeredBean.getBeanClass())) {
91-
return BeanRegistrationAotContribution.withCustomCodeFragments(codeFragments ->
92-
new JpaManagedTypesBeanRegistrationCodeFragments(codeFragments, registeredBean));
76+
if (jpaPresent) {
77+
if (PersistenceManagedTypes.class.isAssignableFrom(registeredBean.getBeanClass())) {
78+
return BeanRegistrationAotContribution.withCustomCodeFragments(codeFragments ->
79+
new JpaManagedTypesBeanRegistrationCodeFragments(codeFragments, registeredBean));
80+
}
9381
}
9482
return null;
9583
}
9684

97-
private static class JpaManagedTypesBeanRegistrationCodeFragments extends BeanRegistrationCodeFragmentsDecorator {
85+
private static final class JpaManagedTypesBeanRegistrationCodeFragments extends BeanRegistrationCodeFragmentsDecorator {
86+
87+
private static final List<Class<? extends Annotation>> CALLBACK_TYPES = List.of(PreUpdate.class,
88+
PostUpdate.class, PrePersist.class, PostPersist.class, PreRemove.class, PostRemove.class, PostLoad.class);
89+
9890

9991
private static final ParameterizedTypeName LIST_OF_STRINGS_TYPE = ParameterizedTypeName.get(List.class, String.class);
10092

10193
private final RegisteredBean registeredBean;
10294

10395
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
10496

105-
public JpaManagedTypesBeanRegistrationCodeFragments(BeanRegistrationCodeFragments codeFragments,
97+
private JpaManagedTypesBeanRegistrationCodeFragments(BeanRegistrationCodeFragments codeFragments,
10698
RegisteredBean registeredBean) {
10799
super(codeFragments);
108100
this.registeredBean = registeredBean;
@@ -114,7 +106,8 @@ public CodeBlock generateInstanceSupplierCode(GenerationContext generationContex
114106
boolean allowDirectSupplierShortcut) {
115107
PersistenceManagedTypes persistenceManagedTypes = this.registeredBean.getBeanFactory()
116108
.getBean(this.registeredBean.getBeanName(), PersistenceManagedTypes.class);
117-
contributeHints(generationContext.getRuntimeHints(), persistenceManagedTypes.getManagedClassNames());
109+
contributeHints(generationContext.getRuntimeHints(),
110+
this.registeredBean.getBeanFactory().getBeanClassLoader(), persistenceManagedTypes.getManagedClassNames());
118111
GeneratedMethod generatedMethod = beanRegistrationCode.getMethods()
119112
.add("getInstance", method -> {
120113
Class<?> beanType = PersistenceManagedTypes.class;
@@ -135,7 +128,7 @@ private CodeBlock toCodeBlock(List<String> values) {
135128
return CodeBlock.join(values.stream().map(value -> CodeBlock.of("$S", value)).toList(), ", ");
136129
}
137130

138-
private void contributeHints(RuntimeHints hints, List<String> managedClassNames) {
131+
private void contributeHints(RuntimeHints hints, @Nullable ClassLoader classLoader, List<String> managedClassNames) {
139132
for (String managedClassName : managedClassNames) {
140133
try {
141134
Class<?> managedClass = ClassUtils.forName(managedClassName, null);
@@ -144,7 +137,7 @@ private void contributeHints(RuntimeHints hints, List<String> managedClassNames)
144137
contributeIdClassHints(hints, managedClass);
145138
contributeConverterHints(hints, managedClass);
146139
contributeCallbackHints(hints, managedClass);
147-
contributeHibernateHints(hints, managedClass);
140+
contributeHibernateHints(hints, classLoader, managedClass);
148141
}
149142
catch (ClassNotFoundException ex) {
150143
throw new IllegalArgumentException("Failed to instantiate the managed class: " + managedClassName, ex);
@@ -194,7 +187,8 @@ private void contributeCallbackHints(RuntimeHints hints, Class<?> managedClass)
194187
}
195188

196189
@SuppressWarnings("unchecked")
197-
private void contributeHibernateHints(RuntimeHints hints, Class<?> managedClass) {
190+
private void contributeHibernateHints(RuntimeHints hints, @Nullable ClassLoader classLoader, Class<?> managedClass) {
191+
Class<? extends Annotation> embeddableInstantiatorClass = loadEmbeddableInstantiatorClass(classLoader);
198192
if (embeddableInstantiatorClass == null) {
199193
return;
200194
}
@@ -216,5 +210,16 @@ private void registerInstantiatorForReflection(ReflectionHints reflection, @Null
216210
Class<?> embeddableInstantiatorClass = (Class<?>) AnnotationUtils.getAnnotationAttributes(annotation).get("value");
217211
reflection.registerType(embeddableInstantiatorClass, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
218212
}
213+
214+
@Nullable
215+
private static Class<? extends Annotation> loadEmbeddableInstantiatorClass(@Nullable ClassLoader classLoader) {
216+
try {
217+
return (Class<? extends Annotation>) ClassUtils.forName(
218+
"org.hibernate.annotations.EmbeddableInstantiator", classLoader);
219+
}
220+
catch (ClassNotFoundException ex) {
221+
return null;
222+
}
223+
}
219224
}
220225
}

0 commit comments

Comments
 (0)