We have an eCommerce webapp with the front-end server and the API server being in separate EC2 Ubuntus. The API server exposes 168 API RESTFul endpoints using Spring MVC. Each class has the @RestController annotation. We have a problem with one of them.
When this endpoint (which is a PUT) is called by the front-end, we know that it is invoked in Spring, we see its effects in the database and the PDF file it generates, but then (every single time) it returns 404 to the browser which we see in the tomcat access logs, as well, even though it is invoked every time.. There is nothing extraordinary about this endpoint. All 168 endpoints look the same. They have the HTTP method, produces JSON and return ResponseEntity. I moved this endpoint to another new class, I changed its endpoint URI, I changed the method name, I removed everything from this method except for "return ResponseEntity.ok().body(new SomeObject())", but it always returns 404. Does Spring MVC do this or tomcat itself?
We use OpenJDK 11.0.11 9, tomcat 9.0.59, Spring Framework 5.3.16, Spring Security 5.6.2, javaee-api 8.0.1 and servlet 4.0. Here is the endpoint method:
@RestController
@RequestMapping(value = "/api/v1/drivers")
public class DriverAPIService
{
@PutMapping(value = "/delivered", produces = "application/json")
public ResponseEntity<OrderStatusResponseBean> markOrderAsDelivered(@RequestBody OrderStatusUpdateRequestBean requestBean, HttpServletRequest request, HttpServletResponse response, Model model)
{
try
{
return DriverService.markOrderAsDelivered(requestBean, request);
}
catch(Throwable e)
{
return ResponseEntity.badRequest().build();
}
}
}
Our tomcat config in the server.xml for the connectors is:
<Executor name="tomcatThreadPool" namePrefix="tomcat9-thread-" maxIdleTime="60000"
maxThreads="50" minSpareThreads="5"/>
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443" maxConnections="100" acceptCount="300"/>
<Connector executor="tomcatThreadPool" SSLEnabled="true" maxPostSize="5000000" port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol" scheme="https"
secure="true" compression="on" maxKeepAliveRequests="10" connectionTimeout="60000"
maxConnections="100" acceptCount="300" enableLookups="false" connectionUploadTimeout="120000" disableUploadTimeout="false">
<SSLHostConfig>
<Certificate certificateFile="conf/cert.pem" certificateKeyFile="conf/privkey.pem" certificateChainFile="conf/chain.pem" />
</SSLHostConfig>
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" compression="on" keepAliveTimeout="360000"/>
</Connector>
CodePudding user response:
404, it means the spring application does not have the uri which you request. I think you can check the log on the console when you start the application. You can search the log whether it contains the uri '/api/v1/drivers/delivered' or not.
if it does not have, it must be return 404. At the same same, I think you code is not right.
CodePudding user response:
Let's recapitulate what we have:
- Your service code is wrapped into a catch-all block, that will transform any inner exceptions into an http-400 response. Catch-alls are a code smell, but in this case it helps to exclude the possibility that the problem is deep in your service.
- The service code is executed (as you say), so the method lookup generally works.
IMHO the problem must be in the response processing. I suspect the HttpServletResponse
to be the problem here. There are only rare cases when it's really needed (streaming, cookies, etc.), but generally it causes more problems than it actually solves. So please remove any unneeded parameters from the method signature and try again.