Skip to content

NPE in DataRestResponseService.findSearchReturnType #1004

Closed
@FranPregernik

Description

@FranPregernik

Describe the bug
The example is under the repository https://github.com/FranPregernik/springdoc-npe-issue

In the example I have a Bank entity (id, code, name) and a standard BankRepository (JpaRepository) with an additional interface CodeLookupRepository with a method findOneByCode.

A subset of my entites have the code column and I need to use this findOneByCode method elsewhere in code (there I am using CodeLookupRepository instead of the concrete BankRepository).

When I have the same findOnByCode inside BankRepository the OpenApi is generated.
When I remove it from BankRepository and just have it in CodeLookupRepository then a NPE occurs:

2021-01-04 10:00:44.584 ERROR 733105 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null
	at java.lang.Class.isAssignableFrom(Native Method) ~[na:1.8.0_265]
	at org.springdoc.data.rest.core.DataRestResponseService.findSearchReturnType(DataRestResponseService.java:171) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.core.DataRestResponseService.buildSearchResponse(DataRestResponseService.java:88) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.core.DataRestOperationService.buildSearchOperation(DataRestOperationService.java:196) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.core.DataRestOperationService.buildOperation(DataRestOperationService.java:121) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.core.DataRestRouterOperationService.buildRouterOperation(DataRestRouterOperationService.java:238) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.core.DataRestRouterOperationService.buildRouterOperationList(DataRestRouterOperationService.java:185) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.core.DataRestRouterOperationService.buildSearchRouterOperationList(DataRestRouterOperationService.java:140) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.lambda$findSearchControllers$15(SpringRepositoryRestResourceProvider.java:299) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:1.8.0_265]
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[na:1.8.0_265]
	at java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1628) ~[na:1.8.0_265]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) ~[na:1.8.0_265]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) ~[na:1.8.0_265]
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:1.8.0_265]
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:1.8.0_265]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_265]
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) ~[na:1.8.0_265]
	at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.findSearchControllers(SpringRepositoryRestResourceProvider.java:299) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.findSearchResourceMappings(SpringRepositoryRestResourceProvider.java:279) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.getRouterOperations(SpringRepositoryRestResourceProvider.java:221) ~[springdoc-openapi-data-rest-1.5.2.jar:1.5.2]
	at org.springdoc.webmvc.api.OpenApiResource.getPaths(OpenApiResource.java:217) ~[springdoc-openapi-webmvc-core-1.5.2.jar:1.5.2]
	at org.springdoc.api.AbstractOpenApiResource.getOpenApi(AbstractOpenApiResource.java:283) ~[springdoc-openapi-common-1.5.2.jar:1.5.2]
	at org.springdoc.webmvc.api.OpenApiResource.openapiJson(OpenApiResource.java:172) ~[springdoc-openapi-webmvc-core-1.5.2.jar:1.5.2]
	at org.springdoc.webmvc.api.OpenApiWebMvcResource.openapiJson(OpenApiWebMvcResource.java:116) ~[springdoc-openapi-webmvc-core-1.5.2.jar:1.5.2]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_265]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_265]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_265]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_265]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.2.jar:5.3.2]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.2.jar:5.3.2]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.2.jar:5.3.2]
...

I traced this to the resolve method where it identifies the return type as EntityT and calling getRawClass() on that type returns a null.

To Reproduce
Steps to reproduce the behavior:

  • Checkout repo
  • Run spring boot app
  • Open the standard swagger-ui.html

Expected behavior

  • I expect the CodeLookupRepository<EntityT, KeyT> method return types to be resolved just like the standard JpaRepository<Entity, ID> generics are resolved
  • Having the findOneByCode method in BankRepository or in CodeLookupRepository should produce the same OpenApi spec

** Additional info **
This is an amazing project! Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions