Format Time using initBinder

Asked

Viewed 90 times

4

I need to catch the time with the "hh:mm" format but it is not working, follow the error also to better specify:

Whitelabel Error Page This application has no Explicit Mapping for /error, so you are Seeing this as a fallback.

Tue Dec 18 13:56:56 BRST 2018
There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='cartelas'. Error count: 1
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'cartelas' on field 'final_time': rejected value [17:20]; codes [typeMismatch.cartelas.final_time,typeMismatch.final_time,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [cartelas.final_time,final_time]; arguments []; default message [final_time]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'final_time'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "17:20"]
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:164)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:126)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:166)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

My class:

package br.com.sky.iTvMC.modelo;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.springframework.format.annotation.DateTimeFormat;

@Table(name = "CARTELAS_NEW_CHANNEL_HD")
@Entity
public class Cartelas {
@SequenceGenerator(name = "seqCart", sequenceName = 
"SEQ_CARTELAS_NEW_CHANNEL_HD", allocationSize = 1)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqCart")
private Long id;
private static final String server_folder = "C:'\'Projetos";

@DateTimeFormat(pattern = "dd/MM/yyyy")
@Temporal(TemporalType.DATE)
private Date initial_date;

@DateTimeFormat(pattern = "dd/MM/yyyy")
@Temporal(TemporalType.DATE)
private Date final_date;

@DateTimeFormat(pattern = "hh:mm")
@Temporal(TemporalType.TIME)
private Date initial_time;

@DateTimeFormat(pattern = "hh:mm")
@Temporal(TemporalType.TIME)
private Date final_time;

@Enumerated(EnumType.STRING)
private CelulasCartela celulas;

private String who;

public Long getId() {
    return id;
}

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

public static String getServerFolder() {
    return server_folder;
}

public Date getInitial_date() {
    return initial_date;
}

public Date getFinal_date() {
    return final_date;
}

public Date getInitial_time() {
    return initial_time;
}

public Date getFinal_time() {
    return final_time;
}

public CelulasCartela getCelulas() {
    return celulas;
}

public void setFinal_time(Date final_time) {
    this.final_time = final_time;
}

public void setInitial_time(Date initial_time) {
    this.initial_time = initial_time;
}

public void setInitial_date(Date initial_date) {
    this.initial_date = initial_date;
}

public void setFinal_date(Date final_date) {
    this.final_date = final_date;
}

public void setCelulas(CelulasCartela celulas) {
    this.celulas = celulas;
}

public String getWho() {
    return who;
}

public void setWho(String who) {
    this.who = who;
}

}

Controller

package br.com.sky.iTvMC.controller;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import br.com.sky.iTvMC.modelo.Cartelas;
import br.com.sky.iTvMC.modelo.CelulasCartela;
import br.com.sky.iTvMC.repository.CartelasRepository;

@Controller
@RequestMapping("/cartelas")
public class ClientChannelController {

@Autowired
CartelasRepository cartelaRepository;

@RequestMapping("/novo")
public ModelAndView novo() {
    ModelAndView mv = new ModelAndView("cadastrarCartela");
    return mv;
}

@InitBinder
public void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm"); //yyyy-MM- 
dd'T'HH:mm:ssZ example
    dateFormat.setLenient(false);
   // System.out.println("init binder");
    binder.registerCustomEditor(Date.class, "initial_time", new 
CustomDateEditor(dateFormat, true));
    binder.registerCustomEditor(Date.class, "final_time", new 
CustomDateEditor(dateFormat, true));
}

@RequestMapping(method = RequestMethod.POST)
public ModelAndView salvar(Cartelas cartela) {
    System.out.println("Data inicial: "+ cartela.getInitial_date());
    System.out.println("Data final: "+ cartela.getFinal_date());
    System.out.println("celula: "+ cartela.getCelulas());        
    System.out.println("hora incial: "+ cartela.getInitial_time());
    System.out.println("hora final: "+ cartela.getFinal_time());        
    cartelaRepository.save(cartela);
    ModelAndView mv = new ModelAndView("cadastrarCartela");
    mv.addObject("mensagem", "Cartela cadastrada com sucesso!");
    return mv;      
}

@ModelAttribute("todasCelulas")
public List<CelulasCartela> todasCelulas(){
    return Arrays.asList(CelulasCartela.values());
}


}

The form page

