title: Spring MVC PropertyEditorSupport for a complex type
body: <p>I'm trying to convert a string date(submitted by a html forum) to Long type (timestamp). As far as I understood, what I had to do was to create a custom PropertyEditor and I did.</p>
  
  <p>I am also using @Valid annotation and a custom Validator class for the binding. And although I've registered both my PropertyEditor and the Validator, PropertyEditor won't work.</p>
  
  <p>According to the console output, Validator kicks in and tries to validate the object and when it finds out that the time string is not long, it adds the "typeMismatch" error to Errors object...</p>
  
  <p>Am I doing something wrong ?</p>
  
  <p>Here are the classes : </p>
  
  <p><strong>Controller class</strong></p>
  
  <pre><code>@InitBinder
  public void initBinder(WebDataBinder binder)
  {
      binder.registerCustomEditor(VisitorRequestBaseMVVM.class,"startingTime",new StringToLongPropertyEditorSupport());
      //I also have tried this...
      //binder.registerCustomEditor(VisitorRequestBase.class,"startingTime",new StringToLongPropertyEditorSupport());
  
  
  @RequestMapping(value="/create-request",method=RequestMethod.POST)
  public ModelAndView postCreateRequest(@ModelAttribute("command") @Valid VisitorRequestBaseMVVM model,
          BindingResult result)
  {
      ModelAndView modelAndView = new ModelAndView("create-request-first-step");
  
      // For to see output of all errors      
      for(ObjectError error : result.getAllErrors())
      {
          System.out.println(error.getObjectName() + ":" + error.getCode() + ":" + error.getDefaultMessage());
      }
  
  
      VisitorRequestBaseMVVM mvvm = new VisitorRequestBaseMVVM();
      mvvm.setVisitorRequestBase(new VisitorRequestBase());
      mvvm.setAllVisitorRequestTypes(allVisitorRequestTypes());
  
      modelAndView.addObject("command",mvvm);
  
      return modelAndView;
  }
  
      binder.addValidators(new VisitorRequestBaseMVVMValidatorImpl());
  }
  </code></pre>
  
  <p><strong>StringToLongPropertyEditorSupport.java</strong></p>
  
  <pre><code>public class StringToLongPropertyEditorSupport extends
          PropertyEditorSupport {
  
       @Override
       public void setAsText(String text) {
           System.out.println("Has it come to this ? (StringToDateTimePropertyEditorSupport):" + text );
           setValue(DateTime.parse(text).getMillis());
       }
  }
  </code></pre>
  
  <p><strong>VisitorRequestBase.java</strong></p>
  
  <pre><code>public class VisitorRequestBase extends BaseEntity{
  private long startingTime;
  private long endingTime;
  private String note;
  private boolean isCompleted;
  
  @Enumerated(EnumType.STRING)
  private ApprovalState approvalState;
  
  @OneToOne
  private User user;
  
  private List&lt;ApprovalHistory&gt; approvalHistories;
  
  public long getStartingTime() {
      return startingTime;
  }
  public void setStartingTime(long startingTime) {
      this.startingTime = startingTime;
  }
  public long getEndingTime() {
      return endingTime;
  }
  public void setEndingTime(long endingTime) {
      this.endingTime = endingTime;
  }
  public String getNote() {
      return note;
  }
  public void setNote(String note) {
      this.note = note;
  }
  public ApprovalState getApprovalState() {
      return approvalState;
  }
  public void setApprovalState(ApprovalState approvalState) {
      this.approvalState = approvalState;
  }
  public User getUser() {
      return user;
  }
  public void setUser(User user) {
      this.user = user;
  }
  public List&lt;ApprovalHistory&gt; getApprovalHistories() {
      return approvalHistories;
  }
  public void setApprovalHistories(List&lt;ApprovalHistory&gt; approvalHistories) {
      this.approvalHistories = approvalHistories;
  }
  public boolean isCompleted() {
      return isCompleted;
  }
  public void setCompleted(boolean isCompleted) {
      this.isCompleted = isCompleted;
  }
  
  
  public void setPropertiesForSubclass(final VisitorRequestBase subObject) 
          throws IllegalArgumentException, IllegalAccessException
  {
      for(Field field : VisitorRequestBase.class.getFields())
      {
          field.set(subObject, field.get(this));
      }
  }
  
  }
  </code></pre>
  
  <p><strong>VisitorRequestBaseValidator.java</strong></p>
  
  <pre><code>@Component
  public class VisitorRequestBaseValidatorImpl implements VisitorRequestBaseValidator {
  
  @Override
  public boolean supports(Class&lt;?&gt; arg0) {
      return VisitorRequestBase.class.isAssignableFrom(arg0);
  }
  
  @Override
  public void validate(Object objectToValidate, Errors errors) {
  
      ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startingTime","validation.createRequest.startingTime.empty");
  }
  
  }
  </code></pre>
  
  <p><strong>VisitorRequestBaseMVVM.java</strong></p>
  
  <pre><code>public class VisitorRequestBaseMVVM {
  private VisitorRequestBase visitorRequestBase;
  private VisitorRequestType visitorRequestType;
  
  private List&lt;VisitorRequestType&gt; allVisitorRequestTypes;
  
  public VisitorRequestBase getVisitorRequestBase() {
      return visitorRequestBase;
  }
  public void setVisitorRequestBase(VisitorRequestBase visitorRequestBase) {
      this.visitorRequestBase = visitorRequestBase;
  }
  public VisitorRequestType getVisitorRequestType() {
      return visitorRequestType;
  }
  public void setVisitorRequestType(VisitorRequestType visitorRequestType) {
      this.visitorRequestType = visitorRequestType;
  }
  public List&lt;VisitorRequestType&gt; getAllVisitorRequestTypes() {
      return allVisitorRequestTypes;
  }
  public void setAllVisitorRequestTypes(List&lt;VisitorRequestType&gt; allVisitorRequestTypes) {
      this.allVisitorRequestTypes = allVisitorRequestTypes;
  }
  
  
  }
  </code></pre>
  
  <p><strong>VisitorRequestBaseMVVMValidatorImpl.java</strong></p>
  
  <pre><code>@Component
  public class VisitorRequestBaseMVVMValidatorImpl implements VisitorRequestBaseMVVMValidator{
  
  
  @Autowired
  private VisitorRequestBaseValidator visitorRequestBaseValidator;
  
  @Override
  public boolean supports(Class&lt;?&gt; clazz) {
      return VisitorRequestBaseMVVM.class.isAssignableFrom(clazz);
  }
  
  @Override
  public void validate(Object target, Errors errors) {
      VisitorRequestBaseMVVM object = (VisitorRequestBaseMVVM)target;
  
  
      if(object.getVisitorRequestType() == null) 
          errors.rejectValue("visitorRequestType", "validation.createRequest.visitorRequestType.notSelected");
  
  
      errors.pushNestedPath("visitorRequestBase");
      ValidationUtils.invokeValidator(visitorRequestBaseValidator,object.getVisitorRequestBase(), errors);
      errors.popNestedPath();
  
  }
  
   }
  </code></pre>
  
  <p><strong><em>UPDATE</em></strong></p>
  
  <p>After these changes, I can convert String to Long</p>
  
  <ul>
  <li>I've changed primitive type long to reference type Long in the VisitorRequestBase</li>
  <li><p>I've created Converter and registered to the application's context by this code.</p>
  
  <pre><code>    &lt;bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"&gt;
          &lt;property name="converters"&gt;
              &lt;list&gt;
                  &lt;bean class="com.test.mvvm.converters.StringToLongConverter"/&gt;
              &lt;/list&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
  
      &lt;mvc:annotation-driven conversion-service="conversionService" /&gt;
  </code></pre></li>
  </ul>