Affects: 5.2.3.RELEASE
Describe the bug on one side we have a controller which is listening to a generic GET endpoint /api1/whatevertypes
@RestController
@RequestMapping(
value = "/api1",
produces = {"application/json"})
@AllArgsConstructor
@CrossOrigin(origins = "*")
@Slf4j
public class GenericApi {
@GetMapping(value = {"/{whatevertype}s")
ResponseEntity getList(
@PathVariable() final String whatevertype,
@RequestHeader HttpHeaders httpHeaders) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.contentType(MediaType.TEXT_PLAIN)
.body("1234");
}
}
on the other side we have Spring Integration http inbound-gateway which should listen to POST endpoint with the same path as above /api1/whatevertypes
<int-http:inbound-gateway request-channel="request-channel"
reply-channel="inbound-reply-channel"
supported-methods="POST"
path="/api1/{whatevertype}s"
request-payload-type="java.lang.String"
>
<int-http:request-mapping consumes="application/json" produces="application/json"/>
<int-http:header name="whatevertype" expression="#pathVariables.whatevertype"/>
</int-http:inbound-gateway>
when we call the POST endpoint with the path like "%/api1/mytypes" it throws the error: Request method 'POST' not supported ,an error <405 METHOD_NOT_ALLOWED> is thrown.
On debug we can see that both mappings exists but when spring is looping through it just tries to match the first map and throws an error if it doesn't find a match.
If we configure the order/prio (RequestMappingHandlerMapping) where spring i trying to resolve the path it is failing the other way round (POST is working GET doesn't).
I opened a ticket for Spring Integration (https://github.com/spring-projects/spring-integration/issues/3366) which were answered by a member with the following comment: Please, consider to raise this issue against https://github.com/spring-projects/spring-framework. The RequestMappingInfoHandlerMapping class is managed over there together with the mentioned throw new HttpRequestMethodNotSupportedException(request.getMethod(), methods); which is not handled to let us to try other HandlerMapping in the DispatcherServlet.
To Reproduce Set up a GET restcontroller with a generic path and in parallel set up an Spring Integration http inbound gateway with a POST method and same path as the GET restcontroller.
Call the POST endpoint leads to <405 METHOD_NOT_ALLOWED>
Expected behavior spring must loop over all possible mappings for matching before throwing an error.
Calling the POST and the GET resource with the configuration above works.
Comment From: artembilan
See my comment in the related Spring Integration issue: https://github.com/spring-projects/spring-integration/issues/3366#issuecomment-678306636
Comment From: artembilan
I probably override a handleNoMatch
in my IntegrationRequestMappingHandlerMapping
to return null
and some order
to make mine with higher precedence. This way the issue with mixed mappings is going to be fixed.
Comment From: rstoyanchev
I'm afraid this is by design. RequestMappingHandlerMapping
considers URL path match to be close enough match and raises a specific 4xx error to suggests what is actually supported. That is a helpful feature and we can't support both that as well as split URL path handling across different HandlerMapping instances.
@artembilan is IntegrationRequestMappingHandlerMapping
ordered ahead of the RequestMappingHandlerMapping
from the MVC config? If so, indeed you could return null from handleNoMatch but could (and probably will) become a regression for applications that currently rely on a helpful 4xx response.
Is there some way that the handling for this path can be unified under Spring Integration? I think Spring Data REST handles this with a custom controller stereotype annotation that makes the regular RequestMappingHandlerMapping
skip over such controllers.
Comment From: artembilan
Yeah... I see your point.
Since a RequestMappingHandlerMapping
is really designed for the @RequestMapping
handling, I'll probably go the way to improve docs for my IntegrationRequestMappingHandlerMapping
extension to say that the same path cannot be used for mapping here and there.
I think your concern about a regression is valid and if there is no MVC in the app, but just Spring Integration, we definitely going to lose the valuable info from the specific 4xx
error.
I don't think Spring Data REST use-case is relevant somehow here: we talk about mapping the same path Spring Integration and MVC ways. The HTTP mapping support was provided into Spring Integration day first: probably that is not going to be a good idea to force people to configure the HTTP endpoints under some common context path... In fact this doesn't sound reasonable to mix MVC and Integration in the same application, especially when we configure the same path in both places...
So, now after more thinking I'm more up to just document such a limitation which is logical to avoid the same path in different places.
In fact it even doesn't work when we have a regular SimpleUrlHandlerMapping
mixed with the mentioned MVC because it has a lower order...
In my opinion we can close this issue like Work as Designed
. I'll rework my Spring Integration PR into docs instead.
Thank you for feedback @rstoyanchev !
Comment From: rstoyanchev
Okay thanks @artembilan.