Learner
Learner

Reputation: 21405

Using @Valid is throwing exceptions & not working in basic Spring 3.0 MVC program

I am learning Spring MVC using Spring In Action 3rd Action, I have implemented the basic program which shows the user registration form and once we submit the form, it will be validated using @Valid.

Here is my Spring Controller:

@Controller
@RequestMapping("/spitter")
public class SpitterController {
        private final SpitterService spitterService;

        @Inject
        public SpitterController(SpitterService spitterService) {
            this.spitterService = spitterService;
        }

        @RequestMapping(method = RequestMethod.GET, params = "new")
        public String createSpitterProfile(Model model) {
            Spittle spittle = new Spittle();
            model.addAttribute(spittle);

            model.addAttribute(new Spitter());
            return "spittles/edit";
        }

            @RequestMapping(method = RequestMethod.POST)
            public String addSpitterFromForm(@Valid Spitter spitter,
            BindingResult bindingResult) {
               if (bindingResult.hasErrors()) {
                    return "spittles/edit";
               }
               spitterService.saveSpitter(spitter);
               return "redirect:/spitter/" + spitter.getUsername();
                }
             }

Here is my Spitter class file:

package com.habuma.spitter.domain;

import java.util.List;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class Spitter {
    private Long id;

    @Size(min = 3, max = 20, message = "User name must be between 3 and 20 characters long.")
    @Pattern(regexp = "^[a-zA-Z0-9]+$", message = "Username must be alphanumeric with no spaces")
    private String username;

    @Size(min = 6, max = 20, message = "The password must be atleast 6 characters long.")
    private String password;

    @Size(min = 3, max = 50, message = "Your full name must be between 3 and 50 characters long.")
    private String fullName;

    @Pattern(regexp = "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}", message = "Invalid email address.")
    private String email;

    private List<Spittle> spittles;
    private boolean updateByEmail;

    ......Setters & Getters.....

    @Override
    public boolean equals(Object obj) {
        Spitter other = (Spitter) obj;
        return other.fullName.equals(fullName)
                && other.username.equals(username)
                && other.password.equals(password);
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }
}

This is my edit.jsp file which is shown to the user for registration:

<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form"%>
<div>
    <h2>Create a free Spitter account</h2>
    <sf:form method="POST" modelAttribute="spitter" enctype="multipart/form-data">
        <fieldset>
            <table cellspacing="0">
                <tr>
                    <th><label for="user_full_name">Fullname:</label></th>
                    <td><sf:input path="fullName" size="15" id="user_full_name" />
                        <sf:errors path="fullName" cssClass="error" /></td>
                </tr>
                <tr>
                    <th><label for="user_screen_name">Username:</label></th>
                    <td><sf:input path="username" size="15" maxlength="15"
                            id="user_screen_name" /> <small id="username_msg">No spaces,please.</small>
                        <sf:errors path="username" cssClass="error" /></td>
                </tr>
                <tr>
                    <th><label for="user_password">Password:</label></th>
                    <td><sf:password path="password" size="30" showPassword="true"
                            id="user_password" /> <small>6
                            characters or more (betricky!)</small> <sf:errors path="password"
                            cssClass="error" /></td>
                </tr>
                <tr>
                    <th><label for="user_email">EmailAddress:</label></th>
                    <td><sf:input path="email" size="30" id="user_email" /> <small>In
                            case you forget something</small> <sf:errors path="email"
                            cssClass="error" /></td>
                </tr>
                <tr>
                    <th></th>
                    <td><sf:checkbox path="updateByEmail"
                            id="user_send_email_newsletter" /> <label
                        for="user_send_email_newsletter">Send me email updates!</label></td>
                </tr>
                <tr>
                    <th><label for="image">Profile image:</label></th>
                    <td><input name="image" type="file" />
                </tr>
                <tr>
                    <th></th>
                    <td><input name="commit" type="submit"
                        value="I accept.Createmyaccount." /></td>
                </tr>
            </table>
        </fieldset>
    </sf:form>
</div>

To load the form I am accessing the URL as : http://localhost:8081/SpringInAction3/spitter?new, once the form is loaded I am just submitting the form without entering any details so that I can check if my form is getting validated or not. But I am getting below exception:

java.lang.NullPointerException
    com.habuma.spitter.domain.Spitter.equals(Spitter.java:87)
    org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver$TraversableHolder.equals(SingleThreadCachedTraversableResolver.java:138)
    java.util.HashMap.get(HashMap.java:305)
    org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver.isReachable(SingleThreadCachedTraversableResolver.java:45)
    org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:757)
    org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:324)
    org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:273)
    org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:256)
    org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:210)
    org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119)
    org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:106)
    org.springframework.validation.DataBinder.validate(DataBinder.java:760)

I am getting NullPointerException in my equals method of Splitter class. Please let me know where I am doing mistake?

Edit:

When I tried to print the values of the fields in my Spitter object I am getting null for all the fields so that is causing the NullPointerException.

This time I removed the equals and hashCode methods from my Spitter class, now when I am submitting the form, the validation is not happening and the page is going to http://localhost:8081/SpringInAction3/spitter/null without showing any errors.

Why the validation is not happening in this case? Also if I just follow the steps in that book, I am getting NullPointerException which is not expected. Please let me know where I am doing mistake?

As per this SO post : @Valid (jsr 303) not working in Spring mvc 3.0, I also have the tag <mvc:annotation-driven/> in my configuration file.

Upvotes: 3

Views: 1439

Answers (1)

Sparticles
Sparticles

Reputation: 608

I see one mistake so far. The sf:form attribute enctype is set as multipart/form-data but that is only used on file uploads, so i guess spring mvc is using the MultipartResolver instead of Data binding mechanism that binds form data to form backing objects , try changing it to application/x-www-form-urlencoded, which is the default and correct type for your case.

Upvotes: 3

Related Questions