Search code examples
javaspring-bootspring-mvcdependency-injectionthymeleaf

Are Spring Model objects (and their attributes) tied to their respective controller endpoints / templates?


I'm just starting with spring so please bear with me. I've just solved a bug in my code that was coming from my assumption that once an attribute is added to any Model object, it would also be available to the templating implementation at other endpoints.

@GetMapping("/user_page")
    public String getUserPage( Model model ) {
        Page page = new Page();
        model.addAttribute("user_page", page);
        return "user_page";

In my Thymeleaf template I was able to use this attribute fine at user_page.html. Now at another endpoint and template I was also trying to use this user_page attribute. Note that it was throwing some errors:

Exception evaluating SpringEL expression:

and

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null

It looks like Thymeleaf couldn't find the user_page attribute.

but I also hadn't added a Model parameter to the controller that handled this other endpoint. After adding a Model to the method parameters and adding the page again model.addAttribute("user_page", page);, this time to the controller handling the different endpoint, the problem went away.

Is Spring autowiring non-singleton Model objects to these controllers? Why did I have to add the same page instance to the model twice? So are these Models tied specifically to the template (maybe even endpoint) that their respective controller returns?


Solution

  • Read Dispatcher Servlet Processing Sequence.

    Are Spring Model objects (and their attributes) tied to their respective controller endpoints / templates?

    There is no such a thing, as "Model's respective controller"; rather, a fresh instance of the Model's implementation gets instantiated each time, any handler method gets invoked.

    When an HTTP request hits dispatcher servlet, and the latter passes the servlet request-response objects into the corresponding handler method, Spring MVC's infrastructure looks up the signature of corresponding handler method and passes a fresh instance of the Model (along with many others), if it is expected.

    You can also use modelAttribute element in your template's form, and this way, you will directly bind the data to the handler method's Model parameter, having the argument being pre-filled with the form data. In this case, you can also enable Bean Validation.