Skip to main content
Version: 5.x.x

Gradle Plugin Usage

Downloading Schema SDL#

GraphQL endpoints are often public and as such many servers might disable introspection queries in production environment. Since GraphQL schema is needed to generate type safe clients, as alternative GraphQL servers might expose private endpoints (e.g. accessible only from within network, etc) that could be used to download schema in Schema Definition Language (SDL) directly. graphqlDownloadSDL task requires target GraphQL server endpoint to be specified and can be executed directly from the command line by explicitly passing endpoint parameter

$ gradle graphqlDownloadSDL --endpoint="http://localhost:8080/sdl"

Task can also be explicitly configured in your Gradle build file

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTask
val graphqlDownloadSDL by tasks.getting(GraphQLDownloadSDLTask::class) {    endpoint.set("http://localhost:8080/sdl")}
info

This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly invoke it OR configure it as a dependency of some other task.

Introspecting Schema#

Introspection task requires target GraphQL server endpoint to be specified. Task can be executed directly from the command line by explicitly passing endpoint parameter

$ gradle graphqlIntrospectSchema --endpoint="http://localhost:8080/graphql"

Task can also be explicitly configured in your Gradle build file

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
val graphqlIntrospectSchema by tasks.getting(GraphQLIntrospectSchemaTask::class) {    endpoint.set("http://localhost:8080/graphql")}
info

This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly invoke it OR configure it as a dependency of some other task.

Generating Client#

GraphQL Kotlin client code is generated based on the provided queries that will be executed against target GraphQL schemaFile. Separate class is generated for each provided GraphQL query and are saved under specified packageName.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {  packageName.set("com.example.generated")  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))}

This will process all GraphQL files located under src/main/resources and generate corresponding GraphQL Kotlin client data models. Generated classes will be automatically added to the project compile sources.

Generating Client with Custom Scalars#

By default, all custom GraphQL scalars will be serialized as Strings. You can override this default behavior by specifying custom scalar converter.

For example given following custom scalar in our GraphQL schema

scalar UUID

We can create a custom converter to automatically convert this custom scalar to java.util.UUID

package com.example
import com.expediagroup.graphql.client.converter.ScalarConverterimport java.util.UUID
class UUIDScalarConverter : ScalarConverter<UUID> {    override fun toScalar(rawValue: Any): UUID = UUID.fromString(rawValue.toString()    override fun toJson(value: UUID): String = value.toString()}

Afterwards we need to configure our plugin to use this custom converter

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.config.GraphQLScalarimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {  packageName.set("com.example.generated")  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))  customScalars.add(GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))}

Generating Client using Kotlinx Serialization#

GraphQL Kotlin plugins default to generate client data models that are compatible with Jackson. We can change this default behavior by explicitly specifying serializer type (in the extension or explicitly in the generate client task) and configuring kotlinx.serialization compiler plugin. See kotlinx.serialization documentation for details.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.config.GraphQLScalarimport com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer
plugins {    kotlin("plugin.serialization") version $kotlinVersion}
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {  packageName.set("com.example.generated")  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))  serializer.set(GraphQLSerializer.KOTLINX)}

Generating Client using Classpath Schema#

Client generation tasks require schemaFile to be provided. Using Gradle we can configure tasks to use local schema file, load it from an URI or consume it directly from a classpath. See Gradle TextResourceFactory for additional details.

If schema.graphql file is provided in a my-lib JAR we can configure our generate client task as follows

// build.gradle.ktsval graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {  packageName.set("com.example.generated")  val archive = configurations["compileClasspath"].filter {      // filter on the jar name.      it.name.startsWith("my-lib")  }  schemaFile.set(resources.text.fromArchive(archive, "schema.graphql").asFile())}

Generating Test Client#

GraphQL Kotlin test client code is generated based on the provided queries that will be executed against target GraphQL schemaFile. Separate class is generated for each provided GraphQL query and are saved under specified packageName.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
val graphqlGenerateTestClient by tasks.getting(GraphQLGenerateTestClientTask::class) {  packageName.set("com.example.generated")  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))}

This will process all GraphQL queries located under src/test/resources and generate corresponding GraphQL Kotlin clients. Generated classes will be automatically added to the project test compile sources.

info

graphqlGenerateTestClient cannot be configured through the graphql extension and has to be explicitly configured.

Minimal Client Configuration Example#

Following is the minimal configuration that runs introspection query against a target GraphQL server and generates a corresponding schema. This generated schema is subsequently used to generate GraphQL client code based on the queries provided under src/main/resources directory.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.graphql
graphql {  client {    endpoint = "http://localhost:8080/graphql"    packageName = "com.example.generated"  }}

Above configuration is equivalent to the following

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTaskimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLIntrospectSchemaTask
val graphqlIntrospectSchema by tasks.getting(GraphQLIntrospectSchemaTask::class) {  endpoint.set("http://localhost:8080/graphql")}val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {  packageName.set("com.example.generated")  schemaFile.set(graphqlIntrospectSchema.outputFile)  dependsOn("graphqlIntrospectSchema")}

Complete Client Configuration Example#

