diff --git a/graphql-kotlin-federation/pom.xml b/graphql-kotlin-federation/pom.xml
index 935e41ebb9..c71dd0cec2 100644
--- a/graphql-kotlin-federation/pom.xml
+++ b/graphql-kotlin-federation/pom.xml
@@ -33,6 +33,10 @@
graphql-kotlin-schema-generator
${project.parent.version}
+
+ io.github.classgraph
+ classgraph
+
org.junit.jupiter
junit-jupiter-params
diff --git a/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGenerator.kt b/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGenerator.kt
index 3a5d1ea737..c16f74dfc1 100644
--- a/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGenerator.kt
+++ b/graphql-kotlin-federation/src/main/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGenerator.kt
@@ -20,8 +20,9 @@ import com.expediagroup.graphql.TopLevelObject
import com.expediagroup.graphql.federation.directives.ExtendsDirective
import com.expediagroup.graphql.generator.SchemaGenerator
import graphql.schema.GraphQLSchema
-import org.reflections.Reflections
+import io.github.classgraph.ClassGraph
import kotlin.reflect.full.createType
+import kotlin.reflect.jvm.jvmName
/**
* Generates federated GraphQL schemas based on the specified configuration.
@@ -41,10 +42,12 @@ open class FederatedSchemaGenerator(generatorConfig: FederatedSchemaGeneratorCon
/**
* Scans specified packages for all the federated (extended) types and adds them to the target schema.
*/
+ @Suppress("Detekt.SpreadOperator")
fun GraphQLSchema.Builder.federation(supportedPackages: List): GraphQLSchema.Builder {
- supportedPackages
- .map { pkg -> Reflections(pkg).getTypesAnnotatedWith(ExtendsDirective::class.java).map { it.kotlin } }
- .flatten()
+ val scanResult = ClassGraph().enableAllInfo().whitelistPackages(*supportedPackages.toTypedArray()).scan()
+
+ scanResult.getClassesWithAnnotation(ExtendsDirective::class.jvmName)
+ .map { it.loadClass().kotlin }
.map {
val graphQLType = if (it.isAbstract) {
interfaceType(it)
diff --git a/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGeneratorTest.kt b/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGeneratorTest.kt
index f256bcb7f4..cbbff12cff 100644
--- a/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGeneratorTest.kt
+++ b/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/FederatedSchemaGeneratorTest.kt
@@ -18,12 +18,12 @@ package com.expediagroup.graphql.federation
import com.expediagroup.graphql.TopLevelObject
import com.expediagroup.graphql.extensions.print
+import com.expediagroup.graphql.federation.data.queries.simple.NestedQuery
+import com.expediagroup.graphql.federation.data.queries.simple.SimpleQuery
import com.expediagroup.graphql.federation.execution.FederatedTypeRegistry
import graphql.schema.GraphQLUnionType
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
-import test.data.queries.simple.NestedQuery
-import test.data.queries.simple.SimpleQuery
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@@ -104,7 +104,7 @@ class FederatedSchemaGeneratorTest {
@Test
fun `verify can generate federated schema`() {
val config = FederatedSchemaGeneratorConfig(
- supportedPackages = listOf("test.data.queries.federated"),
+ supportedPackages = listOf("com.expediagroup.graphql.federation.data.queries.federated"),
hooks = FederatedSchemaGeneratorHooks(FederatedTypeRegistry())
)
@@ -137,7 +137,7 @@ class FederatedSchemaGeneratorTest {
""".trimIndent()
val config = FederatedSchemaGeneratorConfig(
- supportedPackages = listOf("test.data.queries.simple"),
+ supportedPackages = listOf("com.expediagroup.graphql.federation.data.queries.simple"),
hooks = FederatedSchemaGeneratorHooks(FederatedTypeRegistry())
)
@@ -169,7 +169,7 @@ class FederatedSchemaGeneratorTest {
""".trimIndent()
val config = FederatedSchemaGeneratorConfig(
- supportedPackages = listOf("test.data.queries.simple"),
+ supportedPackages = listOf("com.expediagroup.graphql.federation.data.queries.simple"),
hooks = FederatedSchemaGeneratorHooks(FederatedTypeRegistry())
)
diff --git a/graphql-kotlin-federation/src/test/kotlin/test/data/TestResolvers.kt b/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/data/TestResolvers.kt
similarity index 89%
rename from graphql-kotlin-federation/src/test/kotlin/test/data/TestResolvers.kt
rename to graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/data/TestResolvers.kt
index b22eba5513..676b97d2bd 100644
--- a/graphql-kotlin-federation/src/test/kotlin/test/data/TestResolvers.kt
+++ b/graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/data/TestResolvers.kt
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package test.data
+package com.expediagroup.graphql.federation.data
+import com.expediagroup.graphql.federation.data.queries.federated.Book
+import com.expediagroup.graphql.federation.data.queries.federated.User
import com.expediagroup.graphql.federation.execution.FederatedTypeResolver
-import test.data.queries.federated.Book
-import test.data.queries.federated.User
internal class BookResolver : FederatedTypeResolver {
override suspend fun resolve(representations: List
- org.reflections
- reflections
+ io.github.classgraph
+ classgraph
+
+
+ com.google.guava
+ guava
+ ${guava.version}
com.fasterxml.jackson.module
diff --git a/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/SubTypeMapper.kt b/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/SubTypeMapper.kt
index 63309e5587..78828dc34d 100644
--- a/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/SubTypeMapper.kt
+++ b/graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/SubTypeMapper.kt
@@ -16,12 +16,35 @@
package com.expediagroup.graphql.generator
-import org.reflections.Reflections
+import io.github.classgraph.ClassGraph
+import io.github.classgraph.ClassInfo
+import io.github.classgraph.ClassInfoList
import kotlin.reflect.KClass
+import kotlin.reflect.jvm.jvmName
internal class SubTypeMapper(supportedPackages: List) {
- private val reflections = Reflections(supportedPackages)
+ @Suppress("Detekt.SpreadOperator")
+ private val scanResult = ClassGraph()
+ .enableAllInfo()
+ .whitelistPackages(*supportedPackages.toTypedArray())
+ .scan()
- fun getSubTypesOf(kclass: KClass<*>): List> = reflections.getSubTypesOf(kclass.java).filterNot { it.kotlin.isAbstract }.map { it.kotlin }
+ fun getSubTypesOf(kclass: KClass<*>): List> {
+ val classInfo = scanResult.getClassInfo(kclass.jvmName) ?: return emptyList()
+
+ return getImplementingClasses(classInfo)
+ .union(classInfo.subclasses)
+ .map { it.loadClass().kotlin }
+ .filterNot { it.isAbstract }
+ }
+
+ @Suppress("Detekt.SwallowedException")
+ private fun getImplementingClasses(classInfo: ClassInfo) =
+ try {
+ classInfo.classesImplementing
+ } catch (e: IllegalArgumentException) {
+ // Ignored, just return empty list
+ ClassInfoList.emptyList()
+ }
}
diff --git a/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/SubTypeMapperTest.kt b/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/SubTypeMapperTest.kt
index 95f3768976..1678f49a4d 100644
--- a/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/SubTypeMapperTest.kt
+++ b/graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/SubTypeMapperTest.kt
@@ -22,6 +22,10 @@ import kotlin.test.assertEquals
@Suppress("Detekt.UnusedPrivateClass")
internal class SubTypeMapperTest {
+ private interface NoSubTypesInterface
+
+ private abstract class NoSubTypesClass
+
private interface MyInterface {
fun getValue(): Int
}
@@ -75,4 +79,20 @@ internal class SubTypeMapperTest {
assertEquals(expected = 0, actual = list.size)
}
+
+ @Test
+ fun `interface with no subtypes`() {
+ val mapper = SubTypeMapper(listOf("com.expediagroup.graphql"))
+ val list = mapper.getSubTypesOf(NoSubTypesInterface::class)
+
+ assertEquals(expected = 0, actual = list.size)
+ }
+
+ @Test
+ fun `abstract class with no subtypes`() {
+ val mapper = SubTypeMapper(listOf("com.expediagroup.graphql"))
+ val list = mapper.getSubTypesOf(NoSubTypesClass::class)
+
+ assertEquals(expected = 0, actual = list.size)
+ }
}
diff --git a/pom.xml b/pom.xml
index 97cf53ba37..7ddc119916 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,7 +66,7 @@
2.10.0
1.3.50
1.3.2
- 0.9.11
+ 4.8.52
2.2.0.RELEASE
@@ -273,9 +273,9 @@
${kotlin.version}
- org.reflections
- reflections
- ${reflections.version}
+ io.github.classgraph
+ classgraph
+ ${classgraph.version}
com.fasterxml.jackson.module