0
votes

I have a Grails 3.1.2 application

One of my domain classes is Goal

import java.time.LocalDateTime
import java.time.temporal.ChronoUnit

class Goal {
    String name
    String description
    LocalDateTime targetDate
    Date dateCreated
    Date lastUpdated
    static constraints = {
        name(nullable: false, blank: false)
    }
}

When I call validate on my an instance of Goal I get:

  • Field error in object 'com.liftyourgame.model.Goal' on field 'targetDate': rejected value [2016-01-28T15:10:39.000Z]; codes [com.liftyourgame.model.Goal.targetDate.typeMismatch.error,com.liftyourgame.model.Goal.targetDate.typeMismatch,goal.targetDate.typeMismatch.error,goal.targetDate.typeMismatch,typeMismatch.com.liftyourgame.model.Goal.targetDate,typeMismatch.targetDate,typeMismatch.java.time.LocalDateTime,typeMismatch]; arguments [targetDate]; default message [Could not find matching constructor for: java.time.LocalDateTime(java.lang.String)]

How can I change the validation so it doesn't need this constructor?

1
Hi Andreas, It's not really a duplicate. I'm using mappings from org.hibernate:hibernate-java8:5.1.0.Final The hibernate schema validation passes on startup mapping the LocalDateTime fields to MySQL DateTime field types - Greg Pagendam-Turner
@Andreas The problem described here doesn't really relate to Hibernate or persistence. The problem is related to the default data binder. - Jeff Scott Brown

1 Answers

2
votes

How can I change the validation so it doesn't need this constructor?

You can't, but the validation isn't really the problem. The data binder is the problem. The default binder does not yet have built in support for LocalDateTime.

You can register your own converter like this:

Converter:

// src/main/groovy/demo/MyDateTimeConverter.groovy
package demo

import grails.databinding.converters.ValueConverter

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

class MyDateTimeConverter implements ValueConverter {
    @Override
    boolean canConvert(Object value) {
        value instanceof String
    }

    @Override
    Object convert(Object value) {
        def fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
        LocalDateTime.parse(value, fmt)
    }

    @Override
    Class<?> getTargetType() {
        LocalDateTime
    }
}

Register it as a bean:

// grails-app/conf/spring/resources.groovy
beans = {
    myConverter demo.MyDateTimeConverter
}