Skip to content

Commit 5549474

Browse files
authored
Reintroduce legacy constructor on Query classes for backward compatability (#813)
* Reintroduce legacy constructor on Query classes for backward compatibility. * Add tests for legacy query constructor --------- Co-authored-by: pbakker <$(git --no-pager log --format=format:'%ae' -n 1)>
1 parent bb2d6e1 commit 5549474

File tree

2 files changed

+70
-11
lines changed

2 files changed

+70
-11
lines changed

graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/ClientApiGenerator.kt

+21-7
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ class ClientApiGenerator(
206206
.addModifiers(Modifier.PUBLIC)
207207
constructorBuilder.addStatement("super(\$S, queryName)", operation.lowercase())
208208

209+
val legacyConstructorBuilder =
210+
MethodSpec
211+
.constructorBuilder()
212+
.addModifiers(Modifier.PUBLIC)
213+
legacyConstructorBuilder.addStatement("super(\$S, queryName)", operation.lowercase())
214+
209215
it.inputValueDefinitions.forEach { inputValue ->
210216
val findReturnType = TypeUtils(getDatatypesPackageName(), config, document).findReturnType(inputValue.type)
211217

@@ -252,21 +258,24 @@ class ClientApiGenerator(
252258
builderClass.addMethod(referenceMethodBuilder.build())
253259

254260
constructorBuilder.addParameter(findReturnType, ReservedKeywordSanitizer.sanitize(inputValue.name))
261+
legacyConstructorBuilder.addParameter(findReturnType, ReservedKeywordSanitizer.sanitize(inputValue.name))
255262

256263
if (findReturnType.isPrimitive) {
257-
constructorBuilder.addCode(
264+
val code =
258265
"""
259266
|getInput().put("${inputValue.name}", ${ReservedKeywordSanitizer.sanitize(inputValue.name)});
260-
""".trimMargin(),
261-
)
267+
""".trimMargin()
268+
constructorBuilder.addCode(code)
269+
legacyConstructorBuilder.addCode(code)
262270
} else {
263-
constructorBuilder.addCode(
271+
val code =
264272
"""
265273
|if (${ReservedKeywordSanitizer.sanitize(inputValue.name)} != null || fieldsSet.contains("${inputValue.name}")) {
266274
| getInput().put("${inputValue.name}", ${ReservedKeywordSanitizer.sanitize(inputValue.name)});
267275
|}
268-
""".trimMargin(),
269-
)
276+
""".trimMargin()
277+
constructorBuilder.addCode(code)
278+
legacyConstructorBuilder.addCode(code)
270279
}
271280
}
272281

@@ -303,11 +312,16 @@ class ClientApiGenerator(
303312
.addMethod(nameMethodBuilder.build())
304313

305314
constructorBuilder.addParameter(String::class.java, "queryName")
315+
legacyConstructorBuilder.addParameter(String::class.java, "queryName")
306316

307-
if (it.inputValueDefinitions.size > 0) {
317+
if (it.inputValueDefinitions.isNotEmpty()) {
308318
constructorBuilder.addParameter(setOfStringType, "fieldsSet")
319+
legacyConstructorBuilder.addParameter(setOfStringType, "fieldsSet")
309320
constructorBuilder.addParameter(mapOfStringsType, "variableReferences")
310321
constructorBuilder.addParameter(listOfVariablesType, "variableDefinitions")
322+
323+
// We only need this backward compatible constructor if we added the new fields to the main constructor.
324+
javaType.addMethod(legacyConstructorBuilder.build())
311325
}
312326

313327
javaType.addMethod(constructorBuilder.build())

graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/CodeGenTest.kt

+49-4
Original file line numberDiff line numberDiff line change
@@ -5814,12 +5814,28 @@ It takes a title and such.
58145814

58155815
assertCompilesJava(result)
58165816
assertThat(result.javaQueryTypes).hasSize(1)
5817-
val parameters =
5817+
val constructors =
58185818
result.javaQueryTypes[0]
58195819
.typeSpec.methodSpecs
5820-
.filter { it.isConstructor && !it.parameters.isEmpty() }
5821-
.get(0)
5822-
.parameters
5820+
.filter { it.isConstructor }
5821+
assertThat(constructors).hasSize(3).withFailMessage {
5822+
"There should be a no-arg constructor, a legacy constructor without variable references, and one with variable references"
5823+
}
5824+
5825+
val noArg = constructors.find { it.parameters.isEmpty() }
5826+
assertThat(noArg).isNotNull.withFailMessage { "Missing no-arg constructor" }
5827+
5828+
val legacy = constructors.find { it.parameters.isNotEmpty() && it.parameters.none { p -> p.name == "variableReferences" } }
5829+
assertThat(legacy).isNotNull.withFailMessage { "Missing legacy constructor without variableReferences" }
5830+
5831+
val withVariableReferences =
5832+
constructors.find {
5833+
it.parameters.isNotEmpty() &&
5834+
it.parameters.any { p -> p.name == "variableReferences" }
5835+
}
5836+
assertThat(withVariableReferences).isNotNull.withFailMessage { "Missing constructor with variableReferences" }
5837+
5838+
val parameters = withVariableReferences!!.parameters
58235839
assertThat(parameters).extracting("name").contains("variableReferences", "variableDefinitions")
58245840
assertThat(
58255841
parameters
@@ -5855,6 +5871,35 @@ It takes a title and such.
58555871
)
58565872
}
58575873

5874+
@Test
5875+
fun `Generated queries should not contain conflicting constructors when no input arguments exist`() {
5876+
val schema =
5877+
"""
5878+
type Query {
5879+
findPeople: [String]
5880+
}
5881+
""".trimIndent()
5882+
5883+
val result =
5884+
CodeGen(
5885+
CodeGenConfig(
5886+
schemas = setOf(schema),
5887+
packageName = "com.netflix.test",
5888+
generateClientApi = true,
5889+
),
5890+
).generate()
5891+
5892+
assertCompilesJava(result)
5893+
assertThat(result.javaQueryTypes).hasSize(1)
5894+
val constructors =
5895+
result.javaQueryTypes[0]
5896+
.typeSpec.methodSpecs
5897+
.filter { it.isConstructor }
5898+
assertThat(
5899+
constructors,
5900+
).hasSize(2).withFailMessage { "There should be a no-arg constructor and a constructor without variable references" }
5901+
}
5902+
58585903
@Test
58595904
fun generateInputTrackFieldSet() {
58605905
val schema =

0 commit comments

Comments
 (0)