3

I have a spring controller method which takes a String as the entirety of the RequestBody like so:

    @RequestMapping(method=RequestMethod.POST)
    public @ResponseBody DTO method(@PathVariable("userId") long userId, @RequestBody String page) {
         // Controller contents here
     }

Previously, I have been able to post "naked" strings to this method, that is requests with a string as the body (and not a json object). For example (from chrome dev tools):

Initial post attempt

This stopped working after I attempted to add a Jackson Hibernate 4 module to the Jackson2ObjectMapperFactoryBean (to deal with hibernate lazy collections), using the following in my xml config file:

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="modulesToInstall"
                              value="com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module"/>
                    <property name="featuresToEnable">
                        <array>
                            <util:constant static-field="com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES"/>
                        </array>
                    </property>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

After customising the ObjectMapper like this I receive the following error when posting the request as above:

org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Unrecognized token 'Testing': was expecting ('true', 'false' or 'null')
at [Source: java.io.PushbackInputStream@5e6a19fe; line: 1, column: 13]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Testing': was expecting ('true', 'false' or 'null')
at [Source: java.io.PushbackInputStream@5e6a19fe; line: 1, column: 13]

A work arround for this (using angular js) is to call JSON.stringify() before posting to the API, so the angular code becomes

$http.post(Url + userId, JSON.stringify(string)).then(function (result) {
        return result.data;
    });

and the request becomes

With quotes

After this the API works as it did previously, accepting the String on its own.

While I know that a string without enclosing " is not a valid JSON string, what I don't understand is why changing the ObjectMapper bean should make such a difference in this case? I am using spring version 4.3.4 and jackson version 2.8.5, if that's at all useful information.

James Fielder
  • 133
  • 1
  • 7

1 Answers1

0

What did your dispatcher servlet configuration and dependency configuration look like before you introduced a custom MappingJackson2HttpMessageConverter?

Since Spring uses the Content-type header of your request to determine which message converter to use, why would you explicitly send application/json when your request body obviously isn't JSON?

A proper "workaround" would be to send Content-type: text/plain, which would make Spring use the StringHttpMessageConverter which is also what I believe Spring did before you started configuring a MappingJackson2HttpMessageConverter

JTP
  • 231
  • 3
  • 5
  • Dispatcher servlet looked like [this](http://pastie.org/private/s5e1lpwrvfluoeyuj1nifa). There is nothing in my application context related to jackson: I think it's just using spring defaults. I find that even adding the `` tag is enough to trigger this behaviour. I will look into using `Content-type: text/plain`, but I'm just amazed that attempting to customise the message converters has this effect. Alas, the code has been built in a number of places relying on this, so changing it will be a bit painful but the right thing to do overall. – James Fielder Dec 06 '16 at 11:47