From 18d66a48337d73e2f1eb95ca8063003421867700 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 20 Nov 2024 13:58:58 +0100 Subject: [PATCH] Remove `@Deprecated` API. See #3208 --- .../model/AbstractPersistentProperty.java | 3 +- .../AnnotationBasedPersistentProperty.java | 4 +- .../support/RepositoryFactorySupport.java | 2 - .../data/repository/util/ClassUtils.java | 204 ------------------ .../springframework/data/util/CastUtils.java | 28 --- .../data/util/ReflectionUtils.java | 64 ------ ...rydslPredicateArgumentResolverSupport.java | 4 +- .../DefaultRepositoryMetadataUnitTests.java | 7 - .../repository/util/ClassUtilsUnitTests.java | 122 ----------- 9 files changed, 6 insertions(+), 432 deletions(-) delete mode 100644 src/main/java/org/springframework/data/repository/util/ClassUtils.java delete mode 100644 src/main/java/org/springframework/data/util/CastUtils.java delete mode 100755 src/test/java/org/springframework/data/repository/util/ClassUtilsUnitTests.java diff --git a/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java b/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java index a09aa9201a..b200908a16 100644 --- a/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java @@ -27,6 +27,7 @@ import org.springframework.data.mapping.Association; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.util.ClassUtils; import org.springframework.data.util.KotlinReflectionUtils; import org.springframework.data.util.Lazy; import org.springframework.data.util.ReflectionUtils; @@ -50,7 +51,7 @@ public abstract class AbstractPersistentProperty

