Hi
I'm using latest springboot-starter-web version 2.7.5.
implementation 'org.springframework.boot:spring-boot-starter-web:2.7.5'
but I got a stackoverflow error when using the @Controller annotation.
I DON'T see the error when using @RestController.
Reproduce steps:
there are three class files: 1. Main.java
package org.test.example;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
- a interface
ControllerI
package org.test.example;
import org.springframework.web.bind.annotation.*;
public interface ControllerI {
@GetMapping("/greet/{user}")
String greeting(@PathVariable("user") String user);
}
- a simple impl class:
package org.test.example;
import org.springframework.stereotype.*;
@Controller
//@RestController
public class ControllerImpl implements ControllerI{
@Override
public String greeting(String user) {
return String.format("Hello" + user);
}
}
and when I using curl http://127.0.0.1:8080/greet/myname, it shows stackoverflowerror:
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.apache.catalina.core.ApplicationHttpRequest.getSession(ApplicationHttpRequest.java:585) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.apache.catalina.core.ApplicationHttpRequest.getSession(ApplicationHttpRequest.java:585) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:244) ~[tomcat-embed-core-9
Comment From: wilkinsona
When you use @RestController, the controller method's return value is used as the body of the response. When you use @Controller, the controller's return value is the name of a view that should be rendered. I suspect you don't have a view named greet myname and this is somehow triggering a bug in Tomcat. I don't think we can do anything about Tomcat's behavior and, from what you've shared thus far, I don't think it will occur if you return the name of a view that exists.
Comment From: gaoxingliang
Hi @wilkinsona Thanks for your explanation. Yes. The view is not found. I think the embedded tomcat should return a 404 error or some other error instead of a stackoverflow error. I will check more about the source code.
Comment From: gaoxingliang
I found the root cause is when we search the view in class RequestMappingHandlerAdapter It will try to find the matched modelAndView object. and because my url use a path variable and this cause the recursive call.
so for my case,
1. if the initial request is /greet/edward and then it will try to find the view edward under /greet. and then it goes into the controller and the controller will return :
Helloedward (see the source code here )and
2. then it will dispatch to the /greet/Helloedward and again, it will dispatch (by setting the mav.viewName) to /greet/HelloHelloedward (in DispatcherServlet and it will try to render it again in InternalResourceView)
and this cause the infinite loop.