Following is a configuration example that downloads schema SDL from a target GraphQL server that is then used to generate the GraphQL client data models using kotlinx.serialization that are based on the provided query.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.config.GraphQLScalarimport com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializerimport com.expediagroup.graphql.plugin.gradle.graphql
plugins {    kotlin("plugin.serialization") version $kotlinVersion}
graphql {  client {    sdlEndpoint = "http://localhost:8080/sdl"    packageName = "com.example.generated"    // optional configuration    allowDeprecatedFields = true    customScalars = listOf(GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))    headers = mapOf("X-Custom-Header" to "My-Custom-Header")    queryFiles = listOf(file("${project.projectDir}/src/main/resources/queries/MyQuery.graphql"))    serializer = GraphQLSerializer.KOTLINX    timeout {        connect = 10_000        read = 30_000    }  }}

Above configuration is equivalent to the following

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.config.GraphQLScalarimport com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializerimport com.expediagroup.graphql.plugin.gradle.config.TimeoutConfigurationimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTaskimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
plugins {    kotlin("plugin.serialization") version $kotlinVersion}
val graphqlDownloadSDL by tasks.getting(GraphQLDownloadSDLTask::class) {    endpoint.set("http://localhost:8080/sdl")    headers.put("X-Custom-Header", "My-Custom-Header")    timeoutConfig.set(TimeoutConfiguration(connect = 10_000, read = 30_000))}val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {    packageName.set("com.example.generated")    schemaFile.set(graphqlDownloadSDL.outputFile)    // optional    allowDeprecatedFields.set(true)    customScalars.add(GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))    queryFiles.from("${project.projectDir}/src/main/resources/queries/MyQuery.graphql")    serializer.set(GraphQLSerializer.KOTLINX)
    dependsOn("graphqlDownloadSDL")}

Generating Multiple Clients#

GraphQL Kotlin Gradle Plugin registers tasks for generation of a client queries targeting single GraphQL endpoint. You can generate queries targeting additional endpoints by explicitly creating and configuring additional tasks.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTaskimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
val graphqlDownloadSDL by tasks.getting(GraphQLDownloadSDLTask::class) {    endpoint.set("http://localhost:8080/sdl")}val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {    packageName.set("com.example.generated.first")    schemaFile.set(graphqlDownloadSDL.outputFile)    queryFiles.from("${project.projectDir}/src/main/resources/queries/MyFirstQuery.graphql")    dependsOn("graphqlDownloadSDL")}
val graphqlDownloadOtherSDL by tasks.creating(GraphQLDownloadSDLTask::class) {    endpoint.set("http://localhost:8081/sdl")}val graphqlGenerateOtherClient by tasks.creating(GraphQLGenerateClientTask::class) {    packageName.set("com.example.generated.second")    schemaFile.set(graphqlDownloadOtherSDL.outputFile)    queryFiles.from("${project.projectDir}/src/main/resources/queries/MySecondQuery.graphql")    dependsOn("graphqlDownloadOtherSDL")}

Generating SDL Example#

GraphQL schema can be generated directly from your source code using reflections. graphqlGenerateSDL will scan your classpath looking for classes implementing Query, Mutation and Subscription marker interfaces and then generates the corresponding GraphQL schema using graphql-kotlin-schema-generator and default NoopSchemaGeneratorHooks. In order to limit the amount of packages to scan, this task requires users to provide a list of packages that can contain GraphQL types.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.graphql
graphql {  schema {    packages = listOf("com.example")  }}

Above configuration is equivalent to the following task definition

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateSDLTask
val graphqlGenerateSDL by tasks.getting(GraphQLGenerateSDLTask::class) {    packages.set(listOf("com.example"))}
info

This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly invoke it OR configure it as a dependency of some other task.

Generating SDL with Custom Hooks Provider Example#

Plugin will default to use NoopSchemaGeneratorHooks to generate target GraphQL schema. If your project uses custom hooks or needs to generate the federated GraphQL schema, you will need to provide an instance of SchemaGeneratorHooksProvider service provider that will be used to create an instance of your custom hooks.

graphqlGenerateSDL utilizes ServiceLoader mechanism to dynamically load available SchemaGeneratorHooksProvider service providers from the classpath. Service provider can be provided as part of your project, included in one of your project dependencies or through explicitly provided artifact. See Schema Generator Hooks Provider for additional details on how to create custom hooks service provider. Configuration below shows how to configure GraphQL Kotlin plugin with explicitly provided artifact to generate federated GraphQL schema.

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.graphql
graphql {  schema {    packages = listOf("com.example")  }}
dependencies {    graphqlSDL("com.expediagroup:graphql-kotlin-federated-hooks-provider:$graphQLKotlinVersion")}

Above configuration is equivalent to the following task definition

// build.gradle.ktsimport com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateSDLTask
val graphqlGenerateSDL by tasks.getting(GraphQLGenerateSDLTask::class) {    packages.set(listOf("com.example"))}
dependencies {    graphqlSDL("com.expediagroup:graphql-kotlin-federated-hooks-provider:$graphQLKotlinVersion")}
info

This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly invoke it OR configure it as a dependency of some other task.