Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class GraphQLGradlePlugin : Plugin<Project> {

val generateSchemaTask = project.tasks.named(GENERATE_SDL_TASK_NAME, GraphQLGenerateSDLTask::class.java).get()
generateSchemaTask.packages.set(supportedPackages)
generateSchemaTask.jvmArguments.convention(extension.schemaExtension.jvmArguments)
}

if (extension.isGraalVmConfigurationAvailable()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ open class GraphQLPluginClientExtension {
open class GraphQLPluginSchemaExtension {
/** List of supported packages that can contain GraphQL schema type definitions. */
var packages: List<String> = emptyList()

/**
* JVM arguments passed to the process-isolated worker that generates the SDL, e.g. `listOf("-Xmx2g")`.
*
* SDL generation runs in a forked JVM that uses the Gradle default heap. Schemas large enough to
* exhaust that heap (resulting in an `OutOfMemoryError`) can raise it by configuring these arguments.
*/
var jvmArguments: List<String> = emptyList()
}

open class GraphQLPluginGraalVmExtension {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ abstract class GraphQLGenerateSDLTask : SourceTask() {
@OutputFile
val schemaFile: RegularFileProperty = project.objects.fileProperty()

/**
* JVM arguments passed to the process-isolated worker that generates the SDL, e.g. `listOf("-Xmx2g")`.
*
* SDL generation runs in a forked JVM that uses the Gradle default heap. Schemas large enough to
* exhaust that heap (resulting in an `OutOfMemoryError`) can raise it by configuring these arguments.
* Defaults to an empty list, i.e. no additional JVM arguments.
*/
@Input
@Optional
@Option(option = "jvm-args", description = "JVM arguments for the SDL generation worker, e.g. -Xmx2g")
val jvmArguments: ListProperty<String> = project.objects.listProperty(String::class.java)

@get:Inject
abstract val workerExecutor: WorkerExecutor

Expand Down Expand Up @@ -101,8 +113,10 @@ abstract class GraphQLGenerateSDLTask : SourceTask() {
val workQueue: WorkQueue = workerExecutor.processIsolation { workerSpec: ProcessWorkerSpec ->
workerSpec.forkOptions {
it.setExecutable(launcher.get().executablePath.asFile)
it.jvmArgs(jvmArguments.getOrElse(emptyList()))
}
logger.debug("worker executable: \n${workerSpec.forkOptions.executable}")
logger.debug("worker jvm args: \n${workerSpec.forkOptions.allJvmArgs}")

val workerClasspath = pluginClasspath.plus(projectClasspath).plus(source.files)
workerSpec.classpath.from(workerClasspath)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2026 Expedia, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.expediagroup.graphql.plugin.gradle.tasks

import com.expediagroup.graphql.plugin.gradle.GraphQLGradlePlugin
import com.expediagroup.graphql.plugin.gradle.GraphQLPluginExtension
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.testfixtures.ProjectBuilder
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class GraphQLGenerateSDLTaskTest {

@Test
fun `jvmArguments defaults to an empty list`() {
val project = ProjectBuilder.builder().build()
project.pluginManager.apply("java")
project.pluginManager.apply(GraphQLGradlePlugin::class.java)

val task = project.tasks.getByName(GENERATE_SDL_TASK_NAME) as GraphQLGenerateSDLTask
assertTrue(task.jvmArguments.get().isEmpty())
}

@Test
fun `jvmArguments configured on the schema extension are propagated to the task`() {
val project = ProjectBuilder.builder().build()
project.pluginManager.apply("java")
project.pluginManager.apply(GraphQLGradlePlugin::class.java)

val extension = project.extensions.getByType(GraphQLPluginExtension::class.java)
extension.schema {
it.packages = listOf("com.example")
it.jvmArguments = listOf("-Xmx2g", "-XX:+UseG1GC")
}

// extension configuration is applied to the task in an afterEvaluate hook
(project as ProjectInternal).evaluate()

val task = project.tasks.getByName(GENERATE_SDL_TASK_NAME) as GraphQLGenerateSDLTask
assertEquals(listOf("-Xmx2g", "-XX:+UseG1GC"), task.jvmArguments.get())
}

@Test
fun `jvmArguments set directly on the task are not overridden by the schema extension`() {
val project = ProjectBuilder.builder().build()
project.pluginManager.apply("java")
project.pluginManager.apply(GraphQLGradlePlugin::class.java)

val task = project.tasks.getByName(GENERATE_SDL_TASK_NAME) as GraphQLGenerateSDLTask
task.jvmArguments.set(listOf("-Xmx4g"))

val extension = project.extensions.getByType(GraphQLPluginExtension::class.java)
extension.schema {
it.packages = listOf("com.example")
it.jvmArguments = listOf("-Xmx2g")
}

// extension configuration is applied to the task in an afterEvaluate hook
(project as ProjectInternal).evaluate()

assertEquals(listOf("-Xmx4g"), task.jvmArguments.get())
}
}
5 changes: 5 additions & 0 deletions website/docs/plugins/gradle-plugin-tasks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ graphql {
schema {
// List of supported packages that can contain GraphQL schema type definitions
packages = listOf("com.example")
// Optional JVM arguments for the SDL generation worker, e.g. to raise the heap for large schemas
jvmArguments = listOf("-Xmx2g")
}
}
```
Expand Down Expand Up @@ -239,6 +241,8 @@ graphql {
}
schema {
packages = ["com.example"]
// Optional JVM arguments for the SDL generation worker, e.g. to raise the heap for large schemas
jvmArguments = ["-Xmx2g"]
}
}
```
Expand Down Expand Up @@ -352,6 +356,7 @@ GraphQL types.
| -------- | ---- | -------- | ----------- |
| `packages` | `List<String>` | yes | List of supported packages that can be scanned to generate SDL. |
| `schemaFile` | File | | Target GraphQL schema file to be generated.<br/>**Default value is:** `${project.buildDir}/schema.graphql` |
| `jvmArguments` | `List<String>` | | JVM arguments passed to the process-isolated worker that generates the SDL, e.g. `listOf("-Xmx2g")`. Useful for raising the heap when generating large schemas that would otherwise fail with an `OutOfMemoryError`.<br/>**Default value is:** empty list |

By default, this task will attempt to generate the schema using `NoopSchemaGeneratorHooks`. If you need to customize your
schema generation process, you will need to provide your custom instance of `SchemaGeneratorHooksProvider` service provider.
Expand Down
66 changes: 66 additions & 0 deletions website/docs/plugins/gradle-plugin-usage-sdl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,72 @@ This task does not automatically configure itself to be part of your build lifec
invoke it OR configure it as a dependency of some other task.
:::

## Configuring the SDL Generation Heap

SDL generation runs in a process-isolated worker JVM that uses the Gradle default heap. Large schemas can exhaust that
heap and fail with an `OutOfMemoryError`. You can raise the heap (or pass any other JVM arguments) to the worker through
the optional `jvmArguments` property.

<Tabs
defaultValue="kotlin"
values={[
{ label: 'Kotlin', value: 'kotlin' },
{ label: 'Groovy', value: 'groovy' }
]
}>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.graphql

graphql {
schema {
packages = listOf("com.example")
jvmArguments = listOf("-Xmx2g")
}
}
```

Above configuration is equivalent to the following task definition

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateSDLTask

val graphqlGenerateSDL by tasks.getting(GraphQLGenerateSDLTask::class) {
packages.set(listOf("com.example"))
jvmArguments.set(listOf("-Xmx2g"))
}
```

</TabItem>
<TabItem value="groovy">

```groovy
// build.gradle
graphql {
schema {
packages = ["com.example"]
jvmArguments = ["-Xmx2g"]
}
}
```

Above configuration is equivalent to the following task definition

```groovy
//build.gradle
graphqlGenerateSDL {
packages = ["com.example"]
jvmArguments = ["-Xmx2g"]
}
```

</TabItem>
</Tabs>

## Using Custom Hooks Provider

Plugin will default to use `NoopSchemaGeneratorHooks` to generate target GraphQL schema. If your project uses custom hooks
Expand Down
Loading