Sandymcp
06/05/2023, 2:00 PMclass SalesHierarchyQueries(
val salesOpportunityService: SalesOpportunityService,
val salesHierarchyResolver: SalesHierarchyResolver
) : Query {
suspend fun activeProductType(context: VkGraphQLContext, parkId: UUID): ProductTypeEnum {
Sandymcp
06/05/2023, 2:00 PMDariusz Kuc
06/05/2023, 4:23 PMDataFetchingEnvironment
instead and read context from itSandymcp
06/06/2023, 9:30 AMnested exception is com.expediagroup.graphql.generator.exceptions.TypeNotSupportedException: Cannot convert java.math.BigDecimal?
Sandymcp
06/06/2023, 9:31 AMSandymcp
06/06/2023, 9:31 AMSandymcp
06/06/2023, 10:01 AMimplementation 'com.graphql-java:graphql-java-extended-scalars:20.2
is the solution?Dariusz Kuc
06/06/2023, 2:28 PMSandymcp
06/12/2023, 10:36 PMCaused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [graphql.schema.GraphQLSchema]: Factory method 'schema' threw exception; nested exception is java.lang.IllegalArgumentException: Class declares 1 type parameters, but 0 were provided.
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
... 55 common frames omitted\nCaused by: java.lang.IllegalArgumentException: Class declares 1 type parameters, but 0 were provided.
at kotlin.reflect.full.KClassifiers.createType(KClassifiers.kt:54)
at kotlin.reflect.full.KClassifiers.createType$default(KClassifiers.kt:43)
at com.expediagroup.graphql.generator.internal.types.GenerateObjectKt.generateObject(generateObject.kt:52)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.getGraphQLType(generateGraphQLType.kt:106)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.access$getGraphQLType(generateGraphQLType.kt:1)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:67)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.state.TypesCache.buildIfNotUnderConstruction$graphql_kotlin_schema_generator(TypesCache.kt:150)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.objectFromReflection(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.generateGraphQLType(generateGraphQLType.kt:45)
at com.expediagroup.graphql.generator.internal.types.GenerateFunctionKt.generateFunction(generateFunction.kt:55)
at com.expediagroup.graphql.generator.internal.types.GenerateInterfaceKt.generateInterface(generateInterface.kt:61)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.getGraphQLType(generateGraphQLType.kt:104)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.access$getGraphQLType(generateGraphQLType.kt:1)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:67)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.state.TypesCache.buildIfNotUnderConstruction$graphql_kotlin_schema_generator(TypesCache.kt:150)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.objectFromReflection(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.generateGraphQLType(generateGraphQLType.kt:45)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.generateGraphQLType$default(generateGraphQLType.kt:41)
at com.expediagroup.graphql.generator.internal.types.GenerateObjectKt.generateObject(generateObject.kt:52)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.getGraphQLType(generateGraphQLType.kt:106)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.access$getGraphQLType(generateGraphQLType.kt:1)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:67)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.state.TypesCache.buildIfNotUnderConstruction$graphql_kotlin_schema_generator(TypesCache.kt:150)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.objectFromReflection(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.generateGraphQLType(generateGraphQLType.kt:45)
at com.expediagroup.graphql.generator.internal.types.GeneratePropertyKt.generateProperty(generateProperty.kt:38)
at com.expediagroup.graphql.generator.internal.types.GenerateObjectKt.generateObject(generateObject.kt:61)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.getGraphQLType(generateGraphQLType.kt:106)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.access$getGraphQLType(generateGraphQLType.kt:1)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:67)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.state.TypesCache.buildIfNotUnderConstruction$graphql_kotlin_schema_generator(TypesCache.kt:150)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.objectFromReflection(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.generateGraphQLType(generateGraphQLType.kt:45)
at com.expediagroup.graphql.generator.internal.types.GenerateListKt.generateList(generateList.kt:25)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.getGraphQLType(generateGraphQLType.kt:97)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.access$getGraphQLType(generateGraphQLType.kt:1)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:67)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt$objectFromReflection$1.invoke(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.state.TypesCache.buildIfNotUnderConstruction$graphql_kotlin_schema_generator(TypesCache.kt:140)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.objectFromReflection(generateGraphQLType.kt:66)
at com.expediagroup.graphql.generator.internal.types.GenerateGraphQLTypeKt.generateGraphQLType(generateGraphQLType.kt:45)
at com.expediagroup.graphql.generator.internal.types.GenerateFunctionKt.generateFunction(generateFunction.kt:55)
at com.expediagroup.graphql.generator.internal.types.GenerateFunctionKt.generateFunction$default(generateFunction.kt:33)
at com.expediagroup.graphql.generator.internal.types.GenerateQueryKt.generateQueries(generateQuery.kt:43)
at com.expediagroup.graphql.generator.SchemaGenerator.generateSchema(SchemaGenerator.kt:89)
at com.expediagroup.graphql.generator.SchemaGenerator.generateSchema$default(SchemaGenerator.kt:72)
at com.expediagroup.graphql.generator.ToSchemaKt.toSchema(toSchema.kt:43)
at com.expediagroup.graphql.server.spring.NonFederatedSchemaAutoConfiguration.schema(NonFederatedSchemaAutoConfiguration.kt:76)
at com.expediagroup.graphql.server.spring.NonFederatedSchemaAutoConfiguration$$EnhancerBySpringCGLIB$$7295e274.CGLIB$schema$0(<generated>)
at com.expediagroup.graphql.server.spring.NonFederatedSchemaAutoConfiguration$$EnhancerBySpringCGLIB$$7295e274$$FastClassBySpringCGLIB$$bcb98ffc.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
at com.expediagroup.graphql.server.spring.NonFederatedSchemaAutoConfiguration$$EnhancerBySpringCGLIB$$7295e274.schema(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 56 common frames omitted\n"
Sandymcp
06/12/2023, 10:36 PMSandymcp
06/12/2023, 10:38 PMSandymcp
06/12/2023, 10:38 PMpackage de.nergie.vk.graphql
import com.expediagroup.graphql.generator.hooks.SchemaGeneratorHooks
import graphql.language.StringValue
import graphql.scalars.ExtendedScalars
import graphql.schema.Coercing
import graphql.schema.GraphQLScalarType
import graphql.schema.GraphQLType
import org.springframework.stereotype.Component
import java.math.BigDecimal
import java.time.Period
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.*
import kotlin.reflect.KType
@Component
class CustomSchemaGeneratorHooks() : SchemaGeneratorHooks {
/**
* Register additional GraphQL scalar types.
*/
override fun willGenerateGraphQLType(type: KType): GraphQLType? = when (type.classifier) {
ZonedDateTime::class -> graphqlZonedDateTimeType
Period::class -> graphqlPeriodType
UUID::class -> graphqlUUIDType
BigDecimal::class -> ExtendedScalars.GraphQLBigDecimal
else -> super.willGenerateGraphQLType(type)
}
}
val graphqlZonedDateTimeType = GraphQLScalarType.newScalar()
.name("ZonedDateTime")
.description("A type representing a formatted java.time.ZonedDateTime")
.coercing(ZonedDateTimeCoercing)
.build()
object ZonedDateTimeCoercing : Coercing<ZonedDateTime, String> {
private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX")
override fun parseValue(input: Any): ZonedDateTime {
return ZonedDateTime.parse(serialize(input), formatter)
}
override fun parseLiteral(input: Any): ZonedDateTime {
val string = (input as? StringValue)?.value
return ZonedDateTime.parse(string, formatter)
}
override fun serialize(dataFetcherResult: Any): String {
return when (dataFetcherResult) {
is String -> dataFetcherResult
is ZonedDateTime -> dataFetcherResult.format(formatter)
else -> "Invalid Date: $dataFetcherResult"
}
}
}
val graphqlPeriodType = GraphQLScalarType.newScalar()
.name("Period")
.description("A type representing a formatted java.time.Period")
.coercing(PeriodCoercing)
.build()
object PeriodCoercing : Coercing<Period, String> {
override fun parseValue(input: Any): Period {
return Period.parse(serialize(input))
}
override fun parseLiteral(input: Any): Period {
val string = (input as? StringValue)?.value
return Period.parse(string)
}
override fun serialize(dataFetcherResult: Any): String {
return when (dataFetcherResult) {
is String -> dataFetcherResult
is Period -> dataFetcherResult.toString()
else -> "Invalid Period: ${dataFetcherResult.javaClass}"
}
}
}
val graphqlUUIDType = GraphQLScalarType.newScalar()
.name("UUID")
.description("A type representing a formatted java.util.UUID")
.coercing(UUIDCoercing)
.build()
object UUIDCoercing : Coercing<UUID, String> {
override fun parseValue(input: Any): UUID = UUID.fromString(serialize(input))
override fun parseLiteral(input: Any): UUID {
val uuidString = (input as? StringValue)?.value
return UUID.fromString(uuidString)
}
override fun serialize(dataFetcherResult: Any): String = dataFetcherResult.toString()
}
Sandymcp
06/12/2023, 10:40 PMDariusz Kuc
06/12/2023, 11:46 PMFoo<T>
, without seeing the whole schema it is hard to sayS.
06/16/2023, 10:05 AMinterface ExerciseModel {
val uuid: String
val title: String
val category: ExerciseCategory //this is an enum class
val duration: Int
suspend fun user(): DataFetcherResult<UserModel>
}
class ExerciseModelImpl(
override val uuid: String,
override val title: String,
override val category: ExerciseCategory,
override val duration: Int,
private val userId: String,
) : ExerciseModel {
override suspend fun user() : DataFetcherResult<UserModel> = UserService().getUser(userId.toUUID).respond()
}
and a few queries returning ExerciseModel
why does it say Cannot convert com.example.graphql.schema.models.ExerciseModel since it is not a valid GraphQL type or outside the supported packages "[com/example]"
?
(version: 7.0.0-alpha.5
)Michael Edwards
08/02/2023, 9:56 AMDavid Bieregger
08/29/2023, 9:25 PMclass ExposedDaoHook : SchemaGeneratorHooks {
private val graphQLSizedIterable = GraphQLScalarType.newScalar()
.name("SizedIterable")
.description("A custom scalar that converts SizedIterable to List")
.coercing(object : Coercing<SizedIterable<Any>, List<Any>> {
override fun serialize(dataFetcherResult: Any, graphQLContext: GraphQLContext, locale: Locale): List<Any>? {
return (dataFetcherResult as SizedIterable<Any>).toList()
}
})
.build()
private val graphQLLongEntityId = GraphQLScalarType.newScalar()
.name("LongEntityID")
.description("A custom scalar that converts LongEntityID to Long")
.coercing(object : Coercing<EntityID<Long>, Long> {
override fun serialize(dataFetcherResult: Any, graphQLContext: GraphQLContext, locale: Locale): Long {
return (dataFetcherResult as EntityID<Long>).value
}
}).build()
private val graphQLUUIDEntityID = GraphQLScalarType.newScalar()
.name("UUIDEntityID")
.description("A custom scalar that converts UUIDEntityID to UUID")
.coercing(object : Coercing<EntityID<UUID>, UUID> {
override fun serialize(dataFetcherResult: Any, graphQLContext: GraphQLContext, locale: Locale): UUID {
return (dataFetcherResult as EntityID<UUID>).value
}
}).build()
override fun willGenerateGraphQLType(type: KType): GraphQLType? {
return when (type.classifier) {
UUID::class -> ExtendedScalars.UUID
Long::class -> ExtendedScalars.GraphQLLong
EntityID::class ->
when (type.arguments[0].type!!.classifier) {
Long::class -> graphQLLongEntityId
UUID::class -> graphQLUUIDEntityID
else -> null
}
Instant::class -> Scalars.GraphQLString
LocalDate::class -> Scalars.GraphQLString
LocalTime::class -> Scalars.GraphQLString
Duration::class -> Scalars.GraphQLString
SizedIterable::class -> graphQLSizedIterable
else -> null
}
}
private val excludedDaoProperties = listOf("klass", "db", "_readValues", "readValues", "writeValues")
override fun isValidProperty(kClass: KClass<*>, property: KProperty<*>): Boolean {
if (!kClass.allSuperclasses.contains(Entity::class))
return super.isValidProperty(kClass, property)
return !excludedDaoProperties.contains(property.name)
}
val excludedDaoMethods =
listOf("isNewEntity", "delete", "flush", "refresh", "getValue", "setValue", "lookup", "storeWrittenValues")
override fun isValidFunction(kClass: KClass<*>, function: KFunction<*>): Boolean {
val superclasses = kClass.allSuperclasses
if (!superclasses.contains(Entity::class))
return super.isValidFunction(kClass, function)
if (excludedDaoMethods.contains(function.name))
return false
println(function.name)
return true
}
override fun willResolveMonad(type: KType): KType = when (type.classifier) {
SizedIterable::class -> List::class.createType(type.arguments)
else -> type
}
}
This will make the types get serialized correctly. Now we can install the plugin:
install(GraphQL) {
schema {
packages = listOf("com.example")
queries = listOf(
HelloQuery()
)
hooks = ExposedDaoHook()
}
}
val graphQLPlugin = plugin(GraphQL)
routing {
val route = post("graphql") {
newSuspendedTransaction(<http://Dispatchers.IO|Dispatchers.IO>) {
try {
graphQLPlugin.server.execute(call.request)?.let {
call.respond(it)
} ?: call.respond(HttpStatusCode.BadRequest)
} catch (e: UnsupportedOperationException) {
call.respond(HttpStatusCode.MethodNotAllowed)
} catch (e: Exception) {
call.respond(HttpStatusCode.BadRequest)
}
}
}
route.install(ContentNegotiation) {
jackson()
}
}
Sadly there is currently no way to wrap requests in a transaction. So we need to inline some internal functions of the library.
class HelloQuery : Query {
suspend fun user(id: Long) = UserDao.findById(id)
}
class Users : IdTable() {
var forename = varchar("forename", 256)
var surname = varchar("surname", 256)
}
class UserDao(id: EntityID<Long>) : LongEntity(id) {
var forename by Users.forename
var surname by Users.surname
}
Hope this helps someone that has the same use case, please feel free to ask or enhance my implementation if you see obvious bugsDariusz Kuc
09/18/2023, 11:57 PMasavio
09/19/2023, 7:28 AMHenrik Friedrichsen
09/29/2023, 12:15 PMgraphql-kotlin
v7! I'm looking into upgrading and noticed the interface for federated type resolvers changed. Previously it was possible to process multiple representation
objects in one call, now it seems to be one per call. This makes DB querying for us less efficient, as before we were able to batch load based on the list of IDs we have extracted from representations
. Is there still a way to do it like this?Melvin Biamont
10/10/2023, 1:29 PMgraphql-kotlin
obviously, but:
• when I started, graphql-kotlin
wasn't existing (or at a very early stage if I remember well)
• I wanted something lighter, easy to setup and play with
For personal reasons, I wasn't able to work on this project, but I finally finished it!
🚀 Allow me to introduce ArianeGraphQL (a clear reference to Apollo 😉).
I wrote a Medium post here: https://melvinbiamont.medium.com/lightweight-kotlin-graphql-server-5a26b6cab6d6
Feel free to share your thoughts on Medium or discuss it directly here in 🧵.Dariusz Kuc
10/17/2023, 4:34 PMSupercharge your GraphQL with Ktor and GraalVM
at https://windycity.devfest.io/ (free event) next week. If you are in Chicago next Tuesday 10/24 -> stop by to say hiS.
11/12/2023, 12:00 AMAll types within a GraphQL schema must have unique names. No two provided types may have the same name.
No provided type may have a name which conflicts with any built in types (including Scalar and Introspection types).
You have redefined the type 'LocalDateTime' from being a 'GraphQLScalarType' to a 'GraphQLScalarType'
S.
11/13/2023, 7:37 PMFrancois
11/27/2023, 6:06 PMFrancois
11/27/2023, 6:07 PMskennedy
12/29/2023, 6:26 PMDariusz Kuc
03/06/2024, 8:29 PMMitchell Syer
03/10/2024, 11:04 PMdany giguere
03/12/2024, 10:56 PM@GetMapping("/posts/{id}")
suspend fun getById(@PathVariable id: Long): ResponseEntity<PostDto> {
val response = postService.findById(id)
return if (response != null) ResponseEntity.ok(response)
else ResponseEntity.notFound().build()
}
I’d like to convert the project to use GraphQl. (it will be in a different demo of course with a bff and microservices)