2
<form th:action="@{/hi}"  th:object="${datum}" method="post">
    <p>date : <input type="date" th:field="*{date}"/> </p>
    <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>

Controller for form above

@PostMapping("/hi")
fun testum(@ModelAttribute datum: Datum) {
    println(datum)
}

simple pojo class

class Datum(
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        var date: LocalDate? = null
)

I am trying to send date in form but get this exception:

Resolved exception caused by Handler execution: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'datum' on field 'date': rejected value [2018-06-20]; codes [typeMismatch.datum.date,typeMismatch.date,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [datum.date,date]; arguments []; default message [date]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'date'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDate] for value '2018-06-20'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2018-06-20]]

But if I change type from LocalDate to String it works fine. I want to map date that is in form to date property of Datum class. can anyone help me with that? any links? thanks.

This link did not help me similar problem

1

2 Answers 2

3

It's an old question, but I'm leaving an answer just for future readers.
This is not an issue with thymeleaf, and more of an issue of @DateTimeFormat binding.
The example in the question above will work if the Datum class is changed like so:

Solution 1.

class Datum {
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    var date: LocalDate? = null
}

note that the date field has been moved from declaring in the primary constructor into the class body.
(notice the change from Datum (...) to Datum {...})

Solution 2.

class Datum (
   @field:DateTimeFormat(pattern = "yyyy-MM-dd") var date: LocalDate? = null
)

if you need to have it declared inside constructor due to having it as data class or other reasons, you have to annotate using use-site targets.
HOWEVER, beware that Solution 2 may not always work. I cannot reproduce in a sample project - but in a real-life project, there was an issue where @field:DateTimeFormat didn't correctly bind the request parameter string to the Date object. It sometimes worked and sometimes didn't, making it very tricky to debug.
When it didn't work, it spewed out errors like Validation failed for object='Datum'. Error count: 1, while reverting to Solution 1 instead always worked. Every time we compiled again, Solution 2 sometimes worked and randomly broke without any code changes.
We've resorted to strictly putting @DateTimeFormat annotated fields down to the class body declaration to insure it works.

Sign up to request clarification or add additional context in comments.

Comments

0

I just created your example using this as controller:

@Controller
public class StackOverflow {

@GetMapping("/stack")
public String template(Model m) {
    m.addAttribute("datum", new Datanum());
    return "stackoverflow.html";
}

@PostMapping("/stack2")
public String testum(@ModelAttribute Datanum user) {
    System.out.println(user.getDate());
    return null;
}
}

this as view:

<!DOCTYPE html>
<html xmlns:th="http://www.thymleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>

<form th:action="@{/stack2}"  th:object="${datum}" method="post">
            <p>date : <input type="date" th:field="*{date}"/> </p>
            <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
        </form>
</body>
</html>

and this as Bean

   import java.time.LocalDate;

   import org.springframework.format.annotation.DateTimeFormat;

   public class Datanum{
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate date;

        public LocalDate getDate() {
            return date;
        }

        public void setDate(LocalDate date) {
            this.date = date;
        }
    }

and it worked:

enter image description here

enter image description here

The difference I see is that you're using var on your Bean

  var date: LocalDate? = null

I think that is Java 10, isn't it? why don't you try to use

the bean as I did , maybe that could help you.

instead of var use LocalDate

hope this works

4 Comments

it is not java 10 it is kotlin. thanks. switched back to java from kotlin
class Datum ( @DateTimeFormat(pattern = "yyyy-MM-dd") var date: LocalDate ) Problem was that I create properties in primary constructor, I do not know why but thymeleaf cannot set values in that way. it did not work with default values even class Datum ( @DateTimeFormat(pattern = "yyyy-MM-dd") var date: LocalDate = LocalDate.MIN )
Unfortunately this answer is totally unrelated to the question. It doesn't use the correct language(kotlin), and all it points out is that it works in Java. The main issue in the original question is not having annotation use targets set up correctly, so this answer should probably be downvoted for less visibility to prevent future readers getting confused.
@Yussef You saved my day

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.