From ca462e733e9d79dd35ea43e7700c8a65de5a22c7 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 7 Oct 2024 09:53:18 +0200 Subject: [PATCH] Fix native image hints for web support. This commit adds a required native image reflection hint to allow Jackson object mapping to resolve and invoke the constructor of PageMetadata. It also fixes an issue that surfaced after changing the bean constructor argument for SpringDataWebSettings leading to failures during the native compilation. Closes: #3171 --- .../springframework/data/web/aot/WebRuntimeHints.java | 8 +++++++- .../data/web/aot/WebRuntimeHintsUnitTests.java | 11 ++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/springframework/data/web/aot/WebRuntimeHints.java b/src/main/java/org/springframework/data/web/aot/WebRuntimeHints.java index 3a9aee614..68f01f452 100644 --- a/src/main/java/org/springframework/data/web/aot/WebRuntimeHints.java +++ b/src/main/java/org/springframework/data/web/aot/WebRuntimeHints.java @@ -20,6 +20,7 @@ import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.TypeReference; import org.springframework.data.web.PagedModel; +import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.data.web.config.SpringDataJacksonConfiguration.PageModule; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; @@ -35,12 +36,17 @@ class WebRuntimeHints implements RuntimeHintsRegistrar { @Override public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { + hints.reflection().registerType(org.springframework.data.web.config.SpringDataWebSettings.class, hint -> hint + .withMembers(MemberCategory.INVOKE_DECLARED_METHODS).onReachableType(EnableSpringDataWebSupport.class)); + if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader)) { // Page Model for Jackson Rendering hints.reflection().registerType(org.springframework.data.web.PagedModel.class, MemberCategory.INVOKE_PUBLIC_METHODS); - hints.reflection().registerType(PagedModel.PageMetadata.class, MemberCategory.INVOKE_PUBLIC_METHODS); + + hints.reflection().registerType(PagedModel.PageMetadata.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, + MemberCategory.INVOKE_PUBLIC_METHODS); // Type that might not be seen otherwise hints.reflection().registerType(TypeReference.of("org.springframework.data.domain.Unpaged"), diff --git a/src/test/java/org/springframework/data/web/aot/WebRuntimeHintsUnitTests.java b/src/test/java/org/springframework/data/web/aot/WebRuntimeHintsUnitTests.java index 72b20118f..6a88781b5 100644 --- a/src/test/java/org/springframework/data/web/aot/WebRuntimeHintsUnitTests.java +++ b/src/test/java/org/springframework/data/web/aot/WebRuntimeHintsUnitTests.java @@ -15,11 +15,11 @@ */ package org.springframework.data.web.aot; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import org.junit.jupiter.api.Test; - import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; @@ -46,7 +46,7 @@ class WebRuntimeHintsUnitTests { RuntimeHintsPredicates.reflection().onType(TypeReference.of("org.springframework.data.domain.Unpaged"))); } - @Test // GH-3033 + @Test // GH-3033, GH-3171 @ClassPathExclusions(packages = { "com.fasterxml.jackson.databind" }) void shouldRegisterRuntimeHintWithTypeNameWhenJacksonNotPresent() { @@ -56,6 +56,7 @@ class WebRuntimeHintsUnitTests { new WebRuntimeHints().registerHints(runtimeHints, this.getClass().getClassLoader()); - assertThat(runtimeHints.reflection().typeHints()).isEmpty(); + assertThat(runtimeHints).matches(RuntimeHintsPredicates.reflection() + .onType(TypeReference.of("org.springframework.data.web.config.SpringDataWebSettings"))); } }