Skip to content

Commit 9ed6ea1

Browse files
committed
Remove support for @Batched
1 parent 05de582 commit 9ed6ea1

File tree

10 files changed

+70
-224
lines changed

10 files changed

+70
-224
lines changed

src/main/kotlin/graphql/kickstart/tools/FieldResolverScanner.kt

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,9 @@ internal class FieldResolverScanner(val options: SchemaParserOptions) {
111111

112112
private fun verifyMethodArguments(method: java.lang.reflect.Method, requiredCount: Int, search: Search): Boolean {
113113
val appropriateFirstParameter = if (search.requiredFirstParameterType != null) {
114-
if (MethodFieldResolver.isBatched(method, search)) {
115-
verifyBatchedMethodFirstArgument(method.genericParameterTypes.firstOrNull(), search.requiredFirstParameterType)
116-
} else {
117-
method.genericParameterTypes.firstOrNull()?.let {
118-
it == search.requiredFirstParameterType || method.declaringClass.typeParameters.contains(it)
119-
} ?: false
120-
}
114+
method.genericParameterTypes.firstOrNull()?.let {
115+
it == search.requiredFirstParameterType || method.declaringClass.typeParameters.contains(it)
116+
} ?: false
121117
} else {
122118
true
123119
}
@@ -147,24 +143,6 @@ internal class FieldResolverScanner(val options: SchemaParserOptions) {
147143
}
148144
}
149145

150-
private fun verifyBatchedMethodFirstArgument(firstType: JavaType?, requiredFirstParameterType: Class<*>?): Boolean {
151-
if (firstType == null) {
152-
return false
153-
}
154-
155-
if (firstType !is ParameterizedType) {
156-
return false
157-
}
158-
159-
if (!TypeClassMatcher.isListType(firstType, GenericType(firstType, options))) {
160-
return false
161-
}
162-
163-
val typeArgument = firstType.actualTypeArguments.first() as? Class<*> ?: return false
164-
165-
return typeArgument == requiredFirstParameterType
166-
}
167-
168146
private fun findResolverProperty(field: FieldDefinition, search: Search) =
169147
FieldUtils.getAllFields(search.type.unwrap()).find { it.name == field.name }
170148

@@ -207,7 +185,12 @@ internal class FieldResolverScanner(val options: SchemaParserOptions) {
207185
return signatures
208186
}
209187

210-
data class Search(val type: JavaType, val resolverInfo: ResolverInfo, val source: Any?, val requiredFirstParameterType: Class<*>? = null, val allowBatched: Boolean = false)
188+
data class Search(
189+
val type: JavaType,
190+
val resolverInfo: ResolverInfo,
191+
val source: Any?,
192+
val requiredFirstParameterType: Class<*>? = null
193+
)
211194
}
212195

213196
internal class FieldResolverError(msg: String) : RuntimeException(msg)

src/main/kotlin/graphql/kickstart/tools/MethodFieldResolver.kt

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package graphql.kickstart.tools
22

