Skip to content

spring-data-rest: repositories with void methods causing NullPointerException since SpringDoc 1.5.6 until the current 1.5.9 #1171

Closed
@baromojm

Description

@baromojm

Describe the bug
Swagger UI was working fine in my project until 1.5.5 (included), but since 1.5.6 (up to latest current version 1.5.9) it's throwing a NullPointerException when loading http://localhost:8080/swagger-ui.html. Stack trace follows:

java.lang.NullPointerException: null
        at org.springdoc.data.rest.utils.SpringDocDataRestUtils.buildTextUriContent(SpringDocDataRestUtils.java:417)
        at org.springdoc.data.rest.core.DataRestResponseService.buildSearchResponse(DataRestResponseService.java:121)
        at org.springdoc.data.rest.core.DataRestOperationService.buildSearchOperation(DataRestOperationService.java:230)
        at org.springdoc.data.rest.core.DataRestOperationService.buildOperation(DataRestOperationService.java:133)
        at org.springdoc.data.rest.core.DataRestRouterOperationService.buildRouterOperation(DataRestRouterOperationService.java:288)
        at org.springdoc.data.rest.core.DataRestRouterOperationService.buildRouterOperation(DataRestRouterOperationService.java:227)
        at org.springdoc.data.rest.core.DataRestRouterOperationService.buildRouterOperationList(DataRestRouterOperationService.java:193)
        at org.springdoc.data.rest.core.DataRestRouterOperationService.buildSearchRouterOperationList(DataRestRouterOperationService.java:148)
        at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.lambda$findSearchControllers$17(SpringRepositoryRestResourceProvider.java:366)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
        at java.base/java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1675)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
        at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.findSearchControllers(SpringRepositoryRestResourceProvider.java:366)
        at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.findSearchResourceMappings(SpringRepositoryRestResourceProvider.java:345)
        at org.springdoc.data.rest.SpringRepositoryRestResourceProvider.getRouterOperations(SpringRepositoryRestResourceProvider.java:249)
        at org.springdoc.webmvc.api.OpenApiResource.getPaths(OpenApiResource.java:203)
        at org.springdoc.api.AbstractOpenApiResource.getOpenApi(AbstractOpenApiResource.java:287)
        at org.springdoc.webmvc.api.OpenApiResource.openapiJson(OpenApiResource.java:176)
        at org.springdoc.webmvc.api.OpenApiWebMvcResource.openapiJson(OpenApiWebMvcResource.java:116)
        at org.springdoc.webmvc.api.MultipleOpenApiWebMvcResource.openapiJson(MultipleOpenApiWebMvcResource.java:93)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:204)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Thread.java:834)

To Reproduce
Spring Boot: 2.5.0 (issue also exists with 2.4.x)
springdoc-openapi-ui: 1.5.9 (issue also exists in all versions since 1.5.6 until 1.5.9)
springdoc-openapi-data-rest: 1.5.9
springdoc-openapi-security: 1.5.9

SpringdocConfig.java

@OpenAPIDefinition
@Configuration
public class SpringdocConfig {

  /**
   * Definition: app.
   * 
   * @return -
   */
  @Bean
  public GroupedOpenApi appOpenApi() {
    String[] packagesToScan = { "edu.cou.myapp.controller" };
    String[] pathsToMatch = { "/rest/**" };
    String[] pathsToExclude = { "/rest/caches/**", "/rest/export/**", "/rest/merida/**" };
    return GroupedOpenApi.builder().group("app").packagesToScan(packagesToScan).pathsToMatch(
        pathsToMatch).pathsToExclude(pathsToExclude).build();
  }

  /**
   * Definition: export.
   * 
   * @return -
   */
  @Bean
  public GroupedOpenApi exportOpenApi() {
    String[] paths = { "/rest/export/**" };
    return GroupedOpenApi.builder().group("export").pathsToMatch(paths).build();
  }

  /**
   * Definition: misc.
   * 
   * @return -
   */
  @Bean
  public GroupedOpenApi miscOpenApi() {
    String[] paths = { "/*", "/rest/caches/**", "/rest/merida/**", "/rest/tech/**" }; //NOSONAR
    return GroupedOpenApi.builder().group("misc").pathsToMatch(paths).build();
  }

  /**
   * OpenAPI Swagger-UI configuration.<br>
   * http://localhost:8080/swagger-ui.html<br>
   * http://localhost:8080/v3/api-docs<br>
   * 
   * @return -
   */
  @Bean
  public OpenAPI customOpenAPI() {
    final var locUrl = "http://localhost:8080";
    final var devUrl = "https://myapp-dev.cou.edu/myapp_back";
    final var testUrl = "https://myapp-test.cou.edu/myapp_back";
    final var preUrl = "https://myapp-pre.cou.edu/myapp_back";
    final var proUrl = "https://myapp.cou.edu/myapp_back";
    return new OpenAPI().addServersItem(new Server().url(locUrl)).addServersItem(new Server().url(
        devUrl)).addServersItem(new Server().url(testUrl)).addServersItem(new Server().url(preUrl))
        .addServersItem(new Server().url(proUrl)).info(new Info().title("MYAPP").description(
            "Whatever."))
        .components(new Components().addSecuritySchemes("bearer-key", new SecurityScheme().type(
            SecurityScheme.Type.HTTP).scheme("bearer")));
  }

}

Expected behavior
When loading http://localhost:8080/swagger-ui.html it shouldn't throw the NullPointerException.
Note: it worked fine until SpringDoc 1.5.5 (it fails with all version since 1.5.6 until the current 1.5.9)

Screenshots
image

Additional context
Project has Spring Data REST enabled.

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