Skip to content

Commit 656b5e0

Browse files
authored
[plugin] fix generate client MOJO converter parameter (#713)
In order for Maven to recognize complex objects all their fields need to be annoated with `@Parameter` annotation. Additonal changes - add debug messages for logging generate client task/mojo configuration - update integration tests to validate custom scalar logic - update Gradle task `converters` parameter to match Maven MOJO parameter
1 parent 99847f3 commit 656b5e0

File tree

9 files changed

+109
-23
lines changed

9 files changed

+109
-23
lines changed

docs/plugins/gradle-plugin.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ graphql {
4040
// Boolean flag indicating whether or not selection of deprecated fields is allowed.
4141
allowDeprecatedFields = false
4242
// 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"))
43+
converters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.example.UUIDScalarConverter"))
4444
}
4545
```
4646

@@ -73,10 +73,10 @@ file and are placed under specified `packageName`.
7373
| Property | Type | Required | Description |
7474
| -------- | ---- | -------- | ----------- |
7575
| `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+
| `converters` | 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. |
7677
| `packageName` | String | yes | Target package name for generated code.<br/>**Command line property is**: `packageName`. |
7778
| `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. |
7879
| `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. |
8080
| `schemaFile` | File | `schemaFileName` or `schemaFile` has to be provided | GraphQL schema file that will be used to generate client code. |
8181
| `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`. |
8282

@@ -203,7 +203,7 @@ import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
203203
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
204204
packageName.set("com.example.generated")
205205
schemaFileName.set("mySchema.graphql")
206-
scalarConverters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.example.UUIDScalarConverter"))
206+
converters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.example.UUIDScalarConverter"))
207207
}
208208
```
209209

plugins/graphql-kotlin-gradle-plugin/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ file and are placed under specified `packageName`.
5454
| Property | Type | Required | Description |
5555
| -------- | ---- | -------- | ----------- |
5656
| `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`. |
57+
| `converters` | 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. |
5758
| `packageName` | String | yes | Target package name for generated code.<br/>**Command line property is**: `packageName`. |
5859
| `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. |
5960
| `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`. |
60-
| `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. |
6161
| `schemaFile` | File | `schemaFileName` or `schemaFile` has to be provided | GraphQL schema file that will be used to generate client code. |
6262
| `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`. |
6363

plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLGradlePlugin.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class GraphQLGradlePlugin : Plugin<Project> {
5959
val generateClientTask = project.tasks.named(GENERATE_CLIENT_TASK_NAME, GraphQLGenerateClientTask::class.java).get()
6060
generateClientTask.packageName.convention(project.provider { extension.packageName })
6161
generateClientTask.allowDeprecatedFields.convention(project.provider { extension.allowDeprecatedFields })
62-
generateClientTask.scalarConverters.convention(extension.scalarConverters)
62+
generateClientTask.converters.convention(extension.scalarConverters)
6363
generateClientTask.queryFiles.setFrom(extension.queryFiles.from)
6464

6565
if (extension.endpoint != null) {

plugins/graphql-kotlin-gradle-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/gradle/tasks/GraphQLGenerateClientTask.kt

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ open class GraphQLGenerateClientTask : DefaultTask() {
8989
* serialize/deserialize values.
9090
*
9191
* ```kotlin
92-
* scalarConverters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.expediagroup.graphql.examples.client.UUIDScalarConverter"))
92+
* converters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.expediagroup.graphql.examples.client.UUIDScalarConverter"))
9393
* ```
9494
*/
9595
@Input
9696
@Optional
97-
val scalarConverters: MapProperty<String, ScalarConverterMapping> = project.objects.mapProperty(String::class.java, ScalarConverterMapping::class.java)
97+
val converters: MapProperty<String, ScalarConverterMapping> = project.objects.mapProperty(String::class.java, ScalarConverterMapping::class.java)
9898

9999
/**
100100
* Directory containing GraphQL queries, defaults to `src/main/resources`.
@@ -123,12 +123,14 @@ open class GraphQLGenerateClientTask : DefaultTask() {
123123

124124
queryFileDirectory.convention("${project.projectDir}/src/main/resources")
125125
allowDeprecatedFields.convention(false)
126-
scalarConverters.convention(emptyMap())
126+
converters.convention(emptyMap())
127127
}
128128

129129
@Suppress("EXPERIMENTAL_API_USAGE")
130130
@TaskAction
131131
fun generateGraphQLClientAction() {
132+
logger.debug("generating GraphQL client")
133+
132134
val graphQLSchema = when {
133135
schemaFile.isPresent -> schemaFile.get().asFile
134136
schemaFileName.isPresent -> File(schemaFileName.get())
@@ -155,12 +157,34 @@ open class GraphQLGenerateClientTask : DefaultTask() {
155157
if (!targetDirectory.isDirectory && !targetDirectory.mkdirs()) {
156158
throw RuntimeException("failed to generate generated source directory")
157159
}
160+
161+
logConfiguration(graphQLSchema, targetQueryFiles)
158162
val config = GraphQLClientGeneratorConfig(
159163
packageName = targetPackage,
160164
allowDeprecated = allowDeprecatedFields.get(),
161-
scalarTypeToConverterMapping = scalarConverters.get())
165+
scalarTypeToConverterMapping = converters.get())
162166
generateClient(config, graphQLSchema, targetQueryFiles).forEach {
163167
it.writeTo(targetDirectory)
164168
}
169+
logger.debug("successfully generated GraphQL HTTP client")
170+
}
171+
172+
private fun logConfiguration(schema: File, queryFiles: List<File>) {
173+
logger.debug("GraphQL Client generator configuration:")
174+
logger.debug(" schema file = ${schema.path}")
175+
logger.debug(" queries")
176+
queryFiles.forEach {
177+
logger.debug(" - ${it.name}")
178+
}
179+
logger.debug(" packageName = $packageName")
180+
logger.debug(" allowDeprecatedFields = $allowDeprecatedFields")
181+
logger.debug(" converters")
182+
converters.get().entries.forEach { (customScalar, converterInfo) ->
183+
logger.debug(" - custom scalar = $customScalar")
184+
logger.debug(" |- type = ${converterInfo.type}")
185+
logger.debug(" |- converter = ${converterInfo.converter}")
186+
}
187+
logger.debug("")
188+
logger.debug("-- end GraphQL Client generator configuration --")
165189
}
166190
}

plugins/graphql-kotlin-gradle-plugin/src/test/kotlin/com/expediagroup/graphql/plugin/gradle/GraphQLGradlePluginIT.kt

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class GraphQLGradlePluginIT {
136136
val kotlinVersion = System.getProperty("kotlinVersion") ?: "1.3.71"
137137
val buildFileContents = """
138138
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
139+
import com.expediagroup.graphql.plugin.generator.ScalarConverterMapping
139140
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
140141
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLIntrospectSchemaTask
141142
@@ -160,6 +161,7 @@ class GraphQLGradlePluginIT {
160161
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
161162
packageName.set("com.expediagroup.graphql.generated")
162163
schemaFile.set(graphqlIntrospectSchema.outputFile)
164+
converters.put("UUID", ScalarConverterMapping("java.util.UUID", "com.example.UUIDScalarConverter"))
163165
dependsOn("graphqlIntrospectSchema")
164166
}
165167
@@ -189,26 +191,40 @@ class GraphQLGradlePluginIT {
189191
package com.example
190192
191193
import com.expediagroup.graphql.client.GraphQLClient
194+
import com.expediagroup.graphql.client.converter.ScalarConverter
192195
import com.expediagroup.graphql.generated.JUnitQuery
193196
import kotlinx.coroutines.runBlocking
194197
import java.net.URL
198+
import java.util.UUID
195199
196200
fun main() {
197201
val client = GraphQLClient(URL("${wireMockServer.baseUrl()}/graphql"))
198202
val query = JUnitQuery(client)
199203
200204
val variables = JUnitQuery.Variables(JUnitQuery.SimpleArgumentInput(min = null, max = null, newName = "blah"))
201205
runBlocking {
202-
val result = query.execute(variables)
203-
val data = result.data
206+
val response = query.execute(variables = variables)
207+
val data = response.data
204208
assert(data != null)
209+
val scalarResult = data?.scalarQuery
210+
assert(scalarResult is JUnitQuery.ScalarWrapper)
211+
assert(scalarResult != null)
212+
assert(scalarResult?.count is Int)
213+
assert(scalarResult?.custom is JUnitQuery.UUID)
205214
assert(JUnitQuery.CustomEnum.ONE == data?.enumQuery)
206-
assert(data?.interfaceQuery is JUnitQuery.SecondInterfaceImplementation)
207-
assert(data?.unionQuery is JUnitQuery.BasicObject)
208-
assert(result.errors == null)
209-
assert(result.extensions == null)
215+
val interfaceResult = data?.interfaceQuery
216+
assert(interfaceResult is JUnitQuery.SecondInterfaceImplementation)
217+
val unionResult = data?.unionQuery
218+
assert(unionResult is JUnitQuery.BasicObject)
219+
assert(response.errors == null)
220+
assert(response.extensions == null)
210221
}
211222
}
223+
224+
class UUIDScalarConverter : ScalarConverter<UUID> {
225+
override fun toScalar(rawValue: String): UUID = UUID.fromString(rawValue)
226+
override fun toJson(value: UUID): String = value.toString()
227+
}
212228
""".trimIndent())
213229

214230
val codeGenerationResult = GradleRunner.create()

plugins/graphql-kotlin-maven-plugin/src/integration/complete-setup/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@
9898
<configuration>
9999
<packageName>com.expediagroup.graphql.plugin.generated</packageName>
100100
<schemaFile>${project.build.directory}/schema.graphql</schemaFile>
101+
<converters>
102+
<!-- custom scalar UUID type -->
103+
<UUID>
104+
<!-- fully qualified Java class name of a custom scalar type -->
105+
<type>java.util.UUID</type>
106+
<!-- fully qualified Java class name of a custom com.expediagroup.graphql.client.converter.ScalarConverter
107+
used to convert to/from raw JSON and scalar type -->
108+
<converter>com.example.UUIDScalarConverter</converter>
109+
</UUID>
110+
</converters>
101111
</configuration>
102112
</execution>
103113
</executions>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.example
2+
3+
import com.expediagroup.graphql.client.converter.ScalarConverter
4+
import java.util.UUID
5+
6+
class UUIDScalarConverter : ScalarConverter<UUID> {
7+
override fun toScalar(rawValue: String): UUID = UUID.fromString(rawValue)
8+
override fun toJson(value: UUID): String = value.toString()
9+
}

plugins/graphql-kotlin-maven-plugin/src/integration/complete-setup/src/test/kotlin/com/expediagroup/graphql/plugin/maven/GraphQLMavenPluginTest.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ class GraphQLMavenPluginTest {
5757
assertTrue(response.errors == null)
5858
val data = response.data
5959
assertNotNull(data)
60+
val scalarResult = data?.scalarQuery
61+
assertTrue(scalarResult is ExampleQuery.ScalarWrapper)
62+
assertNotNull(scalarResult)
63+
assertTrue(scalarResult?.count is Int)
64+
assertTrue(scalarResult?.custom is ExampleQuery.UUID)
6065
assertEquals(ExampleQuery.CustomEnum.ONE, data?.enumQuery)
6166
val interfaceResult = data?.interfaceQuery
6267
assertTrue(interfaceResult is ExampleQuery.SecondInterfaceImplementation)

plugins/graphql-kotlin-maven-plugin/src/main/kotlin/com/expediagroup/graphql/plugin/maven/GenerateClientMojo.kt

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class GenerateClientMojo : AbstractMojo() {
7474
* ```
7575
*/
7676
@Parameter(name = "converters")
77-
private var converters: Map<String, ScalarConverter> = emptyMap()
77+
private var converters: Map<String, ScalarConverter> = mutableMapOf()
7878