static { CAUSE_FIELD = ReflectionUtils.getRequiredField(Throwable.class, "cause"); - ASSOCIATION_TYPE = ReflectionUtils.loadIfPresent("org.jmolecules.ddd.types.Association", + ASSOCIATION_TYPE = ClassUtils.loadIfPresent("org.jmolecules.ddd.types.Association", AbstractPersistentProperty.class.getClassLoader()); } diff --git a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java index dc4b33de76..810909c123 100644 --- a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java @@ -37,9 +37,9 @@ import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.util.ClassUtils; import org.springframework.data.util.Lazy; import org.springframework.data.util.Optionals; -import org.springframework.data.util.ReflectionUtils; import org.springframework.data.util.StreamUtils; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; @@ -316,7 +316,7 @@ private Stream getAccessors() { @SuppressWarnings("unchecked") private static Class loadIdentityType() { - return (Class) ReflectionUtils.loadIfPresent("org.jmolecules.ddd.annotation.Identity", + return (Class) ClassUtils.loadIfPresent("org.jmolecules.ddd.annotation.Identity", AbstractPersistentProperty.class.getClassLoader()); } } diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java index d77cf0bbf3..a8165a3c21 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java @@ -679,13 +679,11 @@ private static boolean shouldExposeMetadata(RepositoryFragments fragments) { */ static class ImplementationMethodExecutionInterceptor implements MethodInterceptor { - private final RepositoryInformation information; private final RepositoryComposition composition; private final RepositoryInvocationMulticaster invocationMulticaster; public ImplementationMethodExecutionInterceptor(RepositoryInformation information, RepositoryComposition composition, List methodInvocationListeners) { - this.information = information; this.composition = composition; this.invocationMulticaster = methodInvocationListeners.isEmpty() ? NoOpRepositoryInvocationMulticaster.INSTANCE : new DefaultRepositoryInvocationMulticaster(methodInvocationListeners); diff --git a/src/main/java/org/springframework/data/repository/util/ClassUtils.java b/src/main/java/org/springframework/data/repository/util/ClassUtils.java deleted file mode 100644 index 1cd72d49bc..0000000000 --- a/src/main/java/org/springframework/data/repository/util/ClassUtils.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2008-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.repository.util; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; -import java.util.function.Consumer; - -import org.springframework.data.repository.Repository; -import org.springframework.data.util.TypeInformation; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -/** - * Utility class to work with classes. - * - * @author Oliver Gierke - * @author Mark Paluch - * @author Johannes Englmeier - * @deprecated since 3.5, use {@link org.springframework.data.util.ClassUtils} instead. - */ -@Deprecated(since = "3.5", forRemoval = true) -public abstract class ClassUtils { - - /** - * Private constructor to prevent instantiation. - */ - private ClassUtils() {} - - /** - * Returns whether the given class contains a property with the given name. - * - * @param type - * @param property - * @return - */ - public static boolean hasProperty(Class type, String property) { - - if (null != ReflectionUtils.findMethod(type, "get" + property)) { - return true; - } - - return null != ReflectionUtils.findField(type, StringUtils.uncapitalize(property)); - } - - /** - * Determine whether the {@link Class} identified by the supplied {@code className} is present * and can be loaded and - * call the {@link Consumer action} if the {@link Class} could be loaded. - * - * @param className the name of the class to check. - * @param classLoader the class loader to use. - * @param action the action callback to notify. (may be {@code null} which indicates the default class loader) - * @throws IllegalStateException if the corresponding class is resolvable but there was a readability mismatch in the - * inheritance hierarchy of the class (typically a missing dependency declaration in a Jigsaw module - * definition for a superclass or interface implemented by the class to be checked here) - */ - public static void ifPresent(String className, @Nullable ClassLoader classLoader, Consumer> action) { - org.springframework.data.util.ClassUtils.ifPresent(className, classLoader, action); - } - - /** - * Returns wthere the given type is the {@link Repository} interface. - * - * @param interfaze - * @return - */ - public static boolean isGenericRepositoryInterface(Class interfaze) { - - return Repository.class.equals(interfaze); - } - - /** - * Returns whether the given type name is a repository interface name. - * - * @param interfaceName - * @return - */ - public static boolean isGenericRepositoryInterface(@Nullable String interfaceName) { - return Repository.class.getName().equals(interfaceName); - } - - /** - * @deprecated Use {@link #getNumberOfOccurrences(Method, Class)}. - */ - public static int getNumberOfOccurences(Method method, Class type) { - return getNumberOfOccurrences(method, type); - } - - /** - * Returns the number of occurrences for the given {@link Method#getParameterTypes() parameter type} in the given - * {@link Method}. - * - * @param method {@link Method} to evaluate. - * @param parameterType {@link Class} of the {@link Method} parameter type to count. - * @return the number of occurrences for the given {@link Method#getParameterTypes() parameter type} in the given - * {@link Method}. - * @see java.lang.reflect.Method#getParameterTypes() - */ - public static int getNumberOfOccurrences(@NonNull Method method, @NonNull Class parameterType) { - return org.springframework.data.util.ReflectionUtils.getParameterCount(method, parameterType::equals); - } - - /** - * Asserts the given {@link Method}'s return type to be one of the given types. Will unwrap known wrapper types before - * the assignment check (see {@link QueryExecutionConverters}). - * - * @param method must not be {@literal null}. - * @param types must not be {@literal null} or empty. - */ - public static void assertReturnTypeAssignable(Method method, Class... types) { - - Assert.notNull(method, "Method must not be null"); - Assert.notEmpty(types, "Types must not be null or empty"); - - TypeInformation returnType = getEffectivelyReturnedTypeFrom(method); - - Arrays.stream(types)// - .filter(it -> it.isAssignableFrom(returnType.getType()))// - .findAny().orElseThrow(() -> new IllegalStateException( - "Method has to have one of the following return types: " + Arrays.toString(types))); - } - - /** - * Returns whether the given object is of one of the given types. Will return {@literal false} for {@literal null}. - * - * @param object - * @param types - * @return - */ - public static boolean isOfType(@Nullable Object object, Collection> types) { - - if (object == null) { - return false; - } - - return types.stream().anyMatch(it -> it.isAssignableFrom(object.getClass())); - } - - /** - * Returns whether the given {@link Method} has a parameter of the given type. - * - * @param method - * @param type - * @return - */ - public static boolean hasParameterOfType(Method method, Class type) { - return org.springframework.data.util.ReflectionUtils.hasParameterOfType(method, type); - } - - /** - * Returns whether the given {@link Method} has a parameter that is assignable to the given type. - * - * @param method - * @param type - * @return - */ - public static boolean hasParameterAssignableToType(Method method, Class type) { - return org.springframework.data.util.ReflectionUtils.hasParameterOfType(method, type); - } - - /** - * Helper method to extract the original exception that can possibly occur during a reflection call. - * - * @param ex - * @throws Throwable - */ - public static void unwrapReflectionException(Exception ex) throws Throwable { - - if (ex instanceof InvocationTargetException ite) { - ReflectionUtils.handleInvocationTargetException(ite); - } - - throw ex; - } - - // TODO: we should also consider having the owning type here so we can resolve generics better. - private static TypeInformation getEffectivelyReturnedTypeFrom(Method method) { - - TypeInformation returnType = TypeInformation.fromReturnTypeOf(method); - - return QueryExecutionConverters.supports(returnType.getType()) // - || ReactiveWrapperConverters.supports(returnType.getType()) // - ? returnType.getRequiredComponentType() // - : returnType; - } -} diff --git a/src/main/java/org/springframework/data/util/CastUtils.java b/src/main/java/org/springframework/data/util/CastUtils.java deleted file mode 100644 index 3eee4836c9..0000000000 --- a/src/main/java/org/springframework/data/util/CastUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017-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; - -/** - * @deprecated since 3.5 will be removed in a future release. - */ -@Deprecated(since = "3.5", forRemoval = true) -public interface CastUtils { - - @SuppressWarnings("unchecked") - public static T cast(Object object) { - return (T) object; - } -} diff --git a/src/main/java/org/springframework/data/util/ReflectionUtils.java b/src/main/java/org/springframework/data/util/ReflectionUtils.java index 3340265107..51c77f83ae 100644 --- a/src/main/java/org/springframework/data/util/ReflectionUtils.java +++ b/src/main/java/org/springframework/data/util/ReflectionUtils.java @@ -28,7 +28,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.springframework.beans.BeanUtils; import org.springframework.core.KotlinDetector; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; @@ -98,27 +97,6 @@ public static int getParameterCount(Method method, Predicate> predicate return (int) Arrays.stream(method.getParameterTypes()).filter(predicate).count(); } - /** - * Creates an instance of the class with the given fully qualified name or returns the given default instance if the - * class cannot be loaded or instantiated. - * - * @param classname the fully qualified class name to create an instance for. - * @param defaultInstance the instance to fall back to in case the given class cannot be loaded or instantiated. - * @return - * @deprecated since 3.5 as it is not used within the framework anymore. - */ - @SuppressWarnings("unchecked") - @Deprecated(since = "3.5", forRemoval = true) - public static T createInstanceIfPresent(String classname, T defaultInstance) { - - try { - Class type = ClassUtils.forName(classname, ClassUtils.getDefaultClassLoader()); - return (T) BeanUtils.instantiateClass(type); - } catch (Exception e) { - return defaultInstance; - } - } - /** * Check whether the given {@code type} represents a void type such as {@code void}, {@link Void} or Kotlin * {@code Unit}. @@ -264,20 +242,6 @@ public static Field findField(Class type, DescribedFieldFilter filter, boolea return foundField; } - /** - * Finds the field of the given name on the given type. - * - * @param type must not be {@literal null}. - * @param name must not be {@literal null} or empty. - * @return the required field. - * @throws IllegalArgumentException in case the field can't be found. - * @deprecated use {@link #getRequiredField(Class, String)} instead. - */ - @Deprecated(since = "3.5", forRemoval = true) - public static Field findRequiredField(Class type, String name) { - return getRequiredField(type, name); - } - /** * Obtains the required field of the given name on the given type or throws {@link IllegalArgumentException} if the * found could not be found. @@ -411,20 +375,6 @@ public static Stream> returnTypeAndParameters(Method method) { return Stream.concat(returnType, parameterTypes); } - /** - * Returns the {@link Method} with the given name and parameters declared on the given type, if available. - * - * @param type must not be {@literal null}. - * @param name must not be {@literal null} or empty. - * @param parameterTypes must not be {@literal null}. - * @return the optional Method. - * @since 2.0 - */ - @Deprecated(since = "3.5", forRemoval = true) - public static Optional getMethod(Class type, String name, ResolvableType... parameterTypes) { - return Optional.ofNullable(findMethod(type, name, parameterTypes)); - } - /** * Returns the {@link Method} with the given name and parameters declared on the given type, if available. * @@ -557,18 +507,4 @@ public static Object getPrimitiveDefault(Class type) { throw new IllegalArgumentException(String.format("Primitive type %s not supported", type)); } - /** - * Loads the class with the given name using the given {@link ClassLoader}. - * - * @param name the name of the class to be loaded. - * @param classLoader the {@link ClassLoader} to use to load the class. - * @return the {@link Class} or {@literal null} in case the class can't be loaded for any reason. - * @since 2.5 - */ - @Nullable - @Deprecated(since = "3.5", forRemoval = true) - public static Class loadIfPresent(String name, ClassLoader classLoader) { - return org.springframework.data.util.ClassUtils.loadIfPresent(name, classLoader); - } - } diff --git a/src/main/java/org/springframework/data/web/querydsl/QuerydslPredicateArgumentResolverSupport.java b/src/main/java/org/springframework/data/web/querydsl/QuerydslPredicateArgumentResolverSupport.java index 096ad88a46..186e400071 100644 --- a/src/main/java/org/springframework/data/web/querydsl/QuerydslPredicateArgumentResolverSupport.java +++ b/src/main/java/org/springframework/data/web/querydsl/QuerydslPredicateArgumentResolverSupport.java @@ -28,7 +28,6 @@ import org.springframework.data.querydsl.binding.QuerydslBindingsFactory; import org.springframework.data.querydsl.binding.QuerydslPredicate; import org.springframework.data.querydsl.binding.QuerydslPredicateBuilder; -import org.springframework.data.util.CastUtils; import org.springframework.data.util.TypeInformation; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -90,6 +89,7 @@ public boolean supportsParameter(MethodParameter parameter) { return false; } + @SuppressWarnings({ "rawtypes", "unchecked" }) Predicate getPredicate(MethodParameter parameter, MultiValueMap queryParameters) { MergedAnnotations annotations = MergedAnnotations.from(parameter.getParameter()); @@ -98,7 +98,7 @@ Predicate getPredicate(MethodParameter parameter, MultiValueMap TypeInformation domainType = extractTypeInfo(parameter, predicateAnnotation).getRequiredActualType(); Optional>> bindingsAnnotation = predicateAnnotation.getValue("bindings") // - .map(CastUtils::cast); + .map(it -> (Class) it); QuerydslBindings bindings = bindingsAnnotation // .map(it -> bindingsFactory.createBindingsFor(domainType, it)) // diff --git a/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryMetadataUnitTests.java b/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryMetadataUnitTests.java index 07334749c2..05a4b85193 100755 --- a/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryMetadataUnitTests.java +++ b/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryMetadataUnitTests.java @@ -27,7 +27,6 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.RepositoryMetadata; -import org.springframework.data.repository.util.ClassUtils; import org.springframework.data.util.TypeInformation; /** @@ -142,12 +141,6 @@ static interface UserRepository extends CrudRepository { } /** - * Sample interface to serve two purposes: - *

    - *
  1. Check that {@link ClassUtils#getDomainClass(Class)} skips non {@link GenericDao} interfaces
  2. - *
  3. Check that {@link ClassUtils#getDomainClass(Class)} traverses interface hierarchy
  4. - *
- * * @author Oliver Gierke */ private interface SomeDao extends Serializable, UserRepository { diff --git a/src/test/java/org/springframework/data/repository/util/ClassUtilsUnitTests.java b/src/test/java/org/springframework/data/repository/util/ClassUtilsUnitTests.java deleted file mode 100755 index f271579610..0000000000 --- a/src/test/java/org/springframework/data/repository/util/ClassUtilsUnitTests.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2008-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.repository.util; - -import static org.assertj.core.api.Assertions.*; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Future; - -import org.junit.jupiter.api.Test; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.repository.Repository; -import org.springframework.scheduling.annotation.Async; - -/** - * Unit tests for {@link ClassUtils}. - * - * @author Oliver Gierke - * @author John Blum - */ -class ClassUtilsUnitTests { - - @Test - void rejectsInvalidReturnType() { - assertThatIllegalStateException().isThrownBy(() -> ClassUtils.assertReturnTypeAssignable( - SomeDao.class.getMethod("findByFirstname", Pageable.class, String.class), User.class)); - } - - @Test - void determinesValidFieldsCorrectly() { - - assertThat(ClassUtils.hasProperty(User.class, "firstname")).isTrue(); - assertThat(ClassUtils.hasProperty(User.class, "Firstname")).isTrue(); - assertThat(ClassUtils.hasProperty(User.class, "address")).isFalse(); - } - - @Test // DATACMNS-769 - void unwrapsWrapperTypesBeforeAssignmentCheck() throws Exception { - ClassUtils.assertReturnTypeAssignable(UserRepository.class.getMethod("findAsync", Pageable.class), - Page.class); - } - - @Test - public void numberOfOccurrencesForMultipleMethodParametersOfType() throws Exception { - - Method findByAddress = AnotherDao.class.getMethod("findByAddress", Pageable.class, Pageable.class); - - assertThat(ClassUtils.getNumberOfOccurrences(findByAddress, Pageable.class)).isEqualTo(2); - } - - @Test - public void numberOfOccurrencesForNoMethodParameterOfType() throws Exception { - - Method findByAddress = AnotherDao.class.getMethod("findByAddress", Pageable.class, Pageable.class); - - assertThat(ClassUtils.getNumberOfOccurrences(findByAddress, Sort.class)).isZero(); - assertThat(ClassUtils.getNumberOfOccurrences(findByAddress, Page.class)).isZero(); - } - - @Test - public void numberOfOccurrencesForSingleMethodParameterOfType() throws Exception { - - Method findByFirstname = SomeDao.class.getMethod("findByFirstname", Pageable.class, String.class); - - assertThat(ClassUtils.getNumberOfOccurrences(findByFirstname, Pageable.class)).isOne(); - assertThat(ClassUtils.getNumberOfOccurrences(findByFirstname, String.class)).isOne(); - } - - @SuppressWarnings("unused") - private class User { - - private String firstname; - - String getAddress() { - - return null; - } - } - - interface UserRepository extends Repository { - - @Async - Future> findAsync(Pageable pageable); - } - - interface SomeDao extends Serializable, UserRepository { - - Page findByFirstname(Pageable pageable, String firstname); - - GenericType someMethod(); - - List> anotherMethod(); - } - - interface AnotherDao extends Repository { - - Page findByAddress(Pageable pageableOne, Pageable pageableTwo); - - } - - class GenericType { - - } -}