33
import com.fasterxml.jackson.core.type.TypeReference
44
import graphql.TrivialDataFetcher
5-
import graphql.execution.batched.Batched
65
import graphql.kickstart.tools.SchemaParserOptions.GenericWrapper
76
import graphql.kickstart.tools.util.JavaType
87
import graphql.kickstart.tools.util.coroutineScope
@@ -32,19 +31,6 @@ internal class MethodFieldResolver(
3231
val method: Method
3332
) : FieldResolver(field, search, options, search.type) {
3433

35-
companion object {
36-
fun isBatched(method: Method, search: FieldResolverScanner.Search): Boolean {
37-
if (method.getAnnotation(Batched::class.java) != null) {
38-
if (!search.allowBatched) {
39-
throw ResolverError("The @Batched annotation is only allowed on non-root resolver methods, but it was found on ${search.type.unwrap().name}#${method.name}!")
40-
}
41-
42-
return true
43-
}
44-
return false
45-
}
46-
}
47-
4834
private val additionalLastArgument =
4935
try {
5036
method.kotlinFunction?.valueParameters?.size ?: method.parameterCount == (field.inputValueDefinitions.size + getIndexOffset() + 1)
@@ -53,17 +39,16 @@ internal class MethodFieldResolver(
5339
}
5440

5541
override fun createDataFetcher(): DataFetcher<*> {
56-
val batched = isBatched(method, search)
5742
val args = mutableListOf<ArgumentPlaceholder>()
5843
val mapper = options.objectMapperProvider.provide(field)
5944

6045
// Add source argument if this is a resolver (but not a root resolver)
6146
if (this.search.requiredFirstParameterType != null) {
62-
val expectedType = if (batched) Iterable::class.java else this.search.requiredFirstParameterType
47+
val expectedType = this.search.requiredFirstParameterType
6348

6449
args.add { environment ->
6550
val source = environment.getSource<Any>()
66-
if (!(expectedType.isAssignableFrom(source.javaClass))) {
51+
if (!expectedType.isAssignableFrom(source.javaClass)) {
6752
throw ResolverError("Source type (${source.javaClass.name}) is not expected type (${expectedType.name})!")
6853
}
6954

@@ -117,14 +102,10 @@ internal class MethodFieldResolver(
117102
}
118103
}
119104

120-
return if (batched) {
121-
BatchedMethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
105+
return if (args.isEmpty() && isTrivialDataFetcher(this.method)) {
106+
TrivialMethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
122107
} else {
123-
if (args.isEmpty() && isTrivialDataFetcher(this.method)) {
124-
TrivialMethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
125-
} else {
126-
MethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
127-
}
108+
MethodFieldResolverDataFetcher(getSourceResolver(), this.method, args, options)
128109
}
129110
}
130111

@@ -146,16 +127,15 @@ internal class MethodFieldResolver(
146127
}
147128

148129
override fun scanForMatches(): List<TypeClassMatcher.PotentialMatch> {
149-
val batched = isBatched(method, search)
150130
val unwrappedGenericType = genericType.unwrapGenericType(try {
151131
method.kotlinFunction?.returnType?.javaType ?: method.genericReturnType
152132
} catch (e: InternalError) {
153133
method.genericReturnType
154134
})
155-
val returnValueMatch = TypeClassMatcher.PotentialMatch.returnValue(field.type, unwrappedGenericType, genericType, SchemaClassScanner.ReturnValueReference(method), batched)
135+
val returnValueMatch = TypeClassMatcher.PotentialMatch.returnValue(field.type, unwrappedGenericType, genericType, SchemaClassScanner.ReturnValueReference(method))
156136

157137
return field.inputValueDefinitions.mapIndexed { i, inputDefinition ->
158-
TypeClassMatcher.PotentialMatch.parameterType(inputDefinition.type, getJavaMethodParameterType(i)!!, genericType, SchemaClassScanner.MethodParameterReference(method, i), batched)
138+
TypeClassMatcher.PotentialMatch.parameterType(inputDefinition.type, getJavaMethodParameterType(i)!!, genericType, SchemaClassScanner.MethodParameterReference(method, i))
159139
} + listOf(returnValueMatch)
160140
}
161141

@@ -238,12 +218,13 @@ internal open class MethodFieldResolverDataFetcher(
238218
}
239219
}
240220

241-
internal open class TrivialMethodFieldResolverDataFetcher(
221+
internal class TrivialMethodFieldResolverDataFetcher(
242222
sourceResolver: SourceResolver,
243223
method: Method,
244224
args: List<ArgumentPlaceholder>,
245225
options: SchemaParserOptions
246-
) : MethodFieldResolverDataFetcher(sourceResolver, method, args, options), TrivialDataFetcher<Any>
226+
) : MethodFieldResolverDataFetcher(sourceResolver, method, args, options),
227+
TrivialDataFetcher<Any> // just to mark it for tracing and optimizations
247228

248229
private suspend inline fun invokeSuspend(target: Any, resolverMethod: Method, args: Array<Any?>): Any? {
249230
return suspendCoroutineUninterceptedOrReturn { continuation ->
@@ -268,15 +249,5 @@ private inline fun invoke(method: Method, instance: Any, args: Array<Any?>): Any
268249
}
269250
}
270251

271-
internal class BatchedMethodFieldResolverDataFetcher(
272-
sourceResolver: SourceResolver,
273-
method: Method,
274-
args: List<ArgumentPlaceholder>,
275-
options: SchemaParserOptions
276-
) : MethodFieldResolverDataFetcher(sourceResolver, method, args, options) {
277-
@Batched
278-
override fun get(environment: DataFetchingEnvironment) = super.get(environment)
279-
}
280-
281252
internal typealias ArgumentPlaceholder = (DataFetchingEnvironment) -> Any?
282253

src/main/kotlin/graphql/kickstart/tools/PropertyFieldResolver.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ internal class PropertyFieldResolver(
2525
field.type,
2626
property.genericType,
2727
genericType,
28-
SchemaClassScanner.FieldTypeReference(property.toString()),
29-
false))
28+
SchemaClassScanner.FieldTypeReference(property.toString()))
29+
)
3030
}
3131

