Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search a repository that implements QueryDslPredicateExecutor by a related Entity doesn't work anymore [DATAREST-712] #1081

Closed
spring-projects-issues opened this issue Nov 24, 2015 · 4 comments
Assignees
Labels
type: bug

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Nov 24, 2015

Massimo Mangoni opened DATAREST-712 and commented

If you define a repository this way:

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
  Page<Person> findByAddress(@Param("address") Address address, Pageable p);
}

where Address in another Entity, you can invoke the search method like this:
http://localhost:8080/people/search/findByAddress?address=/addresses/1
and everything works like a charm.

Now suppose you want to use QueryDSL predicates on the repository, so the repository must implement QueryDslPredicateExecutor interface:

@RepositoryRestResource(collectionResourceRel = "people", path = "people")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long>, QueryDslPredicateExecutor<Person>
{
  Page<Person> findByAddress(@Param("address") Address address, Pageable p);
}

By implementing this interface something changes in the REST behaviour of the repository and if you try to invoke the same search method:
http://localhost:8080/people/search/findByAddress?address=/addresses/1
you get this exception:

org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.lang.Long for value '/addresses/1'; nested exception is java.lang.NumberFormatException: For input string: "/addresses/1"
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:176) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.data.repository.support.DomainClassConverter$ToEntityConverter.convert(DomainClassConverter.java:159) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.convertToPropertyPathSpecificType(QuerydslPredicateBuilder.java:217) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
	at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.getPredicate(QuerydslPredicateBuilder.java:109) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
	at org.springframework.data.rest.webmvc.config.QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.postProcess(QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver.java:88) ~[spring-data-rest-webmvc-2.4.1.RELEASE.jar:na]
	at org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver.resolveArgument(RootResourceInformationHandlerMethodArgumentResolver.java:92) ~[spring-data-rest-webmvc-2.4.1.RELEASE.jar:na]
	at org.springframework.data.rest.webmvc.config.RootResourceInformationHandlerMethodArgumentResolver.resolveArgument(RootResourceInformationHandlerMethodArgumentResolver.java:40) ~[spring-data-rest-webmvc-2.4.1.RELEASE.jar:na]
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:78) ~[spring-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	[...]
Caused by: java.lang.NumberFormatException: For input string: "/addresses/1"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_66]
	at java.lang.Long.parseLong(Long.java:578) ~[na:1.8.0_66]
	at java.lang.Long.valueOf(Long.java:803) ~[na:1.8.0_66]
	at org.springframework.util.NumberUtils.parseNumber(NumberUtils.java:197) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:61) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:48) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.GenericConversionService$ConverterFactoryAdapter.convert(GenericConversionService.java:425) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	... 60 common frames omitted

Trying to use the "previous" format (by passing the id of the related entity)
http://localhost:8080/people/search/findByAddress?address=1
doesn't work either (this used to work with 2.2.3.RELEASE):

java.lang.IllegalArgumentException: Cannot resolve URI 1. Is it local or remote? Only local URIs are resolvable.
	at org.springframework.data.rest.core.UriToEntityConverter.convert(UriToEntityConverter.java:114) ~[spring-data-rest-core-2.4.1.RELEASE.jar:na]
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
	at org.springframework.data.repository.support.ReflectionRepositoryInvoker.convert(ReflectionRepositoryInvoker.java:248) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
	at org.springframework.data.repository.support.ReflectionRepositoryInvoker.prepareParameters(ReflectionRepositoryInvoker.java:238) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
	at org.springframework.data.repository.support.ReflectionRepositoryInvoker.invokeQueryMethod(ReflectionRepositoryInvoker.java:203) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
	at org.springframework.data.rest.core.support.UnwrappingRepositoryInvokerFactory$UnwrappingRepositoryInvoker.invokeQueryMethod(UnwrappingRepositoryInvokerFactory.java:153) ~[spring-data-rest-core-2.4.1.RELEASE.jar:na]
	at org.springframework.data.querydsl.QuerydslRepositoryInvokerAdapter.invokeQueryMethod(QuerydslRepositoryInvokerAdapter.java:149) ~[spring-data-commons-1.11.1.RELEASE.jar:na]
	at org.springframework.data.rest.webmvc.RepositorySearchController.executeQueryMethod(RepositorySearchController.java:313) ~[spring-data-rest-webmvc-2.4.1.RELEASE.jar:na]
	at org.springframework.data.rest.webmvc.RepositorySearchController.executeSearch(RepositorySearchController.java:177) ~[spring-data-rest-webmvc-2.4.1.RELEASE.jar:na]

Affects: 2.4.1 (Gosling SR1)

Backported to: 2.4.2 (Gosling SR2)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 24, 2015

Oliver Drotbohm commented

That's actually a bug we introduced in 2.4.0 with the general support of Querydsl predicates on collection resources. I've tweaked this to now apply to exactly those (i.e. /customers etc.) so that they don't get applied to query executions by accident. Back ported into the Gosling maintenance branch. Feel free to give the snapshots a try

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 24, 2015

Massimo Mangoni commented

I confirm that with the snapshot version it works as expected. Thank you for the fix!

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 5, 2017

Robert Rackl commented

There is another scenario that results in exactly the same error: When an @Entity references itself, e.g. when you need to store a tree structure in the DB.

@Entity
public class NodeModel {
  public String nodeName;
  @ManyToOne(optional = false)
  @NotNull
  NodeModel parentNode;
  [...]
}

exposed as a @RepositoryRestResource

When you try to POST a new Node (with a link to an existing parent node)

{
   nodeName: "example name",
   parentNode: "/api/nodes/47"
}

then the exaxt same error message is thrown

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Jan 5, 2017

Robert Rackl commented

Sorry, my fault: You get the same error, when you misspell the reference to the parentNode and happen to append a string to it:

{
   nodeName: "example name",
   parentNode: "/api/nodes/47/someString"
}

The "someString" is completely wrong here. And also gives that error message

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug
Projects
None yet
Development

No branches or pull requests

2 participants