<div class="row">
  <div class="col-md-2 col-xs-4 col-md-offset-1">
    <div class="form-group">
      <label for="inputDatacartela">Data Inicio</label>
      <div class="input-group">
        <input type="text" class="form-control" data-provide="datepicker" data-date-orientation="bottom" data-date-format="dd/mm/yyyy" data-date-language="pt-BR" data-date-autoclose="true" data-date-today-highlight="true" autocomplete="off" name="initial_date"
          placeholder="dd/mm/yyyy">
        <div class="input-group-addon">
          <span class="glyphicon glyphicon-calendar"></span>
        </div>
      </div>
    </div>
  </div>
  <div class="col-md-2 col-xs-4 col-md-offset-1">
    <div class="form-group">
      <label for="inputHoraFimCartela">Hora Inicio</label>
      <div class="input-group">
        <div class="input-group clockpicker" data-autoclose="true">
          <input type="text" class="form-control" name="initial_time" placeholder="00:00" autocomplete="off">
          <span class="input-group-addon"> <span
														class="glyphicon glyphicon-time"></span>
          </span>
        </div>
        <script type="text/javascript">
          $('.clockpicker').clockpicker();
        </script>
      </div>
    </div>
  </div>
</div>
<!-- Próxima linha  -->
<div class="row">
  <div class="col-md-2 col-xs-4 col-md-offset-1">
    <div class="form-group">
      <label for="inputFimCartela">Data Final</label>
      <div class="input-group">
        <input type="text" class="form-control" data-provide="datepicker" data-date-orientation="bottom" data-date-format="dd/mm/yyyy" data-date-language="pt-BR" data-date-autoclose="true" data-date-today-highlight="true" autocomplete="off" name="final_date"
          placeholder="dd/mm/yyyy">
        <div class="input-group-addon">
          <span class="glyphicon glyphicon-calendar"></span>
        </div>
      </div>
    </div>
  </div>
  <div class="col-md-2 col-xs-4 col-md-offset-1">
    <div class="form-group">
      <label for="inputFimCartela">Hora Final</label>
      <div class="input-group">
        <div class="input-group clockpicker" data-autoclose="true">
          <input type="text" class="form-control" name="final_time" placeholder="00:00" autocomplete="off">
          <span class="input-group-addon"> <span
														class="glyphicon glyphicon-time"></span>
          </span>
        </div>
        <script type="text/javascript">
          $('.clockpicker').clockpicker();
        </script>
      </div>
    </div>
  </div>
</div>

1 answer

2

According to the error message:

... [Failed to Convert Property value of type 'java.lang.String' to required type 'java.util.Date' for Property 'final time'; nested Exception is java.lang.Illegalargumentexception: Could not parse date: Unparseable date: "17:20"

That means that the String with the value "17:20" was passed to the SimpleDateFormat that you created, but it was not possible to do the Parsing.

Considering the SimpleDateFormat created in your method initBinder:

// SimpleDateFormat que você criou
SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm");
dateFormat.setLenient(false);

// tenta fazer o parsing de 17:20
Date date = dateFormat.parse("17:20");

This code throws an exception:

java.text.Parseexception: Unparseable date: "17:20"

This is because hh corresponds to the field Hour in am/pm, with values between 1 and 12 (for example, the 5 it can be as much 5 in the morning as 5 in the afternoon).

This SimpleDateFormat until would accept values greater than 12 for the hours, but how you used setLenient(false), this causes only values between 1 and 12 to be accepted, and any other bid exception.

As you are receiving values greater than 12, use HH (capital letters) in order to accept values between 0 and 23 (5 it’s 5:00 in the morning and 17 it’s 5 in the afternoon):

// usar HH para as horas (em vez de hh)
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");
dateFormat.setLenient(false);
// agora sim faz o parsing sem lançar exceção
Date date = dateFormat.parse("17:20");

Use the right field

By default, SimpleDateFormat is lenient, which means it accepts any values and tries to find a way to adjust them (what can generate some pretty strange results if you don’t take care).

Using setLenient(false), this permissive mode is switched off and the class becomes more restrictive, accepting only values within the allowed range for each field. And if you look at documentation, you will see that there are 4 fields for the hour, each one represented by a different letter and with a specific range of values:

Letra   Nome do campo/valores
H       Hour in day (0-23)
k       Hour in day (1-24)
K       Hour in am/pm (0-11)
h       Hour in am/pm (1-12)

Like you were wearing hh (lower case), only values between 1 and 12 are allowed. When trying to do "17:20", the exception occurs, since 17 is outside the range of valid values for the field h.

Note that in your case you can use HH (capital), or kk (lower case): the first accepts midnight as zero, and the second as 24. Check in your use cases how you receive this value and use the field that is most suitable.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.