README.md 12.7 KB
Newer Older
1 2
# GraphQL Codegen Gradle plugin #

3
![Build](https://github.com/kobylynskyi/graphql-java-codegen/workflows/Build/badge.svg)
B
Bogdan Kobylynskyi 已提交
4
[![Gradle Plugins](https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/io/github/kobylynskyi/graphql-java-codegen-gradle-plugin/maven-metadata.xml.svg?label=gradle)](https://plugins.gradle.org/plugin/io.github.kobylynskyi.graphql.codegen)
5 6 7 8 9 10 11 12 13
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

This document describes the gradle plugin for graphql-java-codegen.

### Description

This Gradle plugin is able to generate the following classes based on your GraphQL schema:
* Interfaces for GraphQL queries, mutations and subscriptions
* Interfaces for GraphQL unions
14 15 16 17 18
* POJO classes for GraphQL types/inputs
* Enum classes for GraphQL enums
* Interface Resolvers for GraphQL type fields
* Client Request classes for GraphQL queries, mutations and subscriptions

19 20 21 22 23

### Plugin Setup

```groovy
plugins {
24
  id "io.github.kobylynskyi.graphql.codegen" version "1.7.3"
25 26 27 28 29 30 31 32 33 34 35 36 37
}
```

Using [legacy plugin application](https://docs.gradle.org/current/userguide/plugins.html#sec:old_plugin_application):

```groovy
buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
38
    classpath "io.github.kobylynskyi.graphql.codegen:graphql-codegen-gradle-plugin:1.7.3"
39 40 41 42 43 44
  }
}

apply plugin: "io.github.kobylynskyi.graphql.codegen"
```

45 46
### Plugin Options

47 48 49 50
| Option                                          | Data Type          | Default value                                 | Description |
| :---------------------------------------------: | :----------------: | :-------------------------------------------: | ----------- |
| `graphqlSchemaPaths`                            | List(String)       | (falls back to `graphqlSchemas`)              | GraphQL schema locations. You can supply multiple paths to GraphQL schemas. To include many schemas from a folder hierarchy, use the `graphqlSchemas` block instead. |
| `graphqlSchemas`                                | *See table below*  | All `.graphqls`/`.graphql` files in resources | Block to define the input GraphQL schemas, when exact paths are too cumbersome. See table below for a list of options. |
51
| `outputDir`                                     | File               | None                                          | The output target directory into which code will be generated. |
52 53
| `jsonConfigurationFile`                         | String             | Empty                                         | Path to an external mapping configuration. |
| `packageName`                                   | String             | Empty                                         | Java package for generated classes. |
54
| `apiPackageName`                                | String             | Empty                                         | Java package for generated api classes (Query, Mutation, Subscription). |
55
| `modelPackageName`                              | String             | Empty                                         | Java package for generated model classes (type, input, interface, enum, union). |
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| `generateBuilder`                               | Boolean            | True                                          | Specifies whether generated model classes should have builder. |
| `generateApis`                                  | Boolean            | True                                          | Specifies whether api classes should be generated as well as model classes. |
| `generateAsyncApi`                              | Boolean            | False                                         | If true, then wrap type into `java.util.concurrent.CompletableFuture` or `subscriptionReturnType` |
| `generateDataFetchingEnvironmentArgumentInApis` | Boolean            | False                                         | If true, then `graphql.schema.DataFetchingEnvironment env` will be added as a last argument to all methods of root type resolvers and field resolvers. |
| `generateEqualsAndHashCode`                     | Boolean            | False                                         | Specifies whether generated model classes should have equals and hashCode methods defined. |
| `generateToString`                              | Boolean            | False                                         | Specifies whether generated model classes should have toString method defined. |
| `modelNamePrefix`                               | String             | Empty                                         | Sets the prefix for GraphQL model classes (type, input, interface, enum, union). |
| `modelNameSuffix`                               | String             | Empty                                         | Sets the suffix for GraphQL model classes (type, input, interface, enum, union). |
| `modelValidationAnnotation`                     | String             | @javax.validation.<br>constraints.NotNull     | Annotation for mandatory (NonNull) fields. Can be null/empty. |
| `customTypesMapping`                            | Map(String,String) | Empty                                         | Can be used to supply custom mappings for scalars. <br/> Supports:<br/> * Map of (GraphqlObjectName.fieldName) to (JavaType) <br/> * Map of (GraphqlType) to (JavaType) |
| `customAnnotationsMapping`                      | Map(String,String) | Empty                                         | Can be used to supply custom annotations (serializers) for scalars. <br/> Supports:<br/> * Map of (GraphqlObjectName.fieldName) to (JavaAnnotation) <br/> * Map of (GraphqlType) to (JavaAnnotation) |
| `fieldsWithResolvers`                           | Set(String)        | Empty                                         | Fields that require Resolvers should be defined here in format: `TypeName.fieldName` or `TypeName`. |
| `fieldsWithoutResolvers`                        | Set(String)        | Empty                                         | Fields that DO NOT require Resolvers should be defined here in format: `TypeName.fieldName` or `TypeName`. Can be used in conjunction with `generateExtensionFieldsResolvers` option. |
| `generateParameterizedFieldsResolvers`          | Boolean            | True                                          | If true, then generate separate `Resolver` interface for parametrized fields. If false, then add field to the type definition and ignore field parameters. |
| `generateExtensionFieldsResolvers`              | Boolean            | False                                         | Specifies whether all fields in extensions (<code>extend type</code> and <code>extend interface</code>) should be present in Resolver interface instead of the type class itself. |
| `subscriptionReturnType`                        | String             | Empty                                         | Return type for subscription methods. For example: `org.reactivestreams.Publisher`, `io.reactivex.Observable`, etc. |
| `generateRequests`                              | Boolean            | False                                         | Specifies whether client-side classes should be generated for each query, mutation and subscription. This includes: `Request` class (contains input data) and `ResponseProjection` class (contains response fields). |
| `requestSuffix`                                 | String             | Request                                       | Sets the suffix for `Request` classes. |
| `responseProjectionSuffix`                      | String             | ResponseProjection                            | Sets the suffix for `ResponseProjection` classes. |
75 76 77 78 79 80 81 82 83


When exact paths to GraphQL schemas are too cumbersome to provide in the `graphqlSchemaPaths`, use the `graphqlSchemas { ... }` block.
The parameters inside that block are the following:

| Key inside `graphqlSchemas` | Data Type    | Default value      | Description |
| --------------------------- | ------------ | ------------------ | ----------- |
| `rootDir`                   | String       | Main resources dir | The root directory from which to start searching for schema files. |
| `recursive`                 | Boolean      | `true`             | Whether to recursively look into sub directories. |
84
| `includePattern`            | String       | `.*\.graphqls?`    | A Java regex that file names must match to be included. It should be a regex as defined by the [Pattern](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) JDK class. It will be used to match only the file name without path. |
85 86 87 88 89
| `excludedFiles`             | Set<String>  | (empty set)        | A set of files to exclude, even if they match the include pattern. These paths should be either absolute or relative to the provided `rootDir`. |



### Sample Plugin Configuration
90 91 92 93 94 95 96 97

#### build.gradle:

```groovy
graphqlCodegen {
    graphqlSchemaPaths = [
        "$projectDir/src/main/resources/schema.graphqls".toString()
    ]
98
    outputDir = new File("$buildDir/generated")
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    packageName = "com.example.graphql.model"
    customTypesMapping = [
        DateTime: "org.joda.time.DateTime",
        Price.amount: "java.math.BigDecimal"
    ]
    customAnnotationsMapping = [
        DateTime: "com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = com.example.json.EpochMillisScalarDeserializer.class"
    ]
    modelNameSuffix = "TO"
}

// Automatically generate GraphQL code on project build:
compileJava.dependsOn 'graphqlCodegen'

// Add generated sources to your project source sets:
sourceSets.main.java.srcDir "$buildDir/generated"
```

117 118
You can also refer to build.gradle files in example projects: [example-client/build.gradle](example-client/build.gradle), [example-server/build.gradle](example-server/build.gradle)

119 120 121 122 123
#### build.gradle.kts:

```groovy
tasks.named<GraphqlCodegenGradleTask>("graphqlCodegen") {
    graphqlSchemaPaths = listOf("$projectDir/src/main/resources/graphql/schema.graphqls".toString())
124
    outputDir = new File("$buildDir/generated")
125 126 127 128 129 130 131
    packageName = "com.example.graphql.model"
    customTypesMapping = mutableMapOf(Pair("EpochMillis", "java.time.LocalDateTime"))
    customAnnotationsMapping = mutableMapOf(Pair("EpochMillis", "com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = com.example.json.EpochMillisScalarDeserializer.class"))
}

// Automatically generate GraphQL code on project build:
sourceSets {
132
    getByName("main").java.srcDirs("$buildDir/generated")
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
}

// Add generated sources to your project source sets:
val check: DefaultTask by tasks
val graphqlCodegen: DefaultTask by tasks
check.dependsOn(graphqlCodegen)    
```


#### External mapping configuration

Provide a path to external file via property `jsonConfigurationFile`
Sample content of the file:

```json
{
  "generateApis": true,
  "packageName": "com.kobylynskyi.graphql.testconfigjson",
  "customTypesMapping": {
    "Price.amount": "java.math.BigDecimal"
  }
}
```

157 158 159 160 161 162 163 164 165 166 167 168 169

### Examples

* GraphQL **server** code generation: [example-server](example-server)
  * [Plugin configuration in build.gradle](example-server/build.gradle)
  * [GraphQL Resolver classes that implement generated interfaces](example-server/src/main/java/io/github/kobylynskyi/product/graphql/resolvers)
* GraphQL **client** code generation: [example-client](example-client)
  * [Plugin configuration in build.gradle](example-client/build.gradle)
  * [Building GraphQL request and parsing response using Spring RestTemplate](example-client/src/main/java/io/github/kobylynskyi/order/external/ProductServiceGraphQLClient.java)
  * [Building GraphQL request and parsing response using RestAssured](example-client/src/test/java/io/github/kobylynskyi/order/service/CreateProductIntegrationTest.java)


### Different configurations for graphql schemas
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

If you want to have different configuration for different `.graphqls` files (e.g.: different javaPackage, outputDir, etc.), then you will need to create separate gradle tasks for each set of schemas. E.g.:

```groovy
task graphqlCodegenService1(type: GraphqlCodegenGradleTask) {
    graphqlSchemaPaths = ["$projectDir/src/main/resources/schema1.graphqls".toString()]
    outputDir = new File("$buildDir/generated/example1")
}

task graphqlCodegenService2(type: GraphqlCodegenGradleTask) {
    graphqlSchemaPaths = ["$projectDir/src/main/resources/schema2.graphqls".toString()]
    outputDir = new File("$buildDir/generated/example2")
}
```

Later on you can call each task separately or together:

187 188 189
* `gradle clean graphqlCodegenService1 build`
* `gradle clean graphqlCodegenService2 build`
* `gradle clean graphqlCodegenService1 graphqlCodegenService2 build`
190 191 192 193


### Convert generated Java classes to Kotlin classes

194 195
1. Navigate in IntelliJ IDEA to the `./build/generated/graphql/` folder and press `Cmd+Alt+Shift+K`
2. Access generated classes as normal Kotlin classes.
196 197 198 199 200 201


### Inspired by

[swagger-codegen](https://github.com/swagger-api/swagger-codegen)