Skip to content

Commit a746886

Browse files
back of when detecting unresolvable return type
1 parent f8014b6 commit a746886

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

src/main/java/org/springframework/data/repository/aot/generate/AotRepositoryCreator.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import org.apache.commons.logging.Log;
2828
import org.apache.commons.logging.LogFactory;
2929
import org.jspecify.annotations.Nullable;
30-
30+
import org.springframework.core.ResolvableType;
3131
import org.springframework.data.projection.ProjectionFactory;
3232
import org.springframework.data.repository.core.RepositoryInformation;
3333
import org.springframework.data.repository.core.support.RepositoryComposition;
@@ -298,6 +298,19 @@ private void contributeMethod(Method method, @Nullable MethodContributorFactory
298298
return;
299299
}
300300

301+
// TODO: should we do this even before we do something with the method to protect the modules?
302+
if (ResolvableType.forMethodReturnType(method, repositoryInformation.getRepositoryInterface())
303+
.hasUnresolvableGenerics()) {
304+
305+
if (logger.isTraceEnabled()) {
306+
logger.trace("Skipping method [%s.%s] contribution, unresolvable generic return"
307+
.formatted(repositoryInformation.getRepositoryInterface().getName(), method.getName()));
308+
}
309+
310+
generationMetadata.addDelegateMethod(method, contributor);
311+
return;
312+
}
313+
301314
if (contributor.contributesMethodSpec() && !repositoryInformation.isReactiveRepository()) {
302315
generationMetadata.addRepositoryMethod(method, contributor);
303316
} else {

src/test/java/org/springframework/data/repository/aot/generate/AotRepositoryCreatorUnitTests.java

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,21 @@
1515
*/
1616
package org.springframework.data.repository.aot.generate;
1717

18-
import static org.assertj.core.api.Assertions.*;
19-
import static org.mockito.Mockito.*;
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.mockito.Mockito.doReturn;
20+
import static org.mockito.Mockito.mock;
2021

2122
import example.UserRepository.User;
2223

2324
import java.util.List;
25+
import java.util.Map;
2426
import java.util.TimeZone;
2527

2628
import javax.lang.model.element.Modifier;
2729

2830
import org.junit.jupiter.api.BeforeEach;
2931
import org.junit.jupiter.api.Test;
3032
import org.mockito.Answers;
31-
3233
import org.springframework.aot.generate.Generated;
3334
import org.springframework.aot.hint.TypeReference;
3435
import org.springframework.core.ResolvableType;
@@ -40,6 +41,7 @@
4041
import org.springframework.data.repository.core.RepositoryInformation;
4142
import org.springframework.data.repository.core.support.AnnotationRepositoryMetadata;
4243
import org.springframework.data.repository.core.support.RepositoryFragment;
44+
import org.springframework.data.repository.query.DefaultParameters;
4345
import org.springframework.data.repository.query.QueryMethod;
4446
import org.springframework.javapoet.ClassName;
4547
import org.springframework.javapoet.JavaFile;
@@ -179,8 +181,8 @@ void shouldContributeFragmentImplementationMetadata() {
179181
AnnotationRepositoryMetadata.getMetadata(QuerydslUserRepository.class), CrudRepository.class,
180182
List.of(RepositoryFragment.structural(QuerydslPredicateExecutor.class, DummyQuerydslPredicateExecutor.class)));
181183

182-
AotRepositoryCreator creator = AotRepositoryCreator
183-
.forRepository(repositoryInformation, "Commons", new SpelAwareProxyProjectionFactory());
184+
AotRepositoryCreator creator = AotRepositoryCreator.forRepository(repositoryInformation, "Commons",
185+
new SpelAwareProxyProjectionFactory());
184186
creator.contributeMethods(method -> null);
185187
AotRepositoryCreator.AotBundle bundle = doCreate(creator);
186188

@@ -229,6 +231,38 @@ void usesGenericConstructorArguments() {
229231
"public %s(List<Metric> param1, String param2, Object ctorScoped)".formatted(targetType.getSimpleName()));
230232
}
231233

234+
@Test // GH-3374
235+
void skipsMethodWithUnresolvableGenericReturnType() {
236+
237+
SpelAwareProxyProjectionFactory spelAwareProxyProjectionFactory = new SpelAwareProxyProjectionFactory();
238+
AotRepositoryInformation repositoryInformation = new AotRepositoryInformation(
239+
AnnotationRepositoryMetadata.getMetadata(UserRepository.class), CrudRepository.class,
240+
List.of(RepositoryFragment.structural(QuerydslPredicateExecutor.class, DummyQuerydslPredicateExecutor.class)));
241+
242+
AotRepositoryCreator repositoryCreator = AotRepositoryCreator.forRepository(repositoryInformation, "Commons",
243+
spelAwareProxyProjectionFactory);
244+
repositoryCreator.contributeMethods(method -> {
245+
246+
QueryMethod queryMethod = new QueryMethod(method, repositoryInformation, spelAwareProxyProjectionFactory,
247+
DefaultParameters::new);
248+
return new MethodContributor<>(queryMethod, Map::of) {
249+
@Override
250+
public MethodSpec contribute(AotQueryMethodGenerationContext context) {
251+
return MethodSpec.methodBuilder(context.getMethod().getName()).addCode("// 1 = 1").build();
252+
}
253+
254+
@Override
255+
public boolean contributesMethodSpec() {
256+
return true;
257+
}
258+
};
259+
260+
});
261+
262+
// same package as source repo
263+
assertThat(generate(repositoryCreator)).contains("someMethod()").doesNotContain("findByFirstname()");
264+
}
265+
232266
private AotRepositoryCreator.AotBundle doCreate(AotRepositoryCreator creator) {
233267
return creator.create(getTypeSpecBuilder(creator));
234268
}
@@ -263,6 +297,8 @@ private static TypeSpec.Builder getTypeSpecBuilder(ClassName className) {
263297
interface UserRepository extends org.springframework.data.repository.Repository<User, String> {
264298

265299
String someMethod();
300+
301+
<T> List<T> findByFirstname(String firstname, Class<T> type);
266302
}
267303

268304
interface QuerydslUserRepository

0 commit comments

Comments
 (0)