We have an endpoint which can return different responses depending on the Accept header. In particular, it can return zip files, video files, or audio files.
Mapping 1:
@RequestMapping(value = "endpoint",
method = RequestMethod.GET,
produces = {"video/*", "audio/*"})
Mappping 2:
@RequestMapping(value = "endpoint",
method = RequestMethod.GET, produces = {"application/zip", "*/*"})
This setup will take an Accept: video/*
and go to mapping 1 (which is what we want). But, Accept: video/mp4
results in an java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path
exception.
I would have expected that video/mp4
more closely matches mapping 1 and loads that. Indeed that is exactly what we do want.
We can remove the */*
and then Accept: video/mp4
does go to mapping 1. However, we do need the */*
to go to Mapping 2.
Why doesn't Accept: video/mp4
match Mapping 1 since this is a closer match?
Can we configure this endpoint to have a default method if no other accept header more closely matches? Then we could have mapping 1 only declare that it produces application/zip
.
We are using Spring Boot 1.5.3.
@RequestMapping fallback method: We can create a fallback method for the controller class to make sure we are catching all the client requests even though there are no matching handler methods. It is useful in sending custom 404 response pages to users when there are no handler methods for the request.
One of the most important annotations in spring is the @RequestMapping Annotation which is used to map HTTP requests to handler methods of MVC and REST controllers. In Spring MVC applications, the DispatcherServlet (Front Controller) is responsible for routing incoming HTTP requests to handler methods of controllers.
@RequestMapping is used at the class level while @GetMapping is used to connect the methods. This is also an important Spring MVC interview question to knowing how and when to use both RequestMapping and GetMapping is crucial for Java developers.
Why not remove produces
all together and generate the Content-Type
within the method and also have an if condition to test the Accepts
request header? You could call two different methods depending on the request header.
@RequestMapping(value = "endpoint", method = RequestMethod.GET)
public void doIt(HttpServletRequest request, HttpServletResponse response) {
if (request.getHeader("Accept").matches("application/zip"))
doZip();
else
doVideo();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With