From d7646cd488f047a65d7bec6ee956303eb5c0aca3 Mon Sep 17 00:00:00 2001
From: Kavitha Srinivasan <41588701+srinivasankavitha@users.noreply.github.com>
Date: Tue, 23 Apr 2024 09:15:03 -0700
Subject: [PATCH] Use concrete types for JsonSubType annotations on interfaces
 if available. (#683)

---
 .../generators/java/InterfaceGenerator.kt     |  6 ++--
 .../graphql/dgs/codegen/CodeGenTest.kt        | 36 +++++++++++++++++++
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt
index a02c3d3ee..e0590d17e 100644
--- a/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt
+++ b/graphql-dgs-codegen-core/src/main/kotlin/com/netflix/graphql/dgs/codegen/generators/java/InterfaceGenerator.kt
@@ -89,13 +89,13 @@ class InterfaceGenerator(private val config: CodeGenConfig, private val document
         val implementations = document.getDefinitionsOfType(ObjectTypeDefinition::class.java).asSequence()
             .filter { node -> node.implements.any { it.isEqualTo(TypeName(definition.name)) } }
             .map { node ->
-                val nodeName = if (config.generateInterfaces) "I${node.name}" else node.name
-                typeUtils.findJavaInterfaceName(nodeName, packageName)
+                typeUtils.findJavaInterfaceName(node.name, packageName)
             }
             .filterIsInstance<ClassName>()
             .toList()
 
-        if (implementations.isNotEmpty()) {
+        // Add JsonSubType annotations only if there are no generated concrete types that implement the interface
+        if (implementations.isNotEmpty() && config.generateDataTypes) {
             javaType.addAnnotation(jsonTypeInfoAnnotation())
             javaType.addAnnotation(jsonSubTypeAnnotation(implementations))
         }
diff --git a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/CodeGenTest.kt b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/CodeGenTest.kt
index f2a09753f..189b81c9d 100644
--- a/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/CodeGenTest.kt
+++ b/graphql-dgs-codegen-core/src/test/kotlin/com/netflix/graphql/dgs/codegen/CodeGenTest.kt
@@ -2752,6 +2752,42 @@ class CodeGenTest {
         assertCompilesJava(dataTypes + interfaces)
     }
 
+    @Test
+    fun generatedInterfacesShouldShouldHaveCorrectJsonTypeAnnotations() {
+        val schema = """
+            interface Fruit {
+              seeds: [Seed]
+            }
+
+            type Apple implements Fruit {
+              seeds: [Seed]
+              truth: Boolean!
+            }
+
+            type Seed {
+              shape: String
+            }
+        """.trimIndent()
+
+        val result = CodeGen(
+            CodeGenConfig(
+                schemas = setOf(schema),
+                packageName = basePackageName,
+                generateInterfaces = true,
+                generateIsGetterForPrimitiveBooleanFields = true
+            )
+        ).generate()
+
+        val interfaces = result.javaInterfaces
+        val dataTypes = result.javaDataTypes
+
+        val iFruit = interfaces[2]
+        assertThat(iFruit.typeSpec.annotations.size).isEqualTo(2)
+        assertThat(iFruit.typeSpec.annotations[0].toString()).isEqualTo("@com.fasterxml.jackson.annotation.JsonTypeInfo(use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME, include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY, property = \"__typename\")")
+        assertThat(iFruit.typeSpec.annotations[1].toString()).isEqualTo("@com.fasterxml.jackson.annotation.JsonSubTypes(@com.fasterxml.jackson.annotation.JsonSubTypes.Type(value = com.netflix.graphql.dgs.codegen.tests.generated.types.Apple.class, name = \"Apple\"))")
+        assertCompilesJava(dataTypes + interfaces)
+    }
+
     @Test
     fun generateObjectTypeInterfaceWithPrimitiveBooleanShouldUseIsGetter() {
         val schema = """