Search code examples
javaspring-bootthymeleaf

Spring Boot Thymeleaf SpelEvaluationException EL1007E when submitting a form


I'm trying to handle a form submission with thymeleaf in my spring-boot application, i integrated
this example which worked fine on my app. I'm trying to change it a little bit, but this is what i'm getting as an exception:

org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'recruiter' cannot be found on null
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213) ~[spring-expression-5.2.3.RELEASE.jar:5.2.3.RELEASE]

...

This is the object i'm trying to handle with thymeleaf


public class FormRec {

private String recruiter;
public String getRecruiter() {
    return recruiter;
}
public void setRecruiter(String recruiter) {
    this.recruiter = recruiter;
}


}

This is my Controller

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.service.minimicroservice.objects.FormRec;

@Controller
public class MyController {




      @GetMapping("/form")
      public String greetingForm(Model model) {
        model.addAttribute("recForm", new FormRec());
        return "form";
      }

      @PostMapping("/form")
      public String greetingSubmit(@ModelAttribute FormRec rec) {
        return "result";
      }


}

result.html

<!DOCTYPE HTML>
<html xmlns:th="https://www.thymeleaf.org">
<head>
    <title>Getting Started: Handling Form Submission</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1>Result</h1>
    <p th:text="'Recruiter: ' + ${rec.recruiter}" />
    <a href="/form">Submit another message</a>
</body>
</html>

part of the form.html


<body>

                    <form action="#" th:action="@{/form}" th:object="${recForm}" method="post">
                        <div class="form-row m-b-55">
                            <div class="name">Recruiter<br> Name</div>
                            <div class="value">
                                <div class="row row-space">
                                    <div class="col-2">
                                        <div class="input-group-desc">
                                            <input class="input--style-5" type="text" name="first_name" th:field="*{recruiter}">
                                            <label class="label--desc">Full Name</label>
                                        </div>
                                    </div>
...


In order to refer to a FormRec Object i use recForm as th:object in the form.html and rec to refer to it in the result.html.

Note: I pass a value to the th:field="*{recruiter}" input text when i submit the form (is not null)


Solution

  • You have to name the ModelAttribute rec that the data gets bound to. So in your controller method do this (notice the name = "rec"):

    public String greetingSubmit(@ModelAttribute(name = "rec") FormRec rec) {
    ...
    }
    

    It should work.

    Additional explanation:

    I've had a closer look at why that happens and it's because Spring's ModelAttribute annotation by default infers from the name of the type and not the name of the parameter (the example link you provided says it's method parameter name, but it seems to be wrong).

    So in this case Spring sends formRec (notice the camelCase, which it expects when the class name is called FormRec) to the result.html and not rec as you would expect.

    If my explanation doesn't really make sense, then this is the Spring documentation on ModelAttribute:

    The default model attribute name is inferred from the declared attribute type (i.e. the method parameter type or method return type), based on the non-qualified class name: e.g. "orderAddress" for class "mypackage.OrderAddress", or "orderAddressList" for "List".