From 03391dfa94c30c0f34bca99e5fa5deff2d60d343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Thu, 5 Mar 2026 11:22:44 +0100 Subject: [PATCH] Switch serializable flag to primitive boolean This commit improves the change made to TypeHint to use a primitive boolean for the serializable flag. See gh-36379 --- .../aot/hint/JdkProxyHint.java | 22 ++++++------ .../springframework/aot/hint/TypeHint.java | 20 +++++------ .../predicate/ReflectionHintsPredicates.java | 34 ++++++++++--------- .../nativex/ReflectionHintsAttributes.java | 8 ++--- .../aot/hint/ProxyHintsTests.java | 4 +-- .../aot/nativex/RuntimeHintsWriterTests.java | 22 ++++++++++-- 6 files changed, 64 insertions(+), 46 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java b/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java index 912c0bc1890..536a8958564 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/JdkProxyHint.java @@ -37,13 +37,13 @@ public final class JdkProxyHint implements ConditionalHint { private final @Nullable TypeReference reachableType; - private final @Nullable Boolean serializable; + private final boolean javaSerialization; private JdkProxyHint(Builder builder) { this.proxiedInterfaces = List.copyOf(builder.proxiedInterfaces); this.reachableType = builder.reachableType; - this.serializable = builder.serializable; + this.javaSerialization = builder.javaSerialization; } /** @@ -79,12 +79,12 @@ public final class JdkProxyHint implements ConditionalHint { } /** - * Return whether to register this proxy for Java serialization. - * @return whether to register this proxy for Java serialization. + * Return whether this hint registers the proxy for Java serialization. + * @return whether the proxy is registered for Java serialization * @since 7.0.6 */ - public @Nullable Boolean getSerializable() { - return this.serializable; + public boolean hasJavaSerialization() { + return this.javaSerialization; } @Override @@ -92,7 +92,7 @@ public final class JdkProxyHint implements ConditionalHint { return (this == other || (other instanceof JdkProxyHint that && this.proxiedInterfaces.equals(that.proxiedInterfaces) && Objects.equals(this.reachableType, that.reachableType) && - Objects.equals(this.serializable, that.serializable))); + Objects.equals(this.javaSerialization, that.javaSerialization))); } @Override @@ -110,7 +110,7 @@ public final class JdkProxyHint implements ConditionalHint { private @Nullable TypeReference reachableType; - private @Nullable Boolean serializable; + private boolean javaSerialization; Builder() { this.proxiedInterfaces = new LinkedList<>(); @@ -148,12 +148,12 @@ public final class JdkProxyHint implements ConditionalHint { /** * Specify if this proxy should be registered for Java serialization. - * @param serializable whether to register this proxy for Java serialization. + * @param javaSerialization whether to register this proxy for Java serialization * @return {@code this}, to facilitate method chaining * @since 7.0.6 */ - public Builder javaSerialization(@Nullable Boolean serializable) { - this.serializable = serializable; + public Builder withJavaSerialization(boolean javaSerialization) { + this.javaSerialization = javaSerialization; return this; } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java index fe0540ec8e1..962bc90c434 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java @@ -53,7 +53,7 @@ public final class TypeHint implements ConditionalHint { private final Set memberCategories; - private final @Nullable Boolean serializable; + private final boolean javaSerialization; private TypeHint(Builder builder) { @@ -63,7 +63,7 @@ public final class TypeHint implements ConditionalHint { this.fields = builder.fields.stream().map(FieldHint::new).collect(Collectors.toSet()); this.constructors = builder.constructors.values().stream().map(ExecutableHint.Builder::build).collect(Collectors.toSet()); this.methods = builder.methods.values().stream().map(ExecutableHint.Builder::build).collect(Collectors.toSet()); - this.serializable = builder.serializable; + this.javaSerialization = builder.javaSerialization; } /** @@ -124,12 +124,12 @@ public final class TypeHint implements ConditionalHint { } /** - * Return whether to register this type for Java serialization. - * @return whether to register this type for Java serialization. + * Return whether this hint registers the type for Java serialization. + * @return whether the type is registered for Java serialization * @since 7.0.6 */ - public @Nullable Boolean getSerializable() { - return this.serializable; + public boolean hasJavaSerialization() { + return this.javaSerialization; } @Override @@ -165,7 +165,7 @@ public final class TypeHint implements ConditionalHint { private final Set memberCategories = new HashSet<>(); - private @Nullable Boolean serializable; + private boolean javaSerialization; Builder(TypeReference type) { this.type = type; @@ -276,12 +276,12 @@ public final class TypeHint implements ConditionalHint { /** * Specify if this type should be registered for Java serialization. - * @param serializable whether to register this type for Java serialization. + * @param javaSerialization whether to register this type for Java serialization. * @return {@code this}, to facilitate method chaining * @since 7.0.6 */ - public Builder withJavaSerialization(@Nullable Boolean serializable) { - this.serializable = serializable; + public Builder withJavaSerialization(boolean javaSerialization) { + this.javaSerialization = javaSerialization; return this; } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java index 14a3fd735ff..2f75057aea8 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicates.java @@ -23,7 +23,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; -import java.util.Objects; import java.util.Set; import java.util.function.Predicate; @@ -261,7 +260,7 @@ public class ReflectionHintsPredicates { } /** - * Return a predicate that checks whether an invocation hint is registered for the field. + * Return a predicate that checks whether a reflective field access hint is registered for the field. * This looks up a field on the given type with the expected name, if present. * @param className the name of the class holding the field * @param fieldName the field name @@ -288,7 +287,8 @@ public class ReflectionHintsPredicates { } /** - * Return a predicate that checks whether an invocation hint is registered for the given field. + * Return a predicate that checks whether a reflective field access hint is + * registered for the given field. * @param field the field * @return the {@link RuntimeHints} predicate * @since 7.0 @@ -299,27 +299,29 @@ public class ReflectionHintsPredicates { } /** - * Return a predicate that checks whether Java serialization is configured according to the given flag. + * Return a predicate that checks whether Java serialization is configured + * for the type according to the given flag. * @param type the type to check - * @param serializable the expected serializable flag + * @param javaSerialization whether the type is expected to be registered for Java serialization * @return the {@link RuntimeHints} predicate * @since 7.0.6 */ - public Predicate onJavaSerialization(Class type, @Nullable Boolean serializable) { + public Predicate onJavaSerialization(Class type, boolean javaSerialization) { Assert.notNull(type, "'type' must not be null"); - return new SerializationdHintPredicate(TypeReference.of(type), serializable); + return new JavaSerializationHintPredicate(TypeReference.of(type), javaSerialization); } /** - * Return a predicate that checks whether Java serialization is configured according to the given flag. + * Return a predicate that checks whether Java serialization is configured + * for the type according to the given flag. * @param typeReference the type reference to check - * @param serializable the expected serializable flag + * @param javaSerialization whether the type is expected to be registered for Java serialization * @return the {@link RuntimeHints} predicate * @since 7.0.6 */ - public Predicate onJavaSerialization(TypeReference typeReference, @Nullable Boolean serializable) { + public Predicate onJavaSerialization(TypeReference typeReference, boolean javaSerialization) { Assert.notNull(typeReference, "'typeReference' must not be null"); - return new SerializationdHintPredicate(typeReference, serializable); + return new JavaSerializationHintPredicate(typeReference, javaSerialization); } @@ -535,15 +537,15 @@ public class ReflectionHintsPredicates { } - public static class SerializationdHintPredicate implements Predicate { + public static class JavaSerializationHintPredicate implements Predicate { private final TypeReference typeReference; - private final @Nullable Boolean serializable; + private final boolean javaSerialization; - SerializationdHintPredicate(TypeReference typeReference, @Nullable Boolean serializable) { + JavaSerializationHintPredicate(TypeReference typeReference, boolean javaSerialization) { this.typeReference = typeReference; - this.serializable = serializable; + this.javaSerialization = javaSerialization; } @Override @@ -552,7 +554,7 @@ public class ReflectionHintsPredicates { if (typeHint == null) { return false; } - return Objects.equals(typeHint.getSerializable(), this.serializable); + return typeHint.hasJavaSerialization() == this.javaSerialization; } } diff --git a/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsAttributes.java b/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsAttributes.java index ba93dd97d81..650e80dcc31 100644 --- a/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsAttributes.java +++ b/spring-core/src/main/java/org/springframework/aot/nativex/ReflectionHintsAttributes.java @@ -111,7 +111,7 @@ class ReflectionHintsAttributes { handleFields(attributes, hint.fields()); handleExecutables(attributes, Stream.concat( hint.constructors(), hint.methods()).sorted().toList()); - handleSerializable(attributes, hint.getSerializable()); + handleSerializable(attributes, hint.hasJavaSerialization()); return attributes; } @@ -198,12 +198,12 @@ class ReflectionHintsAttributes { Map attributes = new LinkedHashMap<>(); handleCondition(attributes, hint); attributes.put("type", Map.of("proxy", hint.getProxiedInterfaces())); - handleSerializable(attributes, hint.getSerializable()); + handleSerializable(attributes, hint.hasJavaSerialization()); return attributes; } - private void handleSerializable(Map attributes, @Nullable Boolean serializable) { - if (serializable != null) { + private void handleSerializable(Map attributes, boolean serializable) { + if (serializable) { attributes.put("serializable", serializable); } } diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java index e7372b289af..2dd18742277 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ProxyHintsTests.java @@ -84,11 +84,11 @@ class ProxyHintsTests { void registerJdkProxyWithJavaSerialization() { this.proxyHints.registerJdkProxy(hint -> { hint.proxiedInterfaces(TypeReference.of("com.example.Test")); - hint.javaSerialization(true); + hint.withJavaSerialization(true); }); assertThat(this.proxyHints.jdkProxyHints()).singleElement().satisfies(hint -> { assertThat(hint.getProxiedInterfaces()).containsExactly(TypeReference.of("com.example.Test")); - assertThat(hint.getSerializable()).isTrue(); + assertThat(hint.hasJavaSerialization()).isTrue(); }); } diff --git a/spring-core/src/test/java/org/springframework/aot/nativex/RuntimeHintsWriterTests.java b/spring-core/src/test/java/org/springframework/aot/nativex/RuntimeHintsWriterTests.java index 75f83d2c318..bf50e2b5523 100644 --- a/spring-core/src/test/java/org/springframework/aot/nativex/RuntimeHintsWriterTests.java +++ b/spring-core/src/test/java/org/springframework/aot/nativex/RuntimeHintsWriterTests.java @@ -208,7 +208,7 @@ class RuntimeHintsWriterTests { } @Test - void serializationEnabled() throws JSONException { + void javaSerializationEnabled() throws JSONException { RuntimeHints hints = new RuntimeHints(); hints.reflection().registerType(Integer.class, builder -> builder.withJavaSerialization(true)); @@ -224,6 +224,22 @@ class RuntimeHintsWriterTests { """, hints); } + @Test + void javaSerializationDisabled() throws JSONException { + RuntimeHints hints = new RuntimeHints(); + hints.reflection().registerType(Integer.class, builder -> builder.withJavaSerialization(false)); + + assertEquals(""" + { + "reflection": [ + { + "type": "java.lang.Integer" + } + ] + } + """, hints); + } + @Test void ignoreLambda() throws JSONException { Runnable anonymousRunnable = () -> {}; @@ -658,11 +674,11 @@ class RuntimeHintsWriterTests { } @Test - void shouldWriteSerialization() throws JSONException { + void shouldWriteSerializable() throws JSONException { RuntimeHints hints = new RuntimeHints(); hints.proxies().registerJdkProxy(hint -> { hint.proxiedInterfaces(Function.class); - hint.javaSerialization(true); + hint.withJavaSerialization(true); }); assertEquals(""" {