From 452954455929042d9571e2ab2398b895ea44e057 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 31 Mar 2023 10:34:12 +0200 Subject: [PATCH 1/3] prepare issue branch. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index ae51058767..cfc26da4e3 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 4.0.5-SNAPSHOT + 4.0.x-4351-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 58f03fd070..e320a63026 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 4.0.5-SNAPSHOT + 4.0.x-4351-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 6f606b1668..67b0dc3e37 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -15,7 +15,7 @@ org.springframework.data spring-data-mongodb-parent - 4.0.5-SNAPSHOT + 4.0.x-4351-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index c84052c381..929ccde3f7 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 4.0.5-SNAPSHOT + 4.0.x-4351-SNAPSHOT ../pom.xml From 092488082745d08215384a245f2e7a46b04033df Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 31 Mar 2023 10:32:36 +0200 Subject: [PATCH 2/3] Fix AOT processing for lazy loading jdk proxies This commit makes sure to use the ProxyFactory for retrieving the proxied interfaces. This makes sure to capture the exact interface order required when finally loading the proxy at runtime. --- .../aot/LazyLoadingProxyAotProcessor.java | 7 +-- .../core/convert/LazyLoadingProxyFactory.java | 16 ++++- ...LazyLoadingProxyAotProcessorUnitTests.java | 62 +++++++++++++++++++ 3 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessorUnitTests.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java index 0abeab70c9..070a0a4f5c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessor.java @@ -18,6 +18,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -25,7 +26,6 @@ import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.TypeReference; -import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.data.annotation.Reference; @@ -33,7 +33,6 @@ import org.springframework.data.mongodb.core.convert.LazyLoadingProxyFactory.LazyLoadingInterceptor; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.DocumentReference; -import org.springframework.data.util.TypeUtils; /** * @author Christoph Strobl @@ -66,9 +65,7 @@ public void registerLazyLoadingProxyIfNeeded(Class type, GenerationContext ge if (field.getType().isInterface()) { List> interfaces = new ArrayList<>( - TypeUtils.resolveTypesInSignature(ResolvableType.forField(field, type))); - - interfaces.add(0, org.springframework.data.mongodb.core.convert.LazyLoadingProxy.class); + Arrays.asList(LazyLoadingProxyFactory.prepareFactory(field.getType()).getProxiedInterfaces())); interfaces.add(org.springframework.aop.SpringProxy.class); interfaces.add(org.springframework.aop.framework.Advised.class); interfaces.add(org.springframework.core.DecoratingProxy.class); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java index 4f84d57e49..64f2f0a648 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/LazyLoadingProxyFactory.java @@ -90,7 +90,14 @@ public static Class resolveProxyType(Class propertyType, Supplier propertyType, Supplier interceptor) { + /** + * Create the {@link ProxyFactory} for the given type, already adding required additional interfaces. + * + * @param propertyType the type to proxy + * @return the proxy type. + * @since 4.0.5 + */ + public static ProxyFactory prepareFactory(Class propertyType) { ProxyFactory proxyFactory = new ProxyFactory(); @@ -100,6 +107,13 @@ private ProxyFactory prepareProxyFactory(Class propertyType, Supplier propertyType, Supplier interceptor) { + + ProxyFactory proxyFactory = prepareFactory(propertyType); proxyFactory.addAdvice(interceptor.get()); return proxyFactory; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessorUnitTests.java new file mode 100644 index 0000000000..dbcc4d8da0 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/aot/LazyLoadingProxyAotProcessorUnitTests.java @@ -0,0 +1,62 @@ +/* + * 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.data.mongodb.aot; + +import static org.assertj.core.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.aot.generate.ClassNameGenerator; +import org.springframework.aot.generate.DefaultGenerationContext; +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.generate.InMemoryGeneratedFiles; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.data.mongodb.core.mapping.DBRef; +import org.springframework.javapoet.ClassName; + +/** + * @author Christoph Strobl + */ +class LazyLoadingProxyAotProcessorUnitTests { + + @Test // GH-4351 + void registersProxyForLazyDbRefCorrectlyWhenTypeIsCollectionInterface() { + + GenerationContext ctx = new DefaultGenerationContext(new ClassNameGenerator(ClassName.get(this.getClass())), + new InMemoryGeneratedFiles()); + + new LazyLoadingProxyAotProcessor().registerLazyLoadingProxyIfNeeded(A.class, ctx); + + assertThat(ctx.getRuntimeHints()) + .satisfies(RuntimeHintsPredicates.proxies().forInterfaces(java.util.Collection.class, + org.springframework.data.mongodb.core.convert.LazyLoadingProxy.class, java.util.List.class, + org.springframework.aop.SpringProxy.class, org.springframework.aop.framework.Advised.class, + org.springframework.core.DecoratingProxy.class)::test); + } + + static class A { + + String id; + + @DBRef(lazy = true) // + List listRef; + } + + static class B { + String id; + } +} From e353e54bf698272d61093f527edcaf8538d32da2 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Fri, 31 Mar 2023 11:31:19 +0200 Subject: [PATCH 3/3] Fix testcase failing after upgrade --- .../support/SimpleReactiveMongoRepositoryUnitTests.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java index 0e66f26022..911aabfe70 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryUnitTests.java @@ -121,6 +121,9 @@ void shouldAddDefaultCollationToFindWithSortForExampleIfPresent() { void shouldAddDefaultCollationToFindOneForExampleIfPresent() { when(mongoOperations.find(any(), any(), any())).thenReturn(flux); + when(flux.buffer(anyInt())).thenReturn(flux); + when(flux.map(any())).thenReturn(flux); + when(flux.next()).thenReturn(mono); Collation collation = Collation.of("en_US");