From 40109584bf644a42fef97957865dfbb3fda43957 Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Mon, 20 Feb 2023 11:10:03 +0100 Subject: [PATCH] Add missing AOT hints for Spring Batch integration module Resolves #4307 --- .../batch/core/aot/CoreRuntimeHints.java | 51 +++++++++++++++++-- .../main/java/META-INF/spring/aot.factories | 1 + .../aot/IntegrationRuntimeHints.java | 43 ++++++++++++++++ 3 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 spring-batch-integration/src/main/java/META-INF/spring/aot.factories create mode 100644 spring-batch-integration/src/main/java/org/springframework/batch/integration/aot/IntegrationRuntimeHints.java diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/aot/CoreRuntimeHints.java b/spring-batch-core/src/main/java/org/springframework/batch/core/aot/CoreRuntimeHints.java index fd272c2b5..51b474250 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/aot/CoreRuntimeHints.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/aot/CoreRuntimeHints.java @@ -29,9 +29,17 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Properties; +import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.AbstractOwnableSynchronizer; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Stream; import org.springframework.aop.SpringProxy; @@ -41,8 +49,18 @@ import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.aot.hint.SerializationHints; import org.springframework.aot.hint.TypeReference; +import org.springframework.batch.core.Entity; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.scope.context.JobContext; import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.item.Chunk; +import org.springframework.batch.item.ExecutionContext; import org.springframework.core.DecoratingProxy; /** @@ -58,6 +76,12 @@ public class CoreRuntimeHints implements RuntimeHintsRegistrar { @Override public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + Set jdkTypes = Set.of("java.time.Ser", "java.util.Collections$SynchronizedSet", + "java.util.Collections$SynchronizedCollection", "java.util.concurrent.locks.ReentrantLock$Sync", + "java.util.concurrent.locks.ReentrantLock$FairSync", + "java.util.concurrent.locks.ReentrantLock$NonfairSync", + "java.util.concurrent.ConcurrentHashMap$Segment"); + // resource hints hints.resources().registerPattern("org/springframework/batch/core/schema-h2.sql"); hints.resources().registerPattern("org/springframework/batch/core/schema-derby.sql"); @@ -88,14 +112,31 @@ public class CoreRuntimeHints implements RuntimeHintsRegistrar { hints.reflection().registerType(Types.class, MemberCategory.DECLARED_FIELDS); hints.reflection().registerType(JobContext.class, MemberCategory.INVOKE_PUBLIC_METHODS); hints.reflection().registerType(StepContext.class, MemberCategory.INVOKE_PUBLIC_METHODS); + hints.reflection().registerType(JobParameter.class, MemberCategory.values()); + hints.reflection().registerType(JobParameters.class, MemberCategory.values()); + hints.reflection().registerType(ExitStatus.class, MemberCategory.values()); + hints.reflection().registerType(JobInstance.class, MemberCategory.values()); + hints.reflection().registerType(JobExecution.class, MemberCategory.values()); + hints.reflection().registerType(StepExecution.class, MemberCategory.values()); + hints.reflection().registerType(StepContribution.class, MemberCategory.values()); + hints.reflection().registerType(Entity.class, MemberCategory.values()); + hints.reflection().registerType(ExecutionContext.class, MemberCategory.values()); + hints.reflection().registerType(Chunk.class, MemberCategory.values()); + jdkTypes.stream().map(TypeReference::of) + .forEach(type -> hints.reflection().registerType(type, MemberCategory.values())); // serialization hints SerializationHints serializationHints = hints.serialization(); - Stream.of(Number.class, Byte.class, Short.class, Integer.class, Long.class, Double.class, Float.class, - Character.class, String.class, Boolean.class, Date.class, Calendar.class, LocalDate.class, - LocalTime.class, LocalDateTime.class, OffsetTime.class, OffsetDateTime.class, ZonedDateTime.class, - Instant.class, Duration.class, Period.class, HashMap.class, Hashtable.class, ArrayList.class, - Properties.class, Exception.class, UUID.class).forEach(serializationHints::registerType); + Stream.of(LinkedHashSet.class, LinkedHashMap.class, HashSet.class, ReentrantLock.class, ConcurrentHashMap.class, + AbstractOwnableSynchronizer.class, AbstractQueuedSynchronizer.class, Number.class, Byte.class, + Short.class, Integer.class, Long.class, Double.class, Float.class, Character.class, String.class, + Boolean.class, Date.class, Calendar.class, LocalDate.class, LocalTime.class, LocalDateTime.class, + OffsetTime.class, OffsetDateTime.class, ZonedDateTime.class, Instant.class, Duration.class, + Period.class, HashMap.class, Hashtable.class, ArrayList.class, JobParameter.class, JobParameters.class, + ExitStatus.class, JobInstance.class, JobExecution.class, StepExecution.class, StepContribution.class, + Entity.class, ExecutionContext.class, Chunk.class, Properties.class, Exception.class, UUID.class) + .forEach(serializationHints::registerType); + jdkTypes.stream().map(TypeReference::of).forEach(serializationHints::registerType); } } diff --git a/spring-batch-integration/src/main/java/META-INF/spring/aot.factories b/spring-batch-integration/src/main/java/META-INF/spring/aot.factories new file mode 100644 index 000000000..b3a0e6909 --- /dev/null +++ b/spring-batch-integration/src/main/java/META-INF/spring/aot.factories @@ -0,0 +1 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=org.springframework.batch.integration.aot.IntegrationRuntimeHints \ No newline at end of file diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/aot/IntegrationRuntimeHints.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/aot/IntegrationRuntimeHints.java new file mode 100644 index 000000000..72674495f --- /dev/null +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/aot/IntegrationRuntimeHints.java @@ -0,0 +1,43 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.integration.aot; + +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.batch.integration.chunk.ChunkRequest; +import org.springframework.batch.integration.chunk.ChunkResponse; + +/** + * AOT hints for Spring Batch integration module. + * + * @author Mahmoud Ben Hassine + * @since 5.0.1 + */ +public class IntegrationRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + // reflection hints + hints.reflection().registerType(ChunkRequest.class, MemberCategory.values()); + hints.reflection().registerType(ChunkResponse.class, MemberCategory.values()); + + // serialization hints + hints.serialization().registerType(ChunkRequest.class); + hints.serialization().registerType(ChunkResponse.class); + } + +}