americanexpress / nodes

A GraphQL JVM Client - Java, Kotlin, Scala, etc.
Apache License 2.0
307 stars 70 forks source link

Cannot deserialize value of type `java.time.LocalDateTime` from String \"2020-01-30T13:42:34.400\ #104

Closed smfaizalkhan closed 4 years ago

smfaizalkhan commented 4 years ago

@chemdrew @realityforge Hi,

Im trying to use the GraphQL API and we have the need to deserialize a field that is in String to LocalDateTime and in that case ,we get the below exception

"message" : "Servlet.service() for servlet [dispatcherServlet] in context with path [] threw 
  exception [Request processing failed; nested exception is GraphQLException{message='null', 
 status='200', description='Cannot deserialize value of type `java.time.LocalDateTime` from 
String \"2020-01-30T13:42:34.400\": Failed to deserialize java.time.LocalDateTime: 
(java.time.format.DateTimeParseException) Text '2020-01-30T13:42:34.400' could not be 
parsed at index 10\n at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: 
  io.aexp.nodes.graphql.Wrapper[\"data\"]- 
   >com.ing.diba.scalable.domain.inbound.PortFolioResponse[\"realTimeValuation\"]- 
    >com.ing.diba.scalable.domain.inbound.RealTimeValuationResponse[\"dateTime\"])', 
     errors=null}] 

The code to invoke is

public GraphQLResponseEntity<EntityResponse> getEntity(Long 
 entityId) {
    GraphQLResponseEntity<EntityResponse> responseEntity = new 

    GraphQLRequestEntity requestEntity = null;
    try {
        requestEntity = GraphQLRequestEntity.Builder()
                .url(portFolioOverViewProperties.getConnectionUrl())
                .request(Entity.class)
                .arguments(new Arguments("entityOverview", new Argument("id", entityId)))
                .build();
    } catch (MalformedURLException e) {
        log.error("MalFormed URL {}", e);
        throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, 
    e.getMessage(), e);
    }
    responseEntity = graphQLTemplate.query(requestEntity, Entity.class);
    return responseEntity;
}

On debugging we found that the exception occurs from the deserialize method of LocalDateTimeDeserializer class of jacksonjar at highlighted line

   public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws 
         IOException {
    if (parser.hasTokenId(6)) {
        String string = parser.getText().trim();
        if (string.length() == 0) {
            return !this.isLenient() ? (LocalDateTime)this._failForNotLenient(parser, context, 
   JsonToken.VALUE_STRING) : null;
        } else {
            try {
                if (this._formatter == DEFAULT_FORMATTER && string.length() > 10 && 
  string.charAt(10) == 'T') {
                    return string.endsWith("Z") ? LocalDateTime.ofInstant(Instant.parse(string), 
  ZoneOffset.UTC) : LocalDateTime.parse(string, DEFAULT_FORMATTER);
                } **else {
                 return LocalDateTime.parse(string, this._formatter);
                }**
            } catch (DateTimeException var12) {
                return (LocalDateTime)this._handleDateTimeException(context, var12, string);
            }
        }

But if we parse it locally we don't get the exception

   LocalDateTime responseDateTime = LocalDateTime.parse(realTimeValuation.getDateTime());

Can you let me know what is causing this issue? and so its possible to resolve it in our application

chemdrew commented 4 years ago

In your request builder add this .scalars(LocalDateTime.class)

It's described a tad more here: https://americanexpress.io/graphql-for-the-jvm/