title: JSR303 custom validators being called twice
body: <p>I am creating a website using Spring MVC and for persistence I am using Spring Data JPA with Hibernate 4 as my JPA provider. Validation is being handled at present with Hibernate Validator. I have a problem whereby my validators are being called twice and I can't figure out why. The main reason this is a problem is because the second time round, dependencies are not being autowired into the validator and I am getting a null pointer exception.
  The following is the sequence of calls leading up to the failure:</p>
  
  <ol>
  <li>The registration form is submitted and first the NotDefaultSectValidator is called  and completes successfully for the 'whereDidYouHearAboutUs' field on the user object.</li>
  <li>The UniqueUsernameValidator is called next and completes successfully for the 'username' field validation.</li>
  <li>The 'addUserFromForm' method on the controller starts and finds no errors in the bindingResults object.</li>
  <li>The 'addUser' method is then called on the UserService class. This method reaches the line 'userRepository.save(user);' but never then runs the 'print.ln' line immediate afterwards. Stepping over this line takes be back to the 'NotDefaultSectValidator' breakpoint. This completes for the second time and I re-enter the second validator 'UniqueUsernameValidator '. Here I get a null pointer exception because for some reason Spring fails to Autowire in the DAO this second time.</li>
  </ol>
  
  <p>Can anyone shed light on why the validators are being called twice and in particular, why stepping over line 'userRepository.save(user);' goes back into these validators?</p>
  
  <p>Many thanks</p>
  
  <p>Here is my user.java class</p>
  
  <pre><code>package com.dating.domain;
  
  import java.util.HashSet;
  import java.util.Set;
  
  import javax.persistence.CascadeType;
  import javax.persistence.Column;
  import javax.persistence.Entity;
  import javax.persistence.FetchType;
  import javax.persistence.GeneratedValue;
  import javax.persistence.GenerationType;
  import javax.persistence.Id;
  import javax.persistence.JoinColumn;
  import javax.persistence.JoinTable;
  import javax.persistence.ManyToMany;
  import javax.persistence.PrePersist;
  import javax.persistence.PreUpdate;
  import javax.persistence.Table;
  import javax.persistence.Transient;
  import javax.validation.constraints.Pattern;
  import javax.validation.constraints.Size;
  
  import org.hibernate.annotations.Type;
  import org.hibernate.validator.constraints.Email;
  import org.hibernate.validator.constraints.NotEmpty;
  import org.joda.time.LocalDate;
  import org.springframework.format.annotation.DateTimeFormat;
  
  import com.dating.annotation.NotDefaultSelect;
  import com.dating.annotation.UniqueUsername;
  
  @Entity
  @Table(name = "dating.user")
  public class User {
  
      @Id
      @Column(name = "id")
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
  
      @Column(name = "username", unique = true)
      @NotEmpty
      @Pattern(regexp = "^[a-zA-Z0-9]*$")
      @UniqueUsername
      private String username;
  
      @Column(name = "password", nullable = false)
      @NotEmpty
      @Size(min = 8)
      private String password;
  
      @Column(name = "first_name", nullable = false)
      @NotEmpty
      private String firstName;
  
      @Column(name = "last_name", nullable = false)
      @NotEmpty
      private String lastName;
  
      @Transient
      private String fullName;
  
      @Column(name = "email", nullable = false)
      @NotEmpty
      @Email
      private String email;
  
      @Column(name = "gender", nullable = false)
      @NotEmpty
      private String gender;
  
      @Column(name = "date_of_birth", nullable = false)
      @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
      @DateTimeFormat(pattern = "dd/MM/yyyy")
      private LocalDate dateOfBirth;
  
      @Column(name = "join_date", nullable = false)
      @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
      private LocalDate joinDate;
  
      @Column(name = "where_did_you_hear_about_us", nullable = false)
      @NotDefaultSelect
      private String whereDidYouHearAboutUs;
  
      @Column(name = "enabled")
      private boolean enabled;
  
      @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
      @JoinTable(name = "dating.user_roles", joinColumns = { @JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "role_id", nullable = false, updatable = false) })
      private Set&lt;Role&gt; roles = new HashSet&lt;Role&gt;();
  
      @Column(name = "created_time", nullable = false)
      @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
      private LocalDate createdTime;
  
      @Column(name = "modification_time", nullable = false)
      @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
      private LocalDate modificationTime;
  
      public Long getId() {
          return id;
      }
  
      public void setId(Long id) {
          this.id = id;
      }
  
      public String getUsername() {
          return username;
      }
  
      public void setUsername(String username) {
          this.username = username;
      }
  
      public String getPassword() {
          return password;
      }
  
      public void setPassword(String password) {
          this.password = password;
      }
  
      public String getFirstName() {
          return firstName;
      }
  
      public void setFirstName(String firstName) {
          this.firstName = firstName;
      }
  
      public String getLastName() {
          return lastName;
      }
  
      public void setLastName(String lastName) {
          this.lastName = lastName;
      }
  
      public String getFullName() {
          return firstName + " " + lastName;
      }
  
      public void setFullName(String fullName) {
          this.fullName = fullName;
      }
  
      public String getEmail() {
          return email;
      }
  
      public void setEmail(String email) {
          this.email = email;
      }
  
      public String getGender() {
          return gender;
      }
  
      public void setGender(String gender) {
          this.gender = gender;
      }
  
      public LocalDate getDateOfBirth() {
          return dateOfBirth;
      }
  
      public void setDateOfBirth(LocalDate dateOfBirth) {
          this.dateOfBirth = dateOfBirth;
      }
  
      public LocalDate getJoinDate() {
          return joinDate;
      }
  
      public void setJoinDate(LocalDate joinDate) {
          this.joinDate = joinDate;
      }
  
      public String getWhereDidYouHearAboutUs() {
          return whereDidYouHearAboutUs;
      }
  
      public void setWhereDidYouHearAboutUs(String whereDidYouHearAboutUs) {
          this.whereDidYouHearAboutUs = whereDidYouHearAboutUs;
      }
  
      public boolean isEnabled() {
          return enabled;
      }
  
      public void setEnabled(boolean enabled) {
          this.enabled = enabled;
      }
  
      public Set&lt;Role&gt; getRoles() {
          return roles;
      }
  
      public void setRoles(Set&lt;Role&gt; roles) {
          this.roles = roles;
      }
  
      public void addRole(Role role) {
          roles.add(role);
      }
  
      public LocalDate getCreatedTime() {
          return createdTime;
      }
  
      public void setCreatedTime(LocalDate createdTime) {
          this.createdTime = createdTime;
      }
  
      public LocalDate getModificationTime() {
          return modificationTime;
      }
  
      public void setModificationTime(LocalDate modificationTime) {
          this.modificationTime = modificationTime;
      }
  
      @PreUpdate
      public void preUpdate() {
          modificationTime = new LocalDate();
      }
  
      @PrePersist
      public void prePersist() {
          LocalDate now = new LocalDate();
          createdTime = now;
          modificationTime = now;
      }
  }
  </code></pre>
  
  <p>The relevant method in my registration controller:</p>
  
  <pre><code>@RequestMapping(value = "/register", method = RequestMethod.POST)
  public String addUserFromForm(@Valid User user,
          BindingResult bindingResult, RedirectAttributes ra) {
      if (bindingResult.hasErrors()) {
          return "user/register";
      }
      userService.addUser(user);
  
      // Redirecting to avoid duplicate submission of the form
      return "redirect:/user/" + user.getUsername();
  }
  </code></pre>
  
  <p>My service class:</p>
  
  <pre><code>package com.dating.service.impl;
  
  import javax.transaction.Transactional;
  
  import org.joda.time.LocalDate;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  import org.springframework.stereotype.Service;
  
  import com.dating.domain.Role;
  import com.dating.domain.User;
  import com.dating.repository.RoleRepository;
  import com.dating.repository.UserRepository;
  import com.dating.repository.specification.UserSpecifications;
  import com.dating.service.UserService;
  
  @Service
  public class UserServiceImpl implements UserService {
  
      @Autowired
      private UserRepository userRepository;
  
      @Autowired
      private RoleRepository roleRepository;
  
      @Transactional
      @Override
      public void addUser(User user) {
          user.setJoinDate(new LocalDate());
          user.setEnabled(true);
          Role role = roleRepository.findByName(Role.MEMBER);
          if (role == null) {
              role = new Role();
              role.setName(Role.MEMBER);
          }
          user.addRole(role);
          BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
          user.setPassword(encoder.encode(user.getPassword()));
          userRepository.save(user);
          System.out.println("User Saved");
      }
  
      @Override
      public User getUserByUsername(String username) {
          return userRepository.findByUsername(username);
      }
  
      @Override
      public Iterable&lt;User&gt; getAllUsers() {
          return userRepository.findAll();
      }
  
      @Override
      public void updateDetails(User user) {
          userRepository.save(user);
      }
  
      @Override
      public Iterable&lt;User&gt; lastNameIsLike(String searchTerm) {
          return userRepository.findAll(UserSpecifications
                  .lastNameIsLike(searchTerm));
      }
  }
  </code></pre>
  
  <p>My NotDefaultSelect validator:</p>
  
  <pre><code>package com.dating.validator;
  
  import javax.validation.ConstraintValidator;
  import javax.validation.ConstraintValidatorContext;
  import com.dating.annotation.NotDefaultSelect;
  
  public class NotDefaultSelectValidator implements
          ConstraintValidator&lt;NotDefaultSelect, String&gt; {
      @Override
      public void initialize(NotDefaultSelect constraint) {
  
      }
  
      @Override
      public boolean isValid(String selectedValue, ConstraintValidatorContext ctx) {
          if (selectedValue == null) {
              return false;
          }
          if (selectedValue.equals("") || selectedValue.equals("0")
                  || selectedValue.equalsIgnoreCase("default")
                  || selectedValue.equalsIgnoreCase("please select")) {
              return false;
          }
          return true;
      }
  
  }
  </code></pre>
  
  <p>My uniqueUsername validator:</p>
  
  <pre><code>package com.dating.validator;
  
  import javax.validation.ConstraintValidator;
  import javax.validation.ConstraintValidatorContext;
  
  import org.springframework.beans.factory.annotation.Autowired;
  
  import com.dating.annotation.UniqueUsername;
  import com.dating.repository.UserRepository;
  
  public class UniqueUsernameValidator implements
          ConstraintValidator&lt;UniqueUsername, String&gt; {
  
      @Autowired
      private UserRepository userRepository;
  
      @Override
      public void initialize(UniqueUsername constraint) {
  
      }
  
      @Override
      public boolean isValid(String username, ConstraintValidatorContext ctx) {
          if (username == null || userRepository.findByUsername(username) == null) {
              return true;
          }
          return false;
      }
  
  }
  </code></pre>
  
  <p>My UserRepository:</p>
  
  <pre><code>package com.dating.repository;
  
  import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  import org.springframework.data.repository.CrudRepository;
  
  import com.dating.domain.User;
  
  //Spring Data JPA Marker interfaces being extended for automatic CRUD repository creation
  public interface UserRepository extends CrudRepository&lt;User, Long&gt;, JpaSpecificationExecutor&lt;User&gt; {
  
      //Automatic query creation from method name
      public User findByUsername(String username);
  }
  </code></pre>
  
  <p>Lastly my persistence-context.xml file</p>
  
  <pre><code>&lt;!-- Data source properties --&gt;
  &lt;util:properties id="dataSourceSettings" location="classpath:datasource.properties" /&gt;
  
  &lt;!-- Pooled data source using BoneCP --&gt;
  &lt;bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
      destroy-method="close"&gt;
      &lt;property name="driverClass" value="#{dataSourceSettings['jdbc.driverClass']}" /&gt;
      &lt;property name="jdbcUrl" value="#{dataSourceSettings['jdbc.url']}" /&gt;
      &lt;property name="username" value="#{dataSourceSettings['jdbc.username']}" /&gt;
      &lt;property name="password" value="#{dataSourceSettings['jdbc.password']}" /&gt;
      &lt;property name="idleConnectionTestPeriodInMinutes" value="60" /&gt;
      &lt;property name="idleMaxAgeInMinutes" value="240" /&gt;
      &lt;property name="maxConnectionsPerPartition" value="30" /&gt;
      &lt;property name="minConnectionsPerPartition" value="10" /&gt;
      &lt;property name="partitionCount" value="3" /&gt;
      &lt;property name="acquireIncrement" value="5" /&gt;
      &lt;property name="statementsCacheSize" value="100" /&gt;
      &lt;property name="releaseHelperThreads" value="3" /&gt;
  &lt;/bean&gt;
  
  &lt;!-- JPA entity manager factory bean --&gt;
  &lt;bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
      &lt;property name="dataSource" ref="dataSource" /&gt;
      &lt;property name="packagesToScan" value="com.dating.domain" /&gt;
      &lt;property name="jpaVendorAdapter"&gt;
          &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /&gt;
      &lt;/property&gt;
      &lt;property name="jpaProperties"&gt;
          &lt;props&gt;
              &lt;prop key="hibernate.dialect"&gt;#{dataSourceSettings['hibernate.dialect']}&lt;/prop&gt;
              &lt;prop key="hibernate.hbm2ddl.auto"&gt;#{dataSourceSettings['hibernate.hbm2ddl.auto']}
              &lt;/prop&gt;
              &lt;prop key="hibernate.show_sql"&gt;#{dataSourceSettings['hibernate.show_sql']}&lt;/prop&gt;
              &lt;prop key="hibernate.format_sql"&gt;#{dataSourceSettings['hibernate.format_sql']}&lt;/prop&gt;
              &lt;prop key="hibernate.use_sql_comments"&gt;#{dataSourceSettings['hibernate.use_sql_comments']}
              &lt;/prop&gt;
          &lt;/props&gt;
      &lt;/property&gt;
  &lt;/bean&gt;
  
  &lt;tx:annotation-driven transaction-manager="transactionManager" /&gt;
  
  &lt;bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"&gt;
      &lt;property name="entityManagerFactory" ref="entityManagerFactory" /&gt;
  &lt;/bean&gt;
  
  &lt;context:annotation-config /&gt;
  
  &lt;jpa:repositories base-package="com.dating.repository"/&gt;
  </code></pre>