diff --git a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBeanRuntimeHints.java b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBeanRuntimeHints.java index 811c8eaab42..3887667ae3a 100644 --- a/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBeanRuntimeHints.java +++ b/spring-context-support/src/main/java/org/springframework/scheduling/quartz/SchedulerFactoryBeanRuntimeHints.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 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. @@ -37,7 +37,7 @@ class SchedulerFactoryBeanRuntimeHints implements RuntimeHintsRegistrar { private static final String SCHEDULER_FACTORY_CLASS_NAME = "org.quartz.impl.StdSchedulerFactory"; - private final ReflectiveRuntimeHintsRegistrar reflectiveRegistrar = new ReflectiveRuntimeHintsRegistrar(); + private static final ReflectiveRuntimeHintsRegistrar registrar = new ReflectiveRuntimeHintsRegistrar(); @Override @@ -49,7 +49,7 @@ class SchedulerFactoryBeanRuntimeHints implements RuntimeHintsRegistrar { .registerType(TypeReference.of(SCHEDULER_FACTORY_CLASS_NAME), this::typeHint) .registerTypes(TypeReference.listOf(ResourceLoaderClassLoadHelper.class, LocalTaskExecutorThreadPool.class, LocalDataSourceJobStore.class), this::typeHint); - this.reflectiveRegistrar.registerRuntimeHints(hints, LocalTaskExecutorThreadPool.class); + registrar.registerRuntimeHints(hints, LocalTaskExecutorThreadPool.class); } private void typeHint(Builder typeHint) { diff --git a/spring-context/src/main/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessor.java b/spring-context/src/main/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessor.java index 238350ffc22..9cba020aef5 100644 --- a/spring-context/src/main/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 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. @@ -39,7 +39,8 @@ import org.springframework.beans.factory.support.RegisteredBean; */ class ReflectiveProcessorBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor { - private static final ReflectiveRuntimeHintsRegistrar REGISTRAR = new ReflectiveRuntimeHintsRegistrar(); + private static final ReflectiveRuntimeHintsRegistrar registrar = new ReflectiveRuntimeHintsRegistrar(); + @Override public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { @@ -49,7 +50,9 @@ class ReflectiveProcessorBeanFactoryInitializationAotProcessor implements BeanFa return new ReflectiveProcessorBeanFactoryInitializationAotContribution(beanTypes); } - private static class ReflectiveProcessorBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution { + + private static class ReflectiveProcessorBeanFactoryInitializationAotContribution + implements BeanFactoryInitializationAotContribution { private final Class[] types; @@ -60,9 +63,8 @@ class ReflectiveProcessorBeanFactoryInitializationAotProcessor implements BeanFa @Override public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) { RuntimeHints runtimeHints = generationContext.getRuntimeHints(); - REGISTRAR.registerRuntimeHints(runtimeHints, this.types); + registrar.registerRuntimeHints(runtimeHints, this.types); } - } } diff --git a/spring-core/src/main/java/org/springframework/aot/hint/annotation/Reflective.java b/spring-core/src/main/java/org/springframework/aot/hint/annotation/Reflective.java index e12ceae9d49..02dcdcef6ba 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/annotation/Reflective.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/annotation/Reflective.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 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. @@ -39,8 +39,7 @@ import org.springframework.core.annotation.AliasFor; * @see ReflectiveRuntimeHintsRegistrar * @see RegisterReflectionForBinding @RegisterReflectionForBinding */ -@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.CONSTRUCTOR, - ElementType.FIELD, ElementType.METHOD }) +@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Reflective { diff --git a/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java b/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java index 0d1e56f259f..0f027782a5a 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/annotation/RegisterReflectionForBinding.java @@ -36,7 +36,7 @@ import org.springframework.core.annotation.AliasFor; * *
  * @Configuration
- * @RegisterReflectionForBinding({ Foo.class, Bar.class })
+ * @RegisterReflectionForBinding({Foo.class, Bar.class})
  * public class MyConfig {
  *     // ...
  * }
@@ -78,7 +78,7 @@ public @interface RegisterReflectionForBinding { /** * Classes for which reflection hints should be registered. *

At least one class must be specified either via {@link #value} or - * {@link #classes}. + * {@code #classes}. * @see #value() */ @AliasFor("value") diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java b/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java index 5ebc6ac8029..603029ad429 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/SharedEntityManagerCreator.java @@ -395,6 +395,9 @@ public abstract class SharedEntityManagerCreator { else if (targetClass.isInstance(proxy)) { return proxy; } + else { + return this.target.unwrap(targetClass); + } } case "getOutputParameterValue" -> { if (this.entityManager == null) { diff --git a/spring-orm/src/test/java/org/springframework/orm/jpa/SharedEntityManagerCreatorTests.java b/spring-orm/src/test/java/org/springframework/orm/jpa/SharedEntityManagerCreatorTests.java index fa667937654..7bc31f679da 100644 --- a/spring-orm/src/test/java/org/springframework/orm/jpa/SharedEntityManagerCreatorTests.java +++ b/spring-orm/src/test/java/org/springframework/orm/jpa/SharedEntityManagerCreatorTests.java @@ -105,15 +105,20 @@ class SharedEntityManagerCreatorTests { void deferredQueryWithUpdate() { EntityManagerFactory emf = mock(); EntityManager targetEm = mock(); - Query query = mock(); + Query targetQuery = mock(); given(emf.createEntityManager()).willReturn(targetEm); - given(targetEm.createQuery("x")).willReturn(query); + given(targetEm.createQuery("x")).willReturn(targetQuery); given(targetEm.isOpen()).willReturn(true); + given((Query) targetQuery.unwrap(targetQuery.getClass())).willReturn(targetQuery); EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf); - em.createQuery("x").executeUpdate(); + Query query = em.createQuery("x"); + assertThat((Query) query.unwrap(null)).isSameAs(targetQuery); + assertThat((Query) query.unwrap(targetQuery.getClass())).isSameAs(targetQuery); + assertThat(query.unwrap(Query.class)).isSameAs(query); + query.executeUpdate(); - verify(query).executeUpdate(); + verify(targetQuery).executeUpdate(); verify(targetEm).close(); } @@ -121,15 +126,20 @@ class SharedEntityManagerCreatorTests { void deferredQueryWithSingleResult() { EntityManagerFactory emf = mock(); EntityManager targetEm = mock(); - Query query = mock(); + Query targetQuery = mock(); given(emf.createEntityManager()).willReturn(targetEm); - given(targetEm.createQuery("x")).willReturn(query); + given(targetEm.createQuery("x")).willReturn(targetQuery); given(targetEm.isOpen()).willReturn(true); + given((Query) targetQuery.unwrap(targetQuery.getClass())).willReturn(targetQuery); EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf); - em.createQuery("x").getSingleResult(); + Query query = em.createQuery("x"); + assertThat((Query) query.unwrap(null)).isSameAs(targetQuery); + assertThat((Query) query.unwrap(targetQuery.getClass())).isSameAs(targetQuery); + assertThat(query.unwrap(Query.class)).isSameAs(query); + query.getSingleResult(); - verify(query).getSingleResult(); + verify(targetQuery).getSingleResult(); verify(targetEm).close(); } @@ -137,15 +147,20 @@ class SharedEntityManagerCreatorTests { void deferredQueryWithResultList() { EntityManagerFactory emf = mock(); EntityManager targetEm = mock(); - Query query = mock(); + Query targetQuery = mock(); given(emf.createEntityManager()).willReturn(targetEm); - given(targetEm.createQuery("x")).willReturn(query); + given(targetEm.createQuery("x")).willReturn(targetQuery); given(targetEm.isOpen()).willReturn(true); + given((Query) targetQuery.unwrap(targetQuery.getClass())).willReturn(targetQuery); EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf); - em.createQuery("x").getResultList(); + Query query = em.createQuery("x"); + assertThat((Query) query.unwrap(null)).isSameAs(targetQuery); + assertThat((Query) query.unwrap(targetQuery.getClass())).isSameAs(targetQuery); + assertThat(query.unwrap(Query.class)).isSameAs(query); + query.getResultList(); - verify(query).getResultList(); + verify(targetQuery).getResultList(); verify(targetEm).close(); } @@ -153,15 +168,20 @@ class SharedEntityManagerCreatorTests { void deferredQueryWithResultStream() { EntityManagerFactory emf = mock(); EntityManager targetEm = mock(); - Query query = mock(); + Query targetQuery = mock(); given(emf.createEntityManager()).willReturn(targetEm); - given(targetEm.createQuery("x")).willReturn(query); + given(targetEm.createQuery("x")).willReturn(targetQuery); given(targetEm.isOpen()).willReturn(true); + given((Query) targetQuery.unwrap(targetQuery.getClass())).willReturn(targetQuery); EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf); - em.createQuery("x").getResultStream(); + Query query = em.createQuery("x"); + assertThat((Query) query.unwrap(null)).isSameAs(targetQuery); + assertThat((Query) query.unwrap(targetQuery.getClass())).isSameAs(targetQuery); + assertThat(query.unwrap(Query.class)).isSameAs(query); + query.getResultStream(); - verify(query).getResultStream(); + verify(targetQuery).getResultStream(); verify(targetEm).close(); } @@ -169,11 +189,11 @@ class SharedEntityManagerCreatorTests { void deferredStoredProcedureQueryWithIndexedParameters() { EntityManagerFactory emf = mock(); EntityManager targetEm = mock(); - StoredProcedureQuery query = mock(); + StoredProcedureQuery targetQuery = mock(); given(emf.createEntityManager()).willReturn(targetEm); - given(targetEm.createStoredProcedureQuery("x")).willReturn(query); - willReturn("y").given(query).getOutputParameterValue(0); - willReturn("z").given(query).getOutputParameterValue(2); + given(targetEm.createStoredProcedureQuery("x")).willReturn(targetQuery); + willReturn("y").given(targetQuery).getOutputParameterValue(0); + willReturn("z").given(targetQuery).getOutputParameterValue(2); given(targetEm.isOpen()).willReturn(true); EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf); @@ -187,12 +207,12 @@ class SharedEntityManagerCreatorTests { spq.getOutputParameterValue(1)); assertThat(spq.getOutputParameterValue(2)).isEqualTo("z"); - verify(query).registerStoredProcedureParameter(0, String.class, ParameterMode.OUT); - verify(query).registerStoredProcedureParameter(1, Number.class, ParameterMode.IN); - verify(query).registerStoredProcedureParameter(2, Object.class, ParameterMode.INOUT); - verify(query).execute(); + verify(targetQuery).registerStoredProcedureParameter(0, String.class, ParameterMode.OUT); + verify(targetQuery).registerStoredProcedureParameter(1, Number.class, ParameterMode.IN); + verify(targetQuery).registerStoredProcedureParameter(2, Object.class, ParameterMode.INOUT); + verify(targetQuery).execute(); verify(targetEm).close(); - verifyNoMoreInteractions(query); + verifyNoMoreInteractions(targetQuery); verifyNoMoreInteractions(targetEm); } @@ -200,11 +220,11 @@ class SharedEntityManagerCreatorTests { void deferredStoredProcedureQueryWithNamedParameters() { EntityManagerFactory emf = mock(); EntityManager targetEm = mock(); - StoredProcedureQuery query = mock(); + StoredProcedureQuery targetQuery = mock(); given(emf.createEntityManager()).willReturn(targetEm); - given(targetEm.createStoredProcedureQuery("x")).willReturn(query); - willReturn("y").given(query).getOutputParameterValue("a"); - willReturn("z").given(query).getOutputParameterValue("c"); + given(targetEm.createStoredProcedureQuery("x")).willReturn(targetQuery); + willReturn("y").given(targetQuery).getOutputParameterValue("a"); + willReturn("z").given(targetQuery).getOutputParameterValue("c"); given(targetEm.isOpen()).willReturn(true); EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf); @@ -218,12 +238,12 @@ class SharedEntityManagerCreatorTests { spq.getOutputParameterValue("b")); assertThat(spq.getOutputParameterValue("c")).isEqualTo("z"); - verify(query).registerStoredProcedureParameter("a", String.class, ParameterMode.OUT); - verify(query).registerStoredProcedureParameter("b", Number.class, ParameterMode.IN); - verify(query).registerStoredProcedureParameter("c", Object.class, ParameterMode.INOUT); - verify(query).execute(); + verify(targetQuery).registerStoredProcedureParameter("a", String.class, ParameterMode.OUT); + verify(targetQuery).registerStoredProcedureParameter("b", Number.class, ParameterMode.IN); + verify(targetQuery).registerStoredProcedureParameter("c", Object.class, ParameterMode.INOUT); + verify(targetQuery).execute(); verify(targetEm).close(); - verifyNoMoreInteractions(query); + verifyNoMoreInteractions(targetQuery); verifyNoMoreInteractions(targetEm); } diff --git a/spring-web/src/main/java/org/springframework/web/client/NoOpResponseErrorHandler.java b/spring-web/src/main/java/org/springframework/web/client/NoOpResponseErrorHandler.java index c6f7da40a4d..daa735ebaec 100644 --- a/spring-web/src/main/java/org/springframework/web/client/NoOpResponseErrorHandler.java +++ b/spring-web/src/main/java/org/springframework/web/client/NoOpResponseErrorHandler.java @@ -36,7 +36,7 @@ public final class NoOpResponseErrorHandler implements ResponseErrorHandler { @Override public void handleError(ClientHttpResponse response) throws IOException { - + // never actually called } } diff --git a/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java b/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java index 49fc6d8eee1..dceabf07146 100644 --- a/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java +++ b/spring-web/src/main/java/org/springframework/web/filter/ForwardedHeaderFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 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. @@ -481,7 +481,6 @@ public class ForwardedHeaderFilter extends OncePerRequestFilter { @Override public void sendRedirect(String location) throws IOException { - UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(location); UriComponents uriComponents = builder.build();