Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot construct instance of `java.time.LocalDate` - Spring boot, elasticseach, jackson

I'm using Spring-boot 2.0.0.M7 and spring-boot-starter-data-elasticsearch and elasticsearch 5 and I'm getting an error by deserializing a LocalDate field.

My Document looks like that:

@Document(indexName= "myIndex", type = "cluster") public class Cluster {      @Id     @Field     private Long id;     @Field     private String name;     @Field     private ClusterUrl clusterUrl;     @Field     private ClusterVisible clusterVisible; } 

Where ClusterVisible is a child object which holds the LocalDates:

public class ClusterVisible {      @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy")     private LocalDate start;     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy")     private LocalDate end; } 

So I just make a query for one cluster Id and I get this exception:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDate` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)  at [Source: (String)"{"id":12345,"name":"Cluster name ","clusterName":{"de":"Cluster de","it":null,"fr":null},"clusterUrl":{"de":"/url/results","it":null,"fr":null},"clusterVisible":{"start":{"year":2017,"month":"OCTOBER","dayOfMonth":9,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":282,"leapYear":false,"mo"[truncated 252 chars]; line: 1, column: 388] (through reference chain: com.example.elasticsearch5.es.cluster.model.Cluster["clusterVisible"]->com.example.elasticsearch5.es.cluster.model.ClusterVisible["start"])     at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)     at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)     at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)     at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1290)     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)     at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)     at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)     at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)     at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)     at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)     at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)     at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)     at org.springframework.data.elasticsearch.core.DefaultEntityMapper.mapToObject(DefaultEntityMapper.java:65) 

I already know that I need to add some jackson dependencies for the java.time api so I added:

<dependency>     <groupId>com.fasterxml.jackson.datatype</groupId>     <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <dependency>     <groupId>com.fasterxml.jackson.core</groupId>     <artifactId>jackson-databind</artifactId>     <version>2.9.4</version> </dependency> 

But this does not help for now. I also checked the entry in the index by making a query using kibana. The result of the query is:

... "clusterVisible": {     "start": {       "year": 2017,       "month": "OCTOBER",       "dayOfMonth": 25,       "dayOfWeek": "WEDNESDAY",       "era": "CE",       "dayOfYear": 298,       "leapYear": false,       "monthValue": 10,       "chronology": {         "id": "ISO",         "calendarType": "iso8601"       }     },     "end": {       "year": 3000,       "month": "JANUARY",       "dayOfMonth": 1,       "dayOfWeek": "WEDNESDAY",       "era": "CE",       "dayOfYear": 1,       "leapYear": false,       "monthValue": 1,       "chronology": {         "id": "ISO",         "calendarType": "iso8601"       }     } } 

What do I miss for fixing this error?

Addition: The exact error occours at mapper.mapToObject. So I created a new DefaultEntityMapper(); some lines before. Could that be the issue?

@Override public Page<Cluster> findClustersAndScoreByText(String text) {     QueryBuilder queryBuilder = QueryBuilders.boolQuery()             .should(QueryBuilders.queryStringQuery(text).lenient(true).defaultOperator(Operator.OR)                     .field("name")                     .field("svno"));      NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(queryBuilder)             .withPageable(PageRequest.of(0, 100)).build();      DefaultEntityMapper mapper = new DefaultEntityMapper();     ResultsExtractor<Page<Cluster>> rs = new ResultsExtractor<Page<Cluster>>() {          @Override         public Page<Cluster> extract(SearchResponse response) {             ArrayList<Cluster> hotels = new ArrayList<>();             SearchHit[] hits = response.getHits().getHits();             for (SearchHit hit : hits) {                 try {                     Cluster cluster = mapper.mapToObject(hit.getSourceAsString(), Cluster.class);                     cluster.setScore(hit.getScore());                     hotels.add(cluster);                 } catch (IOException e) {                     e.printStackTrace();                 }             }             return new PageImpl<>(hotels, PageRequest.of(0, 100), response.getHits().getTotalHits());         }     };      return elasticsearchTemplate.query(nativeSearchQuery, rs); } 
like image 710
Patrick Avatar asked Feb 19 '18 14:02

Patrick


1 Answers

add below annotation over the field LocalDate

@JsonDeserialize(using = LocalDateDeserializer.class) @JsonSerialize(using = LocalDateSerializer.class) private LocalDate start; 
like image 173
sanjeevjha Avatar answered Oct 11 '22 16:10

sanjeevjha