0

I have looked at other posting on this subject but couldn't get it to work. This seems to be a simple issue. I would appreciate if someone could help.

Person.java

@Entity
@Table(name = "PERSON")
public class Person {

@Id
@Column(name = "PERSON_ID")
private int id;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

public Person() {
}

public Person(String fname, String lname) {
    this.firstName = fname;
    this.lastName = lname;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getFirstName() {
    return firstName;
}

public void setFirstName(String first_name) {
    this.firstName = first_name;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String last_name) {
    this.lastName = last_name;
}
}

PersonController.java

@Controller
@RequestMapping("person")
public class PersonController {

@RequestMapping(value = "add", method = RequestMethod.POST)
public String addPerson(
        @ModelAttribute("person") @Valid Person person, BindingResult result) {

    log.info("in add");

    personValidator.validate(person, result);

    if (!result.hasErrors())
        personService.addPerson(person);

    return "redirect:/spring/person/list";
}

person.jsp

<body>

<form:form method="post" action="add.html" commandName="person">
    <form:errors path="*" cssClass="errorblock" />
    <table>
        <tr>
            <td><form:label path="firstName">First name</form:label></td>
            <td><form:input path="firstName" /></td>
            <td><form:errors path="*" cssClass="error" /></td>
        </tr>
        <tr>
            <td><form:label path="lastName">Last name</form:label></td>
            <td><form:input path="lastName" /></td>
            <td><form:errors path="*" cssClass="error" /></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="Add" /></td>
        </tr>
    </table>
</form:form>
</body>
</html>

PersonValidator.java

@Component
public class PersonValidator implements Validator {
        public void validate(Object arg0, Errors arg1) {
    Person person = (Person) arg0;

    if (personService.findPersonByName(person.getFirstName(), person.getLastName()) != null)
        arg1.rejectValue("firstName", "first name empty");
        //arg1.reject("save.person", "User already exists.");
}
  }

personService.findPersonByName is not null and result.hasErrors() is true, so I know the form has errors but they don't display for some reasons.

0

3 Answers 3

4

You're performing a redirect

mav = new ModelAndView("redirect:/spring/person/list", "person", person);

Your errors are stored in the model and subsequently in the HttpServletRequest attributes. These only last for the duration of one request. A redirect causes the client to send a new request. They therefore don't exist when your redirected view is rendered.

Consider using flash attributes. Look into RedirectAttributes. That's how POST-REDIRECT-GET typically works.

Sign up to request clarification or add additional context in comments.

6 Comments

Could you be more explicit? I tried using String redirect, it didn't work either (actually that's the reason I tried using ModelAndView. @RequestMapping(value = "add", method = RequestMethod.POST) public String addPerson( @ModelAttribute("person") @Valid Person person, BindingResult result) {
@user3260768 I don't know how to be more explicit. A redirect causes the client to send a new request. You can't depend on HttpServletRequest or model attributes for this. Use RedirectAttributes.
My eclipse is not finding RedirectAttributes class. I am using 3.0.5.RELEASE spring mvc.
@user3260768 The class was added in 3.1. If you can't upgrade, this blog post shows you how to implement your own flash scope.
I upgraded spring to 3.1.0.RELEASE. Still no error was showing in my jsp page. It is probably something really simple. I just can't figure it out. public String addPerson( @ModelAttribute("person") @Valid Person person, BindingResult result, RedirectAttributes redirectAttrs) { personValidator.validate(person, result); if (result.hasErrors()) { redirectAttrs.addAttribute("person", person.getId()).addFlashAttribute("message", "duplicate person!"); return "redirect:/spring/person/list"; } personService.addPerson(person); return "redirect:/spring/person/list";
|
0

How does your person bean looks like? Do you have validation annotation(s) there also? Please paste fields.

try this instead:

@RequestMapping(value = "add", method = RequestMethod.POST)
public ModelAndView addPerson(
        @ModelAttribute("person") @Valid Person person, BindingResult result) {

    ModelAndView mav;

    log.info("in add");

    personValidator.validate(person, result);

    if (result.hasErrors()) {
        mav = new ModelAndView("your view here");
        mav.addObject("person", person);
        return mav;
    }

    personService.addPerson(person);

    mav = new ModelAndView("redirect:/spring/person/list", "person", person);

    return mav;
}

If there are any errors we want to add the bean to the mav and display the view again. (If you've got validation in the bean also, the errors will display on the jsp) else the person will be created and redirect..

As you have now, the error messages cannot display because of the redirecting. Therefore we want to add the bean to the view and display the view again.

2 Comments

I just added Person.java. Ideally I want to use String redirect (pls see my updated source).
I did try your suggestion. It didn't work. /spring/person/list is the view that contains the form for input of first and last name as well as a list of persons from db. If the form input is successful and saved to db, I want to display /spring/person/list (which method retrieves records from db and returns "person" to get to person.jsp) page again with the new person record, else I want to display some error above the input on the same page /spring/person/list and person.jsp.
0

Make sure correct validation dependencies are added to your project like below 2:

<!-- https://mvnrepository.com/artifact/jakarta.validation/jakarta.validation-api -->
<dependency>
    <groupId>jakarta.validation</groupId>
    <artifactId>jakarta.validation-api</artifactId>
    <version>2.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.5.Final</version>
</dependency>

Note:
1) Even though hibernate is not used in your project you'll need a bean validation implementer. hibernate-validator provides such implementation.

2) Make sure correct dependency versions are added like below for hibernate-validator 6.2.5.Final needs jakarta.validation version 2.0.2.

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.