Servlet filter added in Spring Boot's org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer may override HttpServletRequestWrapper.getInputStream() and return an object derived from ServletInputStream that is not assignment compatible with Tomcat's CoyoteInputStream.
Comment From: sbrannen
@sada-sigsci, do you have a concrete use case where you encountered a ClassCastException in conjunction with the TomcatHttpHandlerAdapter?
Comment From: sbrannen
Tentatively slated for 5.2.5 since this seems like a potential bug.
Comment From: sada-sigsci
Thank you for reviewing the PR. Yes, web application security servlet filter middleware we work on reads the POST body and inspects for any anomalies before the HTTP servlet can read the POST body. Unbuffered POST body can be read (ServletInputStream.markSupported() may return false) only once in the filter. So the servlet filter has to extend the ServletInputStream class and wrap the body already read in the filter.
Comment From: rstoyanchev
TomcatHttpHandlerAdapter is for use in WebFlux where direct use of the Servlet is not supported. It is expected to use WebFilter instead. For example Spring Security provides a WebFlux integration based on that.
As an aside, when Servlet 3.1 non-blocking I/O is used, as in WebFlux, quite a few other parts of the Servlet API should not be used, or would interfere if used.
Comment From: sada-sigsci
Example application is standard Reactive SpringBootApplication using embedded Tomcat instead of default Netty and customized using component WebServerFactoryCustomizer<TomcatReactiveWebServerFactory>.
Application was throwing ClassCastException when @RestController method tried to read @RequestBody.
TomcatHttpHandlerAdapter wrapped httpHandlerServlet and added to TomcatReactiveWebserver in spring-boot(TomcatReactiveWebServerFactory.java). This fix is required so the servlet httpHandlerServlet is able to read the POST body on behalf of application @RequestBody
Our middleware class derived from ServletInputStream overrides non-blocking i/o methods and ReadListener of servlets 3.1
Comment From: rstoyanchev
So you are wrapping ServletInputStream and don't want it (e.g. unwrapped and) read more efficiently via CoyoteInputStream writing directly to a ByteBuffer (vs via byte[] first)?