7979
/**
8080
* Directory file containing GraphQL queries, defaults to `src/main/resources`. Instead of specifying a directory you can
@@ -107,9 +107,7 @@ class GenerateClientMojo : AbstractMojo() {
107107

108108
val targetQueryFiles: List<File> = when {
109109
::queryFiles.isInitialized -> queryFiles
110-
else -> queryFileDirectory
111-
.listFiles { file -> file.extension == "graphql" }
112-
?.toList() ?: throw RuntimeException("exception while looking up the query files")
110+
else -> queryFileDirectory.listFiles { file -> file.extension == "graphql" }?.toList() ?: throw RuntimeException("exception while looking up the query files")
113111
}
114112
if (targetQueryFiles.isEmpty()) {
115113
throw RuntimeException("no query files specified")
@@ -118,6 +116,8 @@ class GenerateClientMojo : AbstractMojo() {
118116
if (!outputDirectory.isDirectory && !outputDirectory.mkdirs()) {
119117
throw RuntimeException("failed to generate generated source directory")
120118
}
119+
120+
logConfiguration(targetQueryFiles)
121121
val config = GraphQLClientGeneratorConfig(
122122
packageName = packageName,
123123
allowDeprecated = allowDeprecatedFields,
@@ -130,6 +130,25 @@ class GenerateClientMojo : AbstractMojo() {
130130
project.addCompileSourceRoot(outputDirectory.path)
131131
log.debug("successfully generated GraphQL HTTP client")
132132
}
133+
134+
private fun logConfiguration(queryFiles: List<File>) {
135+
log.debug("GraphQL Client generator configuration:")
136+
log.debug(" schema file = ${schemaFile.path}")
137+
log.debug(" queries")
138+
queryFiles.forEach {
139+
log.debug(" - ${it.name}")
140+
}
141+
log.debug(" packageName = $packageName")
142+
log.debug(" allowDeprecatedFields = $allowDeprecatedFields")
143+
log.debug(" converters")
144+
converters.entries.forEach { (customScalar, converterInfo) ->
145+
log.debug(" - custom scalar = $customScalar")
146+
log.debug(" |- type = ${converterInfo.type}")
147+
log.debug(" |- converter = ${converterInfo.converter}")
148+
}
149+
log.debug("")
150+
log.debug("-- end GraphQL Client generator configuration --")
151+
}
133152
}
134153

135154
/**
@@ -140,9 +159,12 @@ class GenerateClientMojo : AbstractMojo() {
140159
*
141160
* @see [Guide to Configuring Plug-ins](https://maven.apache.org/guides/mini/guide-configuring-plugins.html#Mapping_Complex_Objects)
142161
*/
143-
data class ScalarConverter(
162+
class ScalarConverter {
144163
/** Fully qualified class name of a custom scalar type, e.g. java.util.UUID */
145-
val type: String,
164+
@Parameter
165+
lateinit var type: String
166+
146167
/** Fully qualified class name of a custom converter used to convert to/from raw JSON and [type] */
147-
val converter: String
148-
)
168+
@Parameter
169+
lateinit var converter: String
170+
}

0 commit comments

Comments
 (0)