diff --git a/ci/pipeline.properties b/ci/pipeline.properties index cde4a8e881..b9297d8d2b 100644 --- a/ci/pipeline.properties +++ b/ci/pipeline.properties @@ -1,10 +1,10 @@ # Java versions -java.main.tag=24.0.1_9-jdk-noble -java.next.tag=24.0.1_9-jdk-noble +java.main.tag=25 +java.next.tag=25-cds # Docker container images - standard -docker.java.main.image=library/eclipse-temurin:${java.main.tag} -docker.java.next.image=library/eclipse-temurin:${java.next.tag} +docker.java.main.image=bellsoft/liberica-openjdk-alpine:${java.main.tag} +docker.java.next.image=bellsoft/liberica-openjdk-alpine:${java.next.tag} # Supported versions of MongoDB docker.mongodb.6.0.version=6.0.23 diff --git a/pom.xml b/pom.xml index 13143c9f6f..f4bc430605 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-commons - 4.0.0-SNAPSHOT + 4.0.0-STABLE-VALUE-SNAPSHOT Spring Data Core Core Spring concepts underpinning every Spring Data module. @@ -341,18 +341,55 @@ + org.apache.maven.plugins maven-assembly-plugin + org.antora antora-maven-plugin + + + org.apache.maven.plugins + maven-jar-plugin + + + default-jar + + + + true + + + + + + + org.apache.maven.plugins maven-compiler-plugin + + + jdk25 + + compile + + + true + 25 + + ${project.basedir}/src/main/java25 + + + true + + + java-test-compile @@ -366,8 +403,10 @@ + + diff --git a/src/main/java/org/springframework/data/util/Lazy.java b/src/main/java/org/springframework/data/util/Lazy.java index 193726da60..f5208ce2c1 100644 --- a/src/main/java/org/springframework/data/util/Lazy.java +++ b/src/main/java/org/springframework/data/util/Lazy.java @@ -22,7 +22,6 @@ import org.jspecify.annotations.Nullable; import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; /** * Simple value type to delay the creation of an object using a {@link Supplier} returning the produced object for @@ -40,30 +39,14 @@ */ public class Lazy implements Supplier { - private static final Lazy EMPTY = new Lazy<>(() -> null, null, true); - static final String UNRESOLVED = "[Unresolved]"; + private static final Lazy EMPTY = new Lazy<>(() -> null); - private final Supplier supplier; + static final String UNRESOLVED = "[Unresolved]"; - private @Nullable T value; - private volatile boolean resolved; + private final LazyDelegate adapter; - private Lazy(Supplier supplier) { - this(supplier, null, false); - } - - /** - * Creates a new {@code Lazy} for the given {@link Supplier}, value and whether it has been resolved or not. - * - * @param supplier must not be {@literal null}. - * @param value can be {@literal null}. - * @param resolved whether the value handed into the constructor represents a resolved value. - */ - private Lazy(Supplier supplier, @Nullable T value, boolean resolved) { - - this.supplier = supplier; - this.value = value; - this.resolved = resolved; + private Lazy(Supplier adapter) { + this.adapter = new LazyDelegate<>(adapter); } /** @@ -128,16 +111,7 @@ public T get() { */ @Nullable public T getNullable() { - - if (resolved) { - return value; - } - - T result = supplier.get(); - this.value = result; - this.resolved = true; - - return result; + return adapter.getNullable(); } /** @@ -249,35 +223,22 @@ public boolean equals(@Nullable Object o) { return false; } - if (resolved != lazy.resolved) { - return false; - } - - if (!ObjectUtils.nullSafeEquals(supplier, lazy.supplier)) { - return false; - } - - return ObjectUtils.nullSafeEquals(value, lazy.value); + return adapter.equals(lazy.adapter); } @Override public int hashCode() { - - int result = ObjectUtils.nullSafeHashCode(supplier); - - result = 31 * result + ObjectUtils.nullSafeHashCode(value); - result = 31 * result + (resolved ? 1 : 0); - - return result; + return adapter.hashCode(); } @Override public String toString() { - if (!resolved) { + if (!adapter.isResolved()) { return UNRESOLVED; } + T value = getNullable(); return value == null ? "null" : value.toString(); } @@ -293,6 +254,6 @@ public String toString(Supplier fallback) { Assert.notNull(fallback, "Fallback must not be null!"); - return resolved ? toString() : fallback.get(); + return adapter.isResolved() ? toString() : fallback.get(); } } diff --git a/src/main/java/org/springframework/data/util/LazyDelegate.java b/src/main/java/org/springframework/data/util/LazyDelegate.java new file mode 100644 index 0000000000..e077b4069c --- /dev/null +++ b/src/main/java/org/springframework/data/util/LazyDelegate.java @@ -0,0 +1,102 @@ +/* + * Copyright 2016-2025 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.data.util; + +import java.util.function.Supplier; + +import org.jspecify.annotations.Nullable; + +import org.springframework.util.ObjectUtils; + +/** + * Simple lazy implementation using lazy value resolution. Lazy evaluation not guarded with locks and can therefore lead + * to multiple invocations of the underlying {@link Supplier}. + * + * @author Oliver Gierke + * @author Mark Paluch + * @author Henning Rohlfs + * @author Johannes Englmeier + * @author Greg Turnquist + * @since 4.0 + */ +class LazyDelegate { + + private final Supplier supplier; + + private @Nullable T value; + private volatile boolean resolved; + + LazyDelegate(Supplier supplier) { + this.supplier = supplier; + } + + /** + * Returns the value of the lazy evaluation. + * + * @return the value of the lazy evaluation, can be {@literal null}. + */ + @Nullable + public T getNullable() { + + if (resolved) { + return value; + } + + T result = supplier.get(); + this.value = result; + this.resolved = true; + + return result; + } + + public boolean isResolved() { + return resolved; + } + + @Override + public boolean equals(@Nullable Object o) { + + if (this == o) { + return true; + } + + if (!(o instanceof LazyDelegate lazy)) { + return false; + } + + if (resolved != lazy.resolved) { + return false; + } + + if (!ObjectUtils.nullSafeEquals(supplier, lazy.supplier)) { + return false; + } + + return ObjectUtils.nullSafeEquals(value, lazy.value); + } + + @Override + public int hashCode() { + + int result = ObjectUtils.nullSafeHashCode(supplier); + + result = 31 * result + ObjectUtils.nullSafeHashCode(value); + result = 31 * result + (resolved ? 1 : 0); + + return result; + } + +} diff --git a/src/main/java25/org/springframework/data/util/LazyDelegate.java b/src/main/java25/org/springframework/data/util/LazyDelegate.java new file mode 100644 index 0000000000..73d9fd1ce7 --- /dev/null +++ b/src/main/java25/org/springframework/data/util/LazyDelegate.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016-2025 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.data.util; + +import java.util.function.Supplier; + +import org.jspecify.annotations.Nullable; + +import org.springframework.util.ObjectUtils; + +/** + * Lazy adapter using {@link StableValue}. + * + * @author Mark Paluch + * @since 4.0 + */ +class LazyDelegate { + + private final Supplier supplier; + private final StableValue value; + + LazyDelegate(Supplier supplier) { + + System.out.println("Stable"); + this.supplier = supplier; + this.value = StableValue.of(); + } + + /** + * Returns the value of the lazy evaluation. + * + * @return the value of the lazy evaluation, can be {@literal null}. + */ + @Nullable + public T getNullable() { + return value.orElseSet(supplier); + } + + public boolean isResolved() { + return value.isSet(); + } + + @Override + public boolean equals(@Nullable Object o) { + + if (this == o) { + return true; + } + + if (!(o instanceof LazyDelegate lazy)) { + return false; + } + + return ObjectUtils.nullSafeEquals(value, lazy.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + +}