Skip to content

Commit 3facc66

Browse files
authored
[plugins] new generate client Gradle task and Maven mojo (#688)
Introduces new functionality to generate GraphQL Kotlin client based on the specified queries. NOTE: This is a final PR in a series to break down #595 into smaller more manageable pieces
1 parent 609405e commit 3facc66

File tree

28 files changed

+1754
-75
lines changed

28 files changed

+1754
-75
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ GraphQL Kotlin is a collection of libraries built on top of [graphql-java](https
99

1010
## 📦 Modules
1111

12-
* [graphql-kotlin-schema-generator](/graphql-kotlin-schema-generator) - Code only GraphQL schema generation for Kotlin
12+
* [graphql-kotlin-client](/graphql-kotlin-client) - Lightweight GraphQL Kotlin HTTP client
1313
* [graphql-kotlin-federation](/graphql-kotlin-federation) - Schema generator extension to build federated GraphQL schemas
14+
* [graphql-kotlin-schema-generator](/graphql-kotlin-schema-generator) - Code only GraphQL schema generation for Kotlin
1415
* [graphql-kotlin-spring-server](/graphql-kotlin-spring-server) - Spring Boot auto-configuration library to create a GraphQL web app
1516
* [examples](/examples) - Example apps that use graphql-kotlin libraries to test and demonstrate usages
17+
* [plugins](/plugins) - GraphQL Kotlin Gradle and Maven plugins
1618

1719
## ⌨️ Usage
1820

docs/getting-started.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ GraphQL Kotlin is a collection of libraries built on top of [graphql-java](https
77

88
## Modules
99

10-
* [graphql-kotlin-schema-generator](https://github.com/ExpediaGroup/graphql-kotlin/tree/master/graphql-kotlin-schema-generator) ([Javadoc](https://www.javadoc.io/doc/com.expediagroup/graphql-kotlin-schema-generator))
10+
* [graphql-kotlin-client](https://github.com/ExpediaGroup/graphql-kotlin/tree/master/graphql-kotlin-client) ([Javadoc](https://www.javadoc.io/doc/com.expediagroup/graphql-kotlin-client))
11+
— Lightweight GraphQL Kotlin HTTP client
12+
* [graphql-kotlin-schema-generator](https://github.com/ExpediaGroup/graphql-kotlin/tree/master/graphql-kotlin-schema-generator) ([Javadoc](https://www.javadoc.io/doc/com.expediagroup/graphql-kotlin-schema-generator))
1113
— Code only GraphQL schema generation for Kotlin
1214
* [graphql-kotlin-federation](https://github.com/ExpediaGroup/graphql-kotlin/tree/master/graphql-kotlin-federation) ([Javadoc](https://www.javadoc.io/doc/com.expediagroup/graphql-kotlin-federation))
1315
— Schema generator extension to build federated GraphQL schemas
1416
* [graphql-kotlin-spring-server](https://github.com/ExpediaGroup/graphql-kotlin/tree/master/graphql-kotlin-spring-server) ([Javadoc](https://www.javadoc.io/doc/com.expediagroup/graphql-kotlin-spring-server))
1517
— Spring Boot auto-configuration library to create GraphQL web app
1618
* [examples](https://github.com/ExpediaGroup/graphql-kotlin/tree/master/examples)
1719
— Example apps that use graphql-kotlin libraries to test and demonstrate usages
20+
* [plugins](https://github.com/ExpediaGroup/graphql-kotlin/tree/master/plugins)
21+
— GraphQL Kotlin Gradle and Maven plugins
1822

1923
If you encounter any problems using this library please open up a new
2024
[Issue](https://github.com/ExpediaGroup/graphql-kotlin/issues)

docs/plugins/gradle-plugin.md

Lines changed: 153 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,32 @@ plugins {
1717
}
1818
```
1919

20+
## Extension
21+
2022
GraphQL Kotlin Gradle Plugin uses an extension on the project named `graphql` of type
21-
[GraphQLPluginExtension`](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLPluginExtension.kt).
22-
This extension can be used to configure global options instead of explicitly configuring individual tasks.
23+
[GraphQLPluginExtension](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLPluginExtension.kt).
24+
This extension can be used to configure global options instead of explicitly configuring individual tasks. Once extension
25+
is configured, it will automatically download SDL/run introspection to generate GraphQL schema and subsequently generate
26+
all GraphQL clients. GraphQL Extension should be used by default, except for cases where you need to only run individual
27+
tasks.
28+
29+
```kotlin
30+
// build.gradle.kts
31+
import com.expediagroup.graphql.plugin.gradle.graphql
32+
33+
graphql {
34+
// GraphQL server endpoint that will be used to for running introspection queries. Alternatively you can download schema directly from `sdlEndpoint`.
35+
endpoint = "http://localhost:8080/graphql"
36+
// GraphQL server SDL endpoint that will be used to download schema. Alternatively you can run introspection query against `endpoint`.
37+
sdlEndpoint = "http://localhost:8080/sdl"
38+
// Target package name to be used for generated classes.
39+
packageName = "com.example.generated"
40+
// Boolean flag indicating whether or not selection of deprecated fields is allowed.
41+
allowDeprecatedFields = false
42+
// Custom GraphQL scalar to converter mapping containing information about corresponding Java type and converter that should be used to serialize/deserialize values.
43+
scalarConverters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.example.UUIDScalarConverter"))
44+
}
45+
```
2346

2447
## Tasks
2548

@@ -33,13 +56,45 @@ schema file as `schema.graphql` under build directory. In general, this task pro
3356
and could be used as an alternative to `graphqlIntrospectSchema` to generate input for the subsequent
3457
`graphqlGenerateClient` task.
3558

59+
**Properties**
60+
61+
| Property | Type | Required | Description |
62+
| -------- | ---- | -------- | ----------- |
63+
| `endpoint` | String | yes | Target GraphQL server SDL endpoint that will be used to download schema.<br/>**Command line property is**: `endpoint`. |
64+
65+
### graphqlGenerateClient
66+
67+
Task that generates GraphQL Kotlin client and corresponding data classes based on the provided GraphQL queries that are
68+
evaluated against target Graphql schema. Individual clients with their specific data models are generated for each query
69+
file and are placed under specified `packageName`.
70+
71+
**Properties**
72+
73+
| Property | Type | Required | Description |
74+
| -------- | ---- | -------- | ----------- |
75+
| `allowDeprecatedFields` | Boolean | | Boolean flag indicating whether selection of deprecated fields is allowed or not.<br/>**Default value is:** `false`.<br/>**Command line property is**: `allowDeprecatedFields`. |
76+
| `packageName` | String | yes | Target package name for generated code.<br/>**Command line property is**: `packageName`. |
77+
| `queryFiles` | FileCollection | | List of query files to be processed. Instead of a list of files to be processed you can specify `queryFileDirectory` directory instead. If this property is specified it will take precedence over the corresponding directory property. |
78+
| `queryFileDirectory` | String | | Directory file containing GraphQL queries. Instead of specifying a directory you can also specify list of query file by using `queryFiles` property instead.<br/>**Default value is:** `src/main/resources`.<br/>**Command line property is**: `queryFileDirectory`. |
79+
| `scalarConverters` | Map<String, ScalarConverter> | | Custom GraphQL scalar to converter mapping containing information about corresponding Java type and converter that should be used to serialize/deserialize values. |
80+
| `schemaFile` | File | `schemaFileName` or `schemaFile` has to be provided | GraphQL schema file that will be used to generate client code. |
81+
| `schemaFileName` | String | `schemaFileName` or `schemaFile` has to be provided | Path to GraphQL schema file that will be used to generate client code.<br/>**Command line property is**: `schemaFileName`. |
82+
3683
### graphqlIntrospectSchema
3784

38-
Executes GraphQL introspection query against specified endpoint and saves the underlying schema file as
85+
Task that executes GraphQL introspection query against specified `endpoint` and saves the underlying schema file as
3986
`schema.graphql` under build directory. In general, this task provides limited functionality by itself and instead
4087
should be used to generate input for the subsequent `graphqlGenerateClient` task.
4188

42-
## Downloading Schema SDL
89+
**Properties**
90+
91+
| Property | Type | Required | Description |
92+
| -------- | ---- | -------- | ----------- |
93+
| `endpoint` | String | yes | Target GraphQL server endpoint that will be used to execute introspection queries.<br/>**Command line property is**: `endpoint`. |
94+
95+
## Examples
96+
97+
### Downloading Schema SDL
4398

4499
GraphQL endpoints are often public and as such many servers might disable introspection queries in production environment.
45100
Since GraphQL schema is needed to generate type safe clients, as alternative GraphQL servers might expose private
@@ -51,65 +106,136 @@ be executed directly from the command line by explicitly passing `endpoint` para
51106
$ gradle graphqlDownloadSDL --endpoint="http://localhost:8080/sdl"
52107
```
53108

54-
Task can also be configured in your Gradle build file using global extension
109+
Task can also be explicitly configured in your Gradle build file
55110

56111
```kotlin
57112
// build.gradle.kts
58-
import com.expediagroup.graphql.plugin.gradle.graphql
113+
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTask
59114

60-
graphql {
61-
sdlEndpoint = "http://localhost:8080/graphql"
115+
val graphqlIntrospectSchema by tasks.getting(GraphQLDownloadSDLTask::class) {
116+
graphqlDownloadSDL.set("http://localhost:8080/sdl")
62117
}
63118
```
64119

65-
Or by explicitly configuring the task
120+
NOTE: This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly
121+
invoke it OR configure it as a dependency of some other task.
122+
123+
### Introspecting Schema
124+
125+
Introspection task requires target GraphQL server `endpoint` to be specified. Task can be executed directly from the
126+
command line by explicitly passing endpoint parameter
127+
128+
```shell script
129+
$ gradle graphqlIntrospectSchema --endpoint="http://localhost:8080/graphql"
130+
```
131+
132+
Task can also be explicitly configured in your Gradle build file
66133

67134
```kotlin
68135
// build.gradle.kts
69-
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTask
136+
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
70137

71-
val graphqlIntrospectSchema by tasks.getting(GraphQLDownloadSDLTask::class) {
72-
graphqlDownloadSDL.set("http://localhost:8080/graphql")
138+
val graphqlIntrospectSchema by tasks.getting(GraphQLIntrospectSchemaTask::class) {
139+
endpoint.set("http://localhost:8080/graphql")
73140
}
74141
```
75142

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

79-
## Introspecting Schema
146+
### Generating Client
80147

81-
Introspection task requires target GraphQL server `endpoint` to be specified. Task can be executed directly from the
82-
command line by explicitly passing endpoint parameter
148+
GraphQL client code is generated based on the provided queries that will be executed against target GraphQL `schemaFile`.
149+
Separate class is generated for each provided GraphQL query and are saved under specified `packageName`. When using default
150+
configuration and storing GraphQL queries under `src/main/resources` directories, task can be executed directly from the
151+
command line by explicitly providing required properties.
83152

84153
```shell script
85-
$ gradle graphqlIntrospectSchema --endpoint="http://localhost:8080/graphql"
154+
$ gradle graphqlGenerateClient --schemaFileName"mySchema.graphql" --packageName="com.example.generated"
86155
```
87156

88-
Task can also be configured in your Gradle build file using global extension
157+
Task can also be explicitly configured in your Gradle build file
89158

90159
```kotlin
91160
// build.gradle.kts
92-
import com.expediagroup.graphql.plugin.gradle.graphql
161+
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
93162

94-
graphql {
95-
endpoint = "http://localhost:8080/graphql"
163+
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
164+
packageName.set("com.example.generated")
165+
schemaFileName.set("mySchema.graphql")
166+
}
167+
```
168+
169+
This will process all GraphQL queries located under `src/main/resources` and generate corresponding GraphQL Kotlin clients.
170+
Generated classes will be automatically added to the project compile sources.
171+
172+
### Generating client with Custom Scalars
173+
174+
By default, all custom GraphQL scalars will be serialized as Strings. You can override this default behavior by specifying
175+
custom [scalar converter](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/graphql-kotlin-client/src/main/kotlin/com/expediagroup/graphql/client/converter/ScalarConverter.kt).
176+
177+
For example given following custom scalar in our GraphQL schema
178+
179+
```graphql
180+
scalar UUID
181+
```
182+
183+
We can create a custom converter to automatically convert this custom scalar to `java.util.UUID`
184+
185+
```kotlin
186+
package com.example
187+
188+
import com.expediagroup.graphql.client.converter.ScalarConverter
189+
import java.util.UUID
190+
191+
class UUIDScalarConverter : ScalarConverter<UUID> {
192+
override fun toScalar(rawValue: String): UUID = UUID.fromString(rawValue)
193+
override fun toJson(value: UUID): String = value.toString()
96194
}
97195
```
98196

99-
Or by explicitly configuring the task
197+
Afterwards we need to configure our plugin to use this custom converter
100198

101199
```kotlin
102200
// build.gradle.kts
103201
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
104202

105-
val graphqlIntrospectSchema by tasks.getting(GraphQLIntrospectSchemaTask::class) {
106-
endpoint.set("http://localhost:8080/graphql")
203+
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
204+
packageName.set("com.example.generated")
205+
schemaFileName.set("mySchema.graphql")
206+
scalarConverters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.example.UUIDScalarConverter"))
107207
}
108208
```
109209

110-
NOTE: This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly
111-
invoke it OR configure it as a dependency of some other task.
210+
### Complete Configuration Example
211+
212+
Following is the minimal configuration that runs introspection query against a target GraphQL server and generates a
213+
corresponding schema. This generated schema is subsequently used to generate GraphQL client code based on the queries
214+
provided under `src/main/resources` directory.
215+
216+
```kotlin
217+
// build.gradle.kts
218+
import com.expediagroup.graphql.plugin.gradle.graphql
219+
220+
graphql {
221+
endpoint = "http://localhost:8080/graphql"
222+
packageName = "com.example.generated"
223+
}
224+
```
225+
226+
Above configuration is equivalent to the following
112227

113-
## Complete Example
228+
```kotlin
229+
// build.gradle.kts
230+
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
231+
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLIntrospectSchemaTask
114232

115-
// TODO complete once all tasks are merged
233+
val graphqlIntrospectSchema by tasks.getting(GraphQLIntrospectSchemaTask::class) {
234+
endpoint.set("http://localhost:8080/graphql")
235+
}
236+
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
237+
packageName.set("com.example.generated")
238+
schemaFile.set(graphqlIntrospectSchema.outputFile)
239+
dependsOn("graphqlIntrospectSchema")
240+
}
241+
```

0 commit comments

Comments
 (0)