knelson59406
knelson59406

Reputation: 891

Spring Boot 3.4.1: Why Is spring.data.rest.base-path Causing 404 Errors? Possible Conflict with DevTools?

I recently upgraded my Spring Boot application from version 3.4.0 to 3.4.1 and encountered an issue with Spring Data REST.

In version 3.4.0 (and all previous 3.x versions), the following configuration worked as expected:

spring.data.rest.base-path=/api

With this property set, I could successfully access my REST API resources via: http://localhost:8080/api/todos

However, after upgrading to Spring Boot 3.4.1, this configuration no longer works. Attempting to access the API endpoints with the configuration spring.data.rest.base-path results in a 404 Not Found error. I suspect there might be a conflict with the Spring Boot DevTools dependency, as removing it resolves the issue.

Environment

How To Reproduce

I have a reproducible example at this repo

  1. Clone the git repo: https://github.com/knelson59406/spring-data-rest-demo
  2. Move into the project directory
  3. Run the Spring Boot app: mvn clean spring-boot:run
  4. Access the REST API

You will receive a 404 Not Found error.

Observed Behavior

Accessing the API endpoint results in a Whitelabel Error Page:

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

There was an unexpected error (type=Not Found, status=404).
No static resource api/todos.
org.springframework.web.servlet.resource.NoResourceFoundException: No static resource api/todos.
    at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:585)
    at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:52)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
    at java.base/java.lang.Thread.run(Thread.java:1575)

Expected Behavior:

I expected a successful response with 200 status code and following output:

{
  "_embedded": {
    "todos": []
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/todos?page=0&size=20"
    },
    "profile": {
      "href": "http://localhost:8080/api/profile/todos"
    }
  },
  "page": {
    "size": 20,
    "totalElements": 0,
    "totalPages": 0,
    "number": 0
  }
}

Possible Conflict with DevTools:

After troubleshooting, I discovered that removing the Spring Boot DevTools dependency resolves the issue. For example:

        <!--
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        -->

Once the DevTools dependency is removed, the application runs successfully. You are able to access the endpoint http://localhost:8080/api/todos and it returns a 200 response as expected along with the following content.

{
  "_embedded": {
    "todos": []
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/todos?page=0&size=20"
    },
    "profile": {
      "href": "http://localhost:8080/api/profile/todos"
    }
  },
  "page": {
    "size": 20,
    "totalElements": 0,
    "totalPages": 0,
    "number": 0
  }
}

What I’ve Tried

Questions

  1. Has the behavior of the spring.data.rest.base-path property changed in Spring Boot 3.4.1?
  2. Could there be a known conflict between Spring Data REST and Spring Boot DevTools in this version 3.4.1?
  3. Is this a bug, or has the configuration been deprecated/modified?
  4. Is there a problem with my code or configuration related to this issue?
  5. Are there any alternative workarounds or fixes for this issue?

Any guidance or workarounds would be greatly appreciated!

I also filed this as a bug with the Spring Boot project team.

Upvotes: 1

Views: 769

Answers (1)

Shaneshay
Shaneshay

Reputation: 1

Yes, the issue appears to be a bug introduced in latest spring 3.4.1 released on 19th Dec 2024. Two possible workarounds are,

  1. Downgrading spring-boot to 3.4.0 by changing the version in pom.xml file and reloading the maven changes.
  2. Removing spring dev-tools dependency from pom.xml file if you want to continue to use spring 3.4.1

(Ref: https://www.udemy.com/course/spring-hibernate-tutorial/learn/lecture/36836512#questions/22798063)

Upvotes: 0

Related Questions