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)
- 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.