spring-projects / spring-projects/spring-data-couchbase
returnType must not be null! when working with projections
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 284
- Forks
- 197
- PR merge metrics
- No merged PRs in 30d
Description
Hello, I am migrating from Spring Boot 2.2 (Spring Couchbase 3.x) to Spring Boot 2.7 (Spring Couchbase 4.x) and I am getting this exception:
java.lang.IllegalArgumentException: returnType must not be null!
at org.springframework.util.Assert.notNull(Assert.java:201) ~[spring-core-5.3.31.jar:5.3.31]
at org.springframework.data.couchbase.core.ExecutableFindByQueryOperationSupport$ExecutableFindByQuerySupport.as(ExecutableFindByQueryOperationSupport.java:124) ~[spring-data-couchbase-4.4.18.jar:4.4.18]
at org.springframework.data.couchbase.repository.query.AbstractCouchbaseQuery.lambda$getExecutionToWrap$1(AbstractCouchbaseQuery.java:126) ~[spring-data-couchbase-4.4.18.jar:4.4.18]
at org.springframework.data.couchbase.repository.query.CouchbaseQueryExecution$ResultProcessingExecution.execute(CouchbaseQueryExecution.java:84) ~[spring-data-couchbase-4.4.18.jar:4.4.18]
at org.springframework.data.couchbase.repository.query.AbstractCouchbaseQuery.doExecute(AbstractCouchbaseQuery.java:95) ~[spring-data-couchbase-4.4.18.jar:4.4.18]
at org.springframework.data.couchbase.repository.query.AbstractCouchbaseQueryBase.execute(AbstractCouchbaseQueryBase.java:133) ~[spring-data-couchbase-4.4.18.jar:4.4.18]
at org.springframework.data.couchbase.repository.query.AbstractCouchbaseQueryBase.execute(AbstractCouchbaseQueryBase.java:113) ~[spring-data-couchbase-4.4.18.jar:4.4.18]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:160) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:139) ~[spring-data-commons-2.7.18.jar:2.7.18]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.31.jar:5.3.31]
at org.springframework.data.couchbase.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:141) ~[spring-data-couchbase-4.4.18.jar:4.4.18]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.31.jar:5.3.31]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.31.jar:5.3.31]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.31.jar:5.3.31]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241) ~[spring-aop-5.3.31.jar:5.3.31]
at com.sun.proxy.$Proxy223.getDetails(Unknown Source) ~[?:?]
at com.example.UserController.getDetails(UserController.java:32) ~[classes/:?]
User Document:
@EqualsAndHashCode(callSuper = true)
@Document
@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@Valid
public class User extends ParentUser {
private String firstName;
private String lastName;
private String address;
private boolean isTest;
}
Projection Interface:
public final class Projections {
@Projection(name = "names", types = {User.class})
interface Names {
String getFirstName();
String getLastName();
}
}
User Repository
public interface UserRepository extends PagingAndSortingRepository<User, String> {
@Query("""
#{#n1ql.selectEntity} WHERE #{#n1ql.filter}
AND isTest = true
"""
)
List<Projections.Names> getDetails(@Param("isTest") boolean isTest);
}
User Controller
@RestController
@RequestMapping(value = "/users")
@RequiredArgsConstructor
public class UserController {
private final UserRepository repository;
@GetMapping(value = {"/find/test"}, produces = APPLICATION_JSON_VALUE)
public Projections.Names getDetails(@RequestParam("isTest") final boolean isTest) {
return repository.getDetails(isTest);
}
Can projections still be used?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ExecutableFindByQueryOperationSupport.as and AbstractCouchbaseQuery, using the provided UserRepository query and Projections.Names projection as the reproduction. Trace how the repository method's List<Projections.Names> return type is processed, then verify the behavior with the supplied controller call. Done means establishing whether interface projections are supported in this version and documenting or correcting the resulting behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100