Register reflection hints for Relay pagination types - #1480
Conversation
graphql-java's PropertyFetchingImpl resolves Connection edges, nodes, cursors and page info via reflection. The Relay implementation classes that ConnectionFieldTypeVisitor constructs (DefaultConnection, DefaultConnectionCursor, DefaultEdge, DefaultPageInfo) are no longer present in the GraalVM reachability metadata for recent graphql-java releases, so in a native image those getter calls fail and edges are serialized with null nodes and page info. Add a RuntimeHintsRegistrar that registers INVOKE_PUBLIC_METHODS for the four Relay types so they remain reflectively accessible in a native image, and wire it through META-INF/spring/aot.factories. Closes spring-projectsgh-1479 Signed-off-by: seonwoo_jung <laborlawseon@kap.kr>
|
Gentle ping — open since mid-June.
Is registering them here the right home, or would you rather this be pushed back to the graphql-java metadata? Still merges cleanly and all four checks are green. |
|
Thanks for this contribution, but I think it would be strange to copy/paste the code that I contributed to the shared reachability metadata in this project, wouldn't it? I think it would be best to fix this in the central repository. |
Fixes #1479
Root cause
graphql-java'sPropertyFetchingImplresolves Relay connection fields (edges,node,cursor,pageInfo,hasNextPage,endCursor, …) reflectively against whatever Java object the data fetcher returns. Spring for GraphQL wrapsWindow,Slice, and other backing containers into the concretegraphql-javatypesDefaultConnection,DefaultConnectionCursor,DefaultEdge, andDefaultPageInfoinsideConnectionFieldTypeVisitor.ConnectionDataFetcher.The GraalVM reachability metadata that used to list those four classes for
graphql-javahas been dropped from recent versions of the published metadata. On the JVM the reflective lookup still works, but in a native image the getters are inaccessible andPropertyFetchingImplfalls back tonull, so relay responses come back with emptynode/pageInfoeven though the data fetcher produced the correct objects. The reporter on #1479 confirmed that adding hints for these four types restores the expected behavior.Change
Adds
RelayPaginationRuntimeHints, aRuntimeHintsRegistrarthat registersINVOKE_PUBLIC_METHODSfor the fourgraphql.relay.Default*types, and wires it throughMETA-INF/spring/aot.factories. Since Spring for GraphQL is the component that surfaces these types tographql-java, registering the hints here keeps the fix scoped to the situations where Spring actually creates them, rather than relying on upstream metadata to stay in sync.The hint only covers public getters (
INVOKE_PUBLIC_METHODS), matching whatPropertyFetchingImplactually uses; no constructor or field hints are needed because Spring instantiates these types directly.Test evidence
RelayPaginationRuntimeHintsTestscovers two things:META-INF/spring/aot.factoriesINVOKE_PUBLIC_METHODShint registered./gradlew :spring-graphql:test --tests "org.springframework.graphql.data.pagination.*"passes (existingConnectionFieldTypeVisitorTests,Base64CursorEncoderTests, plus the new tests, all green)../gradlew :spring-graphql:checkstyleMain :spring-graphql:checkstyleTestis clean.Verification done
gh pr list --repo spring-projects/spring-graphql --search "relay native hints"and a scan of the recent PR list show no open PR referencing this issue.META-INF/spring/aot.factories.main. None ofDefaultConnection/DefaultConnectionCursor/DefaultEdge/DefaultPageInfoappear inspring-graphql/src/main/resources/META-INF/native-image/.../reflect-config.json, and no existingRuntimeHintsRegistrarregisters them — verified bygrep -r "DefaultConnection\|DefaultEdge\|DefaultPageInfo" spring-graphql/src/main/.Windowrunning in native image) and a precise root-cause trace throughgraphql.schema.PropertyFetchingImpl; the reporter verified the same fix in their own application.