3232
override fun toString() = "PropertyFieldResolver{property=$property}"

src/main/kotlin/graphql/kickstart/tools/PropertyMapResolver.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ internal class PropertyMapResolver(
3838
}
3939

4040
override fun scanForMatches(): List<TypeClassMatcher.PotentialMatch> {
41-
return listOf(TypeClassMatcher.PotentialMatch.returnValue(field.type, mapGenericValue, genericType, SchemaClassScanner.FieldTypeReference(field.name), false))
41+
return listOf(TypeClassMatcher.PotentialMatch.returnValue(field.type, mapGenericValue, genericType, SchemaClassScanner.FieldTypeReference(field.name)))
4242
}
4343

4444
override fun toString() = "PropertyMapResolverDataFetcher{key=${field.name}}"

src/main/kotlin/graphql/kickstart/tools/ResolverInfo.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ internal class NormalResolverInfo(
4141

4242
override fun getFieldSearches(): List<FieldResolverScanner.Search> {
4343
return listOf(
44-
FieldResolverScanner.Search(resolverType, this, resolver, dataClassType, true),
44+
FieldResolverScanner.Search(resolverType, this, resolver, dataClassType),
4545
FieldResolverScanner.Search(dataClassType, this, null)
4646
)
4747
}
@@ -66,7 +66,7 @@ internal class MultiResolverInfo(val resolverInfoList: List<NormalResolverInfo>)
6666
override fun getFieldSearches(): List<FieldResolverScanner.Search> {
6767
return resolverInfoList
6868
.asSequence()
69-
.map { FieldResolverScanner.Search(it.resolverType, this, it.resolver, dataClassType, true) }
69+
.map { FieldResolverScanner.Search(it.resolverType, this, it.resolver, dataClassType) }
7070
.plus(FieldResolverScanner.Search(dataClassType, this, null))
7171
.toList()
7272
}

src/main/kotlin/graphql/kickstart/tools/SchemaClassScanner.kt

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,11 @@ internal class SchemaClassScanner(
113113
}
114114

115115
private fun validateAndCreateResult(rootTypeHolder: RootTypesHolder): ScannedSchemaObjects {
116-
initialDictionary.filter { !it.value.accessed }.forEach {
117-
log.warn("Dictionary mapping was provided but never used, and can be safely deleted: \"${it.key}\" -> ${it.value.get().name}")
118-
}
116+
initialDictionary
117+
.filter { !it.value.accessed }
118+
.forEach {
119+
log.warn("Dictionary mapping was provided but never used, and can be safely deleted: \"${it.key}\" -> ${it.value.get().name}")
120+
}
119121

120122
val observedDefinitions = dictionary.keys.toSet() + unvalidatedTypes
121123

@@ -125,35 +127,37 @@ internal class SchemaClassScanner(
125127
// Union types can also be excluded, as their possible types are resolved recursively later
126128
val dictionary = try {
127129
BiMap.unmodifiableBiMap(BiMap.create<TypeDefinition<*>, JavaType>().also {
128-
dictionary.filter {
129-
it.value.javaType != null
130-
&& it.value.typeClass() != java.lang.Object::class.java
131-
&& !java.util.Map::class.java.isAssignableFrom(it.value.typeClass())
132-
&& it.key !is InputObjectTypeDefinition
133-
&& it.key !is UnionTypeDefinition
134-
}.mapValuesTo(it) { it.value.javaType }
130+
dictionary
131+
.filter {
132+
it.value.javaType != null
133+
&& it.value.typeClass() != java.lang.Object::class.java
134+
&& !java.util.Map::class.java.isAssignableFrom(it.value.typeClass())
135+
&& it.key !is InputObjectTypeDefinition
136+
&& it.key !is UnionTypeDefinition
137+
}.mapValuesTo(it) { it.value.javaType }
135138
})
136139
} catch (t: Throwable) {
137140
throw SchemaClassScannerError("Error creating bimap of type => class", t)
138141
}
139142
val scalarDefinitions = observedDefinitions.filterIsInstance<ScalarTypeDefinition>()
140143

141144
// Ensure all scalar definitions have implementations and add the definition to those.
142-
val scalars = scalarDefinitions.filter {
143-
// Filter for any defined scalars OR scalars that aren't defined but also aren't standard
144-
scalars.containsKey(it.name) || !ScalarInfo.STANDARD_SCALAR_DEFINITIONS.containsKey(it.name)
145-
}.map { definition ->
146-
val provided = scalars[definition.name]
147-
?: throw SchemaClassScannerError("Expected a user-defined GraphQL scalar type with name '${definition.name}' but found none!")
148-
GraphQLScalarType.newScalar()
149-
.name(provided.name)
150-
.description(
151-
if (definition.description != null) definition.description.content
152-
else SchemaParser.getDocumentation(definition) ?: provided.description)
153-
.coercing(provided.coercing)
154-
.definition(definition)
155-
.build()
156-
}.associateBy { it.name!! }
145+
val scalars = scalarDefinitions
146+
.filter {
147+
// Filter for any defined scalars OR scalars that aren't defined but also aren't standard
148+
scalars.containsKey(it.name) || !ScalarInfo.STANDARD_SCALAR_DEFINITIONS.containsKey(it.name)
149+
}.map { definition ->
150+
val provided = scalars[definition.name]
151+
?: throw SchemaClassScannerError("Expected a user-defined GraphQL scalar type with name '${definition.name}' but found none!")
152+
GraphQLScalarType.newScalar()
153+
.name(provided.name)
154+
.description(
155+
if (definition.description != null) definition.description.content
156+
else SchemaParser.getDocumentation(definition) ?: provided.description)
157+
.coercing(provided.coercing)
158+
.definition(definition)
159+
.build()
160+
}.associateBy { it.name!! }
157161

158162
val unusedDefinitions = (definitionsByName.values - observedDefinitions).toSet()
159163
unusedDefinitions
@@ -343,8 +347,7 @@ internal class SchemaClassScanner(
343347
inputValueDefinition.type,
344348
inputValueJavaType,
345349
GenericType(javaType, options).relativeToType(inputValueJavaType),
346-
InputObjectReference(inputValueDefinition),
347-
false
350+
InputObjectReference(inputValueDefinition)
348351
)))
349352
} else {
350353
var mappingAdvice = "Try adding it manually to the dictionary"

src/main/kotlin/graphql/kickstart/tools/TypeClassMatcher.kt

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ internal class TypeClassMatcher(private val definitionsByName: Map<String, TypeD
2020
private fun error(potentialMatch: PotentialMatch, msg: String) = SchemaClassScannerError("Unable to match type definition (${potentialMatch.graphQLType}) with java type (${potentialMatch.javaType}): $msg")
2121

2222
fun match(potentialMatch: PotentialMatch): Match {
23-
return if (potentialMatch.batched) {
24-
match(stripBatchedType(potentialMatch)) // stripBatchedType sets 'batched' to false
25-
} else {
26-
match(potentialMatch, potentialMatch.graphQLType, potentialMatch.javaType, true)
27-
}
23+
return match(potentialMatch, potentialMatch.graphQLType, potentialMatch.javaType, true)
2824
}
2925

3026
private fun match(potentialMatch: PotentialMatch, graphQLType: GraphQLLangType, javaType: JavaType, root: Boolean = false): Match {
@@ -101,34 +97,30 @@ internal class TypeClassMatcher(private val definitionsByName: Map<String, TypeD
10197

10298
private fun isListType(realType: ParameterizedType, potentialMatch: PotentialMatch) = isListType(realType, potentialMatch.generic)
10399

104-
private fun stripBatchedType(potentialMatch: PotentialMatch): PotentialMatch {
105-
return if (potentialMatch.location == Location.PARAMETER_TYPE) {
106-
potentialMatch.copy(javaType = potentialMatch.javaType, batched = false)
107-
} else {
108-
val realType = potentialMatch.generic.unwrapGenericType(potentialMatch.javaType)
109-
if (realType is ParameterizedType && isListType(realType, potentialMatch)) {
110-
potentialMatch.copy(javaType = realType.actualTypeArguments.first(), batched = false)
111-
} else {
112-
throw error(potentialMatch, "Method was marked as @Batched but ${potentialMatch.location.prettyName} was not a list!")
113-
}
114-
}
115-
}
116-
117100
internal interface Match
101+
118102
internal data class ScalarMatch(val type: ScalarTypeDefinition) : Match
103+
119104
internal data class ValidMatch(val type: TypeDefinition<*>, val javaType: JavaType, val reference: SchemaClassScanner.Reference) : Match
105+
120106
internal enum class Location(val prettyName: String) {
121107
RETURN_TYPE("return type"),
122108
PARAMETER_TYPE("parameter"),
123109
}
124110

125-
internal data class PotentialMatch(val graphQLType: GraphQLLangType, val javaType: JavaType, val generic: GenericType.RelativeTo, val reference: SchemaClassScanner.Reference, val location: Location, val batched: Boolean) {
111+
internal data class PotentialMatch(
112+
val graphQLType: GraphQLLangType,
113+
val javaType: JavaType,
114+
val generic: GenericType.RelativeTo,
115+
val reference: SchemaClassScanner.Reference,
116+
val location: Location
117+
) {
126118
companion object {
127-
fun returnValue(graphQLType: GraphQLLangType, javaType: JavaType, generic: GenericType.RelativeTo, reference: SchemaClassScanner.Reference, batched: Boolean) =
128-
PotentialMatch(graphQLType, javaType, generic, reference, Location.RETURN_TYPE, batched)
119+
fun returnValue(graphQLType: GraphQLLangType, javaType: JavaType, generic: GenericType.RelativeTo, reference: SchemaClassScanner.Reference) =
120+
PotentialMatch(graphQLType, javaType, generic, reference, Location.RETURN_TYPE)
129121

130-
fun parameterType(graphQLType: GraphQLLangType, javaType: JavaType, generic: GenericType.RelativeTo, reference: SchemaClassScanner.Reference, batched: Boolean) =
131-
PotentialMatch(graphQLType, javaType, generic, reference, Location.PARAMETER_TYPE, batched)
122+
fun parameterType(graphQLType: GraphQLLangType, javaType: JavaType, generic: GenericType.RelativeTo, reference: SchemaClassScanner.Reference) =
123+
PotentialMatch(graphQLType, javaType, generic, reference, Location.PARAMETER_TYPE)
132124
}
133125
}
134126
}

0 commit comments

Comments
 (0)