spring-projects / spring-projects/spring-data-commons
QuerydslPredicateArgumentResolver does not handle annotations in a spring-like way [DATACMNS-1334]
@odrotbohm is already working on this.
Since Dec 30, 2020.
- Dominant language
- Java
- Stars
- 838
- Forks
- 730
- PR merge metrics
- No merged PRs in 30d
Description
George Hartz opened DATACMNS-1334 and commented
The QuerydslPredicateArgumentResolver class does not handle searching for @QuerydslPredicate annotations in the same way most Spring annotation searching happens – specifically it doesn't appear to find them when defined on an interface, but rather just the concrete method. Additionally, the annotation metadata implies it can be placed on a type (and it can) but it isn't used in that case.
Our specific use case that ran into this is the use of a method on a generic-typed base class that takes a Predicate parameter. The find method's return type is the generic type, but because of erasure, is actually Object at runtime. The Querydsl support attempts to load a QObject type for the Predicate, which does't exist.
One would assume that annotating the class would provide a fall-back type for those scenarios, or a @QuerydslPredicate annotation on an interface declaration that the base class is implementing would be picked up, but neither are true.
I'm not set up to be able to submit a patch for this, because we don't want to be running a custom Spring build. The way we fixed it was to not register the QuerydslPredicateArgumentResolver class, and to register a version with the extractTypeInfo method reimplemented as such:
static TypeInformation<?> extractTypeInfo(MethodParameter parameter) {
Optional<QuerydslPredicate> annotation = Optional
.ofNullable(AnnotationUtils.findAnnotation(parameter.getMethod(), QuerydslPredicate.class));
if (!annotation.isPresent())
annotation = Optional
.ofNullable(AnnotationUtils.findAnnotation(parameter.getContainingClass(), QuerydslPredicate.class));
return annotation.filter(it -> !Object.class.equals(it.root()))//
.<TypeInformation<?>> map(it -> ClassTypeInformation.from(it.root()))//
.orElseGet(() -> detectDomainType(parameter));
}
Using AnnotationUtils means the "normal" spring logic of finding annotations is used, and we added a fall-back to look on the type hierarchy for the annotation, if one wasn't found. Only after that does the return type get used.
Affects: 2.0.7 (Kay SR7)
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.
Assessment
This issue has not been assessed yet.