faisal bhat
faisal bhat

Reputation: 319

Spring model and request objects

In Spring, why can't we simply use a request object to carry data around in the application? Why did we switch over to using a model object? Also I read on a popular Spring book that it is still a request object (even in a Spring application) that does most of the hardwork of carrying data. Does it mean that the models we create in Spring are somehow linked to a request object underneath the hood?

Upvotes: 0

Views: 5659

Answers (1)

Ali Dehghani
Ali Dehghani

Reputation: 48123

In Spring, why can't we simply use a request object to carry data around in the application?

You can use HttpServletRequest or even WebRequest as method argument and then inspect those two in order to extract the data out of it. For example, if you want to get the value of a query string named page:

@RequestMapping("/users")
public void listUsers(HttpServletRequest request) {
    String page = request.getParameter("page");
    ...
}

Why did we switch over to using a model object?

You can simply read from a HttpServletRequest and finally write to a HttpServletResponse in any controller method but spring also provides nicer abstractions for handling typical web scenarios. For example if your page parameter is a required int parameter with the default value of 1, you can simply write:

@RequestMapping("/users")
public void listUsers(@RequestParam(defaultValue = "1") Integer page) {
    ...
}

Spring automatically does all the string to int conversion and populating with default values for you. Or suppose you want to automatically validate your json or xml Request Body and return validation errors. With these higher abstractions you will define a model object that contains all the validation logic in it and simply add @Valid annotation before its reference it method arguments, that's it!

@RequestMappting(value = "/users", method = POST)
public void addNewUser(@RequestBody @Valid User user) {
    // automatically validates the user
    // and send validation error, if user wasn't valid
}

Of course you can do the same by inspecting HttpServletRequest but it would be so cumbersome.

Does it mean that the models we create in Spring are somehow linked to a request object underneath the hood?

They're not necessarily link to them but usually these model objects will be populated from request parameters.

For example, spring convert the request body to the method argument by using an HttpMessageConverter. HttpMessageConverter is responsible for converting from the HTTP request message to an object and converting from an object to the HTTP response body. For instance FormHttpMessageConverter converts form data to/from a MultiValueMap<String, String>. This class has a read method that reads the request body and converts it to a MultiValueMap<String, String>. This method looks like this:

public MultiValueMap<String, String> read(Class<? extends MultiValueMap<String, ?>> clazz,
            HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {

        MediaType contentType = inputMessage.getHeaders().getContentType();
        Charset charset = (contentType.getCharSet() != null ? contentType.getCharSet() : this.charset);
        String body = StreamUtils.copyToString(inputMessage.getBody(), charset);

        String[] pairs = StringUtils.tokenizeToStringArray(body, "&");
        MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(pairs.length);
        for (String pair : pairs) {
            int idx = pair.indexOf('=');
            if (idx == -1) {
                result.add(URLDecoder.decode(pair, charset.name()), null);
            }
            else {
                String name = URLDecoder.decode(pair.substring(0, idx), charset.name());
                String value = URLDecoder.decode(pair.substring(idx + 1), charset.name());
                result.add(name, value);
            }
        }
        return result;
}

By String body = StreamUtils.copyToString(inputMessage.getBody(), charset);, it actually reads the request body and converts it to a String.

Upvotes: 5

Related Questions