spring-projects / spring-projects/spring-data-commons

QuerydslPredicateArgumentResolver does not handle annotations in a spring-like way [DATACMNS-1334]

Open
#1,772 0 comments 0 reactions 1 assignee View on GitHub

@odrotbohm is already working on this.

Since Dec 30, 2020.

in: repository type: bug
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.