Search code examples
javaspring-mvcvalidationdto

How to bind a calendar on DTO using Spring MVC


I have a form with a date Field. I would like to know how I could to bind on a DTO with Calendar attribute. I was trying with String, but the conversion to java.sql.Date was being very complicated.

HTML

<input type="text" id="date" name="date" />

Spring MVC

@RequestMapping(value = "/newholiday", method=RequestMethod.POST)
public String cadastrar(ModelMap model, HolidayDTO dto) {
    System.out.println(dto.getDate());
    return "/newholiday";
}

DTO

public class HolidayDTO extends DTO<Holiday> {
    private Calendar date;
}

If directly, It returns an exception:

HTTP ERROR 500

Problem accessing /cemiterio/feriados/cadastrar/. Reason:

    org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'holidayDTO' on field 'date': rejected value [23/12/1988]; codes [typeMismatch.holidayDTO.date,typeMismatch.date,typeMismatch.java.util.Calendar,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [holidayDTO.date,date]; arguments []; default message [date]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Calendar' for property 'date'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Calendar] for property 'date': no matching editors or conversion strategy found]
Caused by:

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'holidayDTO' on field 'date': rejected value [23/12/1988]; codes [typeMismatch.holidayDTO.date,typeMismatch.date,typeMismatch.java.util.Calendar,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [holidayDTO.date,date]; arguments []; default message [date]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Calendar' for property 'date'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Calendar] for property 'date': no matching editors or conversion strategy found]
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:810)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:359)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Solution

  • Instead of using Calendar object, I would highly advice you to use Joda Time because you will have all the flexibility to do date time manipulation AND most importantly, it is immutable. Converting Joda DateTime to java.sql.Date is as simple as this:-

    DateTime dateTime = ...;
    java.sql.Date sqlDate = new java.sql.Date(dateTime.getMillis());
    

    Here's an example:-

    Spring Form

    public class MyForm {
    
        @DateTimeFormat(pattern = "MM/dd/yyyy")
        private DateTime dateTime;
    
        public DateTime getDateTime() {
            return dateTime;
        }
    
        public void setDateTime(DateTime dateTime) {
            this.dateTime = dateTime;
        }
    }
    

    Controller

    @Controller
    @RequestMapping(value = "/")
    public class HomeController {
    
        @RequestMapping(method = RequestMethod.POST)
        public String post(@ModelAttribute MyForm myForm) {
            System.out.println("@@@@@@: " + myForm.getDateTime());
            return "home";
        }
    }
    

    JSP

    <spring:form modelAttribute="myForm">
        <spring:input path="dateTime"/>
        <spring:button>Submit</spring:button>
    </spring:form>