yahoo / elide

Elide is a Java library that lets you stand up a GraphQL/JSON-API web service with minimal effort.

Home Page:https://elide.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

elide-spring-boot-starter:7.0.0-pr5 doesn't work with spring boot 3.1.1

ynixt opened this issue · comments

Expected Behavior

Current Behavior

The following exception is throw:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.queryRunners' defined in class path resource [com/yahoo/elide/spring/config/ElideAutoConfiguration$RefreshableConfiguration$GraphQLConfiguration.class]: Failed to instantiate [com.yahoo.elide.graphql.QueryRunners]: Factory method 'queryRunners' threw exception with message: null

Possible Solution

Steps to Reproduce (for bugs)

  1. Follow the start guide https://elide.io/pages/guide/v7/01-start.html

Context

Your Environment

  • Elide version used: 7.0.0-pr5
  • Environment name and version (Java 1.8.0_152): Java 20.0.1
  • Operating System and version: Windows
  • Link to your project:

I have tried but failed the reproduce the issue. Can you provide the project you are using or a minimum reproduction using https://github.com/yahoo/elide-spring-boot-example/tree/elide-7.x?

One thing I noticed is that you are using the refreshable configuration so if you are using elide-spring-boot-example you need to set spring.cloud.refresh.enabled=true to replicate your setup.

Project example https://github.com/ynixt/test-elide

In a brief summary:

Is a kotlin project with:

  • spring boot 3.1.1
  • h2 memory
  • elide-spring-boot-starter:7.0.0-pr5
  • flyway

the application.yml contains

elide:
  json-api:
    path: /api/v1
    enabled: true
  graphql:
    path: /graphql/api/v1
    enabled: true
  api-docs:
    path: /doc
    enabled: true
    version: openapi_3_0

Today I discover that the problem occurs when elide is trying to convert my null ZonedDateTime on GraphQLConversionUtils.java:531:

if (inputType == null) {

                /* Attempt to convert an object type */
            inputType = classToInputObject(conversionClass);
        }

The full exception is

Caused by: java.lang.StackOverflowError: null
	at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:586) ~[na:na]
	at java.base/java.lang.StringBuilder.append(StringBuilder.java:179) ~[na:na]
	at ch.qos.logback.core.pattern.FormattingConverter.write(FormattingConverter.java:39) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.pattern.CompositeConverter.convert(CompositeConverter.java:24) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.pattern.FormattingConverter.write(FormattingConverter.java:36) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.pattern.PatternLayoutBase.writeLoopOnConverters(PatternLayoutBase.java:116) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:176) ~[logback-classic-1.4.8.jar:1.4.8]
	at ch.qos.logback.classic.PatternLayout.doLayout(PatternLayout.java:39) ~[logback-classic-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.encoder.LayoutWrappingEncoder.encode(LayoutWrappingEncoder.java:114) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.OutputStreamAppender.writeOut(OutputStreamAppender.java:192) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:228) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51) ~[logback-core-1.4.8.jar:1.4.8]
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272) ~[logback-classic-1.4.8.jar:1.4.8]
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259) ~[logback-classic-1.4.8.jar:1.4.8]
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426) ~[logback-classic-1.4.8.jar:1.4.8]
	at ch.qos.logback.classic.Logger.filterAndLog_1(Logger.java:402) ~[logback-classic-1.4.8.jar:1.4.8]
	at ch.qos.logback.classic.Logger.info(Logger.java:588) ~[logback-classic-1.4.8.jar:1.4.8]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.classToInputObject(GraphQLConversionUtils.java:410) ~[elide-graphql-7.0.0-pr5.jar:na]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.fetchScalarOrObjectInput(GraphQLConversionUtils.java:531) ~[elide-graphql-7.0.0-pr5.jar:na]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.attributeToInputObject(GraphQLConversionUtils.java:352) ~[elide-graphql-7.0.0-pr5.jar:na]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.classToInputObject(GraphQLConversionUtils.java:432) ~[elide-graphql-7.0.0-pr5.jar:na]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.fetchScalarOrObjectInput(GraphQLConversionUtils.java:531) ~[elide-graphql-7.0.0-pr5.jar:na]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.attributeToInputObject(GraphQLConversionUtils.java:354) ~[elide-graphql-7.0.0-pr5.jar:na]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.classToInputObject(GraphQLConversionUtils.java:432) ~[elide-graphql-7.0.0-pr5.jar:na]
	at com.yahoo.elide.graphql.GraphQLConversionUtils.fetchScalarOrObjectInput(GraphQLConversionUtils.java:531) ~[elide-graphql-7.0.0-pr5.jar:na]

And this can be fixed with

kotlin
@ElideTypeConverter(type = ZonedDateTime::class, name = "ZonedDateTimeSerde")
class ZonedDateTimeSerde : Serde<String, ZonedDateTime> {
    override fun deserialize(value: String?): ZonedDateTime? {
        return if (value == null) null else ZonedDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
    }

    override fun serialize(value: ZonedDateTime?): String? {
        return value?.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
    }
}

I didn't know that ZonedDateTime doesn't have a serde by default. All was my mistake. I'm closing this issue.

Is there any reason why you need to use ZonedDateTime instead of OffsetDateTime? There is a default serde for OffsetDateTime.

Even if a default serde for ZonedDateTime was provided the string format for ZonedDateTime contains the time zone information in square brackets 2007-12-03T10:15:30+01:00[Europe/Paris] and this isn't a standard yet and I'm not sure if this is what clients would expect.