Skip to content

Commit

Permalink
Register Hibernate @EmbeddableInstantiator reflection hints
Browse files Browse the repository at this point in the history
This commit updates PersistenceManagedTypesBeanRegistrationAotProcessor
to register reflection hints for `@EmbeddableInstantiator` annotations
available as of Hibernate 6.0 when needed.

Related tests will be added in
https://github.com/spring-projects/spring-aot-smoke-tests.

Closes gh-31534
  • Loading branch information
sdeleuze committed Nov 7, 2023
1 parent c30b379 commit 9d6bda2
Showing 1 changed file with 35 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import jakarta.persistence.Convert;
import jakarta.persistence.Converter;
import jakarta.persistence.Embedded;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.IdClass;
import jakarta.persistence.PostLoad;
Expand Down Expand Up @@ -64,11 +65,26 @@
* @author Sebastien Deleuze
* @since 6.0
*/
@SuppressWarnings("unchecked")
class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {

private static final List<Class<? extends Annotation>> CALLBACK_TYPES = List.of(PreUpdate.class,
PostUpdate.class, PrePersist.class, PostPersist.class, PreRemove.class, PostRemove.class, PostLoad.class);

@Nullable
private static Class<? extends Annotation> embeddableInstantiatorClass;

static {
try {
embeddableInstantiatorClass = (Class<? extends Annotation>) ClassUtils.forName("org.hibernate.annotations.EmbeddableInstantiator",
PersistenceManagedTypesBeanRegistrationAotProcessor.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
embeddableInstantiatorClass = null;
}
}


@Nullable
@Override
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
Expand Down Expand Up @@ -129,6 +145,7 @@ private void contributeHints(RuntimeHints hints, List<String> managedClassNames)
contributeIdClassHints(hints, managedClass);
contributeConverterHints(hints, managedClass);
contributeCallbackHints(hints, managedClass);
contributeHibernateHints(hints, managedClass);
}
catch (ClassNotFoundException ex) {
throw new IllegalArgumentException("Failed to instantiate the managed class: " + managedClassName, ex);
Expand Down Expand Up @@ -176,5 +193,23 @@ private void contributeCallbackHints(RuntimeHints hints, Class<?> managedClass)
reflection.registerMethod(method, ExecutableMode.INVOKE),
method -> CALLBACK_TYPES.stream().anyMatch(method::isAnnotationPresent));
}

@SuppressWarnings("unchecked")
private void contributeHibernateHints(RuntimeHints hints, Class<?> managedClass) {
if (embeddableInstantiatorClass == null) {
return;
}
ReflectionHints reflection = hints.reflection();
ReflectionUtils.doWithFields(managedClass, field -> {
Embedded embeddedAnnotation = AnnotationUtils.findAnnotation(field, Embedded.class);
if (embeddedAnnotation != null && field.getAnnotatedType().getType() instanceof Class<?> embeddedClass) {
Annotation embeddableInstantiatorAnnotation = AnnotationUtils.findAnnotation(embeddedClass, embeddableInstantiatorClass);
if (embeddableInstantiatorAnnotation != null) {
Class<?> embeddableInstantiatorClass = (Class<?>) AnnotationUtils.getAnnotationAttributes(embeddableInstantiatorAnnotation).get("value");
reflection.registerType(embeddableInstantiatorClass, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
}
}
});
}
}
}

0 comments on commit 9d6bda2

Please sign in to comment.