Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @RequestMapping consumes charset?

I'm trying to use @RequestMapping with the consumes-element. Reading the API-document it works on the Content-Type-header of the request. However, using

@RequestMapping(consumes = "application/x-www-form-urlencoded;charset=UTF-8", value = "/test")
public void test() {
  :
}

or

@RequestMapping(consumes = "application/x-www-form-urlencoded;charset=ISO-8859-1", value = "/test")
public void test() {
  :
}

doesn't make a difference. The header in the request can look like

Content-Type: application/x-www-form-urlencoded;charset=UTF-8

or

Content-Type: application/x-www-form-urlencoded

test() will be called in all four possible constellations.

However, and this is proof to me that Spring sees and tries to use the charset-part, if I specify

@RequestMapping(consumes = "application/x-www-form-urlencoded;charset=UTF-x8", value = "/test")
public void test() {
  :
}

I get an exception during startup (!) of the web-app:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Initialization of bean failed;
    nested exception is java.nio.charset.UnsupportedCharsetException: UTF-x8

Note that the documentation on the produces-element also doesn't mention the use of charset, but according to Google some use it.

Any clues to what's happening here or what I'm doing wrong?

BTW, this is Spring 3.1.1.RELEASE.

like image 563
sjngm Avatar asked Jan 21 '26 07:01

sjngm


1 Answers

I think you have already answered your question, so this is more of a confirmation, from a code point of view, as to why the charset is not taken into account when resolving mappings.

When digging into Spring code, the culprit seems to be the MediaType#includes(). method

More digging reveals that a RequestMappingInfo is created in association to the RequestMapping annotation of the method. This RequestMappingInfo stores a series of AbstractRequestCondition objects, one of them being the ConsumesRequestCondition which holds the MediaType defined in the consumes part of the annotation (i.e. application/x-www-form-urlencoded;charset=UTF-8).

Later when a request is made, this ConsumesRequestCondition has an inner ConsumeMediaTypeExpression class with a matchMediaType() method that extracts the MediaType of the HttpServletRequest and checks it against it's own MediaType to see if it's included.

If you look at the MediaType#includes() implementation (Lines 426 to 428), it returns true when type (i.e. application) and subtype (i.e. x-www-form-urlencoded) are equal, completely disregarding the parameters Map which in this case holds the remnant "charset","UTF-8" combination.

Digging into the produces track seems to show similar results, but in this case it's the MediaType#isCompatibleWith() method involved, and again, it reaches only to type and subtype if they are equal.

If you found evidence on Google of the produces working for charset request mapping, I would doubt it (unless they changed core Spring stuff)

As to why it was designed this way, well that's another question :)

like image 84
betomontejo Avatar answered Jan 23 '26 05:01

betomontejo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!