Skip to content

Commit 55b4d19

Browse files
authored
Merge pull request #849 from graphql-java-kickstart/build/stricter-verify
Fail the build on compiler warnings and check the release bundle in CI
2 parents 79e65c6 + c5d449b commit 55b4d19

22 files changed

Lines changed: 130 additions & 52 deletions

‎.github/workflows/pull-request.yml‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,23 @@ jobs:
2424
restore-keys: ${{ runner.os }}-m2
2525
- name: Build with Maven
2626
run: mvn --batch-mode --update-snapshots verify
27+
28+
# The same jar has to work with the oldest supported graphql-java, so build and test against it too
29+
graphql-java-25:
30+
runs-on: ubuntu-latest
31+
steps:
32+
- name: Checkout
33+
uses: actions/checkout@v7
34+
- name: Setup java
35+
uses: actions/setup-java@v6
36+
with:
37+
java-version: '11'
38+
distribution: 'temurin'
39+
- name: Cache Maven packages
40+
uses: actions/cache@v6
41+
with:
42+
path: ~/.m2
43+
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
44+
restore-keys: ${{ runner.os }}-m2
45+
- name: Build with Maven
46+
run: mvn --batch-mode --update-snapshots verify -Dgraphql-java.version=25.1

‎pom.xml‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@
262262
<artifactId>kotlin-maven-plugin</artifactId>
263263
<groupId>org.jetbrains.kotlin</groupId>
264264
<version>${kotlin.version}</version>
265+
<configuration>
266+
<args>
267+
<arg>-Werror</arg>
268+
</args>
269+
</configuration>
265270
<executions>
266271
<execution>
267272
<id>compile</id>
@@ -286,8 +291,8 @@
286291
<artifactId>maven-compiler-plugin</artifactId>
287292
<version>3.16.0</version>
288293
<configuration>
289-
<source>11</source>
290-
<target>11</target>
294+
<release>11</release>
295+
<failOnWarning>true</failOnWarning>
291296
</configuration>
292297
</plugin>
293298

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ internal class SchemaClassScanner(
234234
dictionary
235235
.filter {
236236
it.value.javaType != null
237-
&& it.value.typeClass() != java.lang.Object::class.java
238-
&& !java.util.Map::class.java.isAssignableFrom(it.value.typeClass())
237+
&& it.value.typeClass() != Any::class.java
238+
&& !Map::class.java.isAssignableFrom(it.value.typeClass())
239239
&& it.key !is InputObjectTypeDefinition
240240
&& it.key !is UnionTypeDefinition
241241
}.mapValuesTo(it) { it.value.javaType }
@@ -355,7 +355,7 @@ internal class SchemaClassScanner(
355355
* Scan a new object for types that haven't been mapped yet.
356356
*/
357357
private fun scanQueueItemForPotentialMatches(item: QueueItem) {
358-
val resolverInfo = if (item.clazz == Object::class.java) {
358+
val resolverInfo = if (item.clazz == Any::class.java) {
359359
getResolverInfoFromTypeDictionary(item.type.name)
360360
?: throw SchemaClassScannerError("The GraphQL schema type '${item.type.name}' maps to a field of type java.lang.Object however there is no matching entry for this type in the type dictionary. You may need to add this type to the dictionary before building the schema.")
361361
} else {
@@ -391,7 +391,7 @@ internal class SchemaClassScanner(
391391
}
392392

393393
private fun isResolverForSupertype(resolverInfo: NormalResolverInfo, dataClass: Class<*>) =
394-
resolverInfo.dataClassType != Object::class.java && resolverInfo.dataClassType.isAssignableFrom(dataClass)
394+
resolverInfo.dataClassType != Any::class.java && resolverInfo.dataClassType.isAssignableFrom(dataClass)
395395

396396
private fun scanResolverInfoForPotentialMatches(type: ObjectTypeDefinition, resolverInfo: ResolverInfo) {
397397
type.getExtendedFieldDefinitions(extensionDefinitions).forEach { field ->
@@ -428,7 +428,7 @@ internal class SchemaClassScanner(
428428
if (options.preferGraphQLResolver && realEntry.hasResolverRef()) {
429429
log.warn("The real entry ${realEntry.joinReferences()} is a GraphQLResolver so ignoring this one ${javaType.unwrap()} $reference")
430430
} else {
431-
if (java.util.Map::class.java.isAssignableFrom(javaType.unwrap())) {
431+
if (Map::class.java.isAssignableFrom(javaType.unwrap())) {
432432
throw SchemaClassScannerError("Two different property map classes used for type ${type.name}:\n${realEntry.joinReferences()}\n\n- ${javaType}:\n| ${reference.getDescription()}")
433433
}
434434
throw SchemaClassScannerError("Two different classes used for type ${type.name}:\n${realEntry.joinReferences()}\n\n- ${javaType.typeName}:\n| ${reference.getDescription()}")

‎src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import graphql.language.*
1212
import graphql.schema.*
1313
import graphql.schema.idl.RuntimeWiring
1414
import graphql.schema.idl.ScalarInfo
15-
import graphql.schema.visibility.NoIntrospectionGraphqlFieldVisibility
15+
import graphql.schema.visibility.BlockedFields
1616
import org.slf4j.LoggerFactory
1717
import kotlin.reflect.KClass
1818

@@ -69,7 +69,10 @@ class SchemaParser internal constructor(
6969
*/
7070
fun parseSchemaObjects(): SchemaObjects {
7171
if (!options.introspectionEnabled) {
72-
codeRegistryBuilder.fieldVisibility(NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY)
72+
// What the deprecated NoIntrospectionGraphqlFieldVisibility does. Its suggested replacement,
73+
// Introspection.enabledJvmWide, would also turn introspection off for every other schema in the JVM.
74+
// TODO deprecate introspectionEnabled and remove this in 15.0.0 (#858)
75+
codeRegistryBuilder.fieldVisibility(BlockedFields.newBlock().addPattern("__.*").build())
7376
}
7477
// this overrides the above introspection enabled setting obviously... todo: add documentation
7578
options.fieldVisibility?.let { codeRegistryBuilder.fieldVisibility(it) }
@@ -433,6 +436,7 @@ class SchemaParser internal constructor(
433436
}
434437

435438
// TODO remove this once directives are fully replaced with applied directives
439+
@Suppress("DEPRECATION") // legacy directive argument values
436440
private fun buildDirectives(
437441
directives: List<Directive>,
438442
directiveLocation: Introspection.DirectiveLocation
@@ -535,7 +539,7 @@ class SchemaParser internal constructor(
535539
is NonNullType -> GraphQLNonNull(determineType(expectedType, typeDefinition.type, allowedTypeReferences, inputObjects))
536540
is InputObjectTypeDefinition -> {
537541
log.info("Create input object")
538-
createInputObject(typeDefinition, inputObjects, referencingInputObjects as MutableSet<String>)
542+
createInputObject(typeDefinition, inputObjects, referencingInputObjects)
539543
}
540544
is TypeName -> {
541545
val scalarType = customScalars[typeDefinition.name]

‎src/main/kotlin/graphql/kickstart/tools/SchemaParserOptions.kt‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import graphql.schema.DataFetcher
1010
import graphql.schema.DataFetchingEnvironment
1111
import graphql.schema.visibility.GraphqlFieldVisibility
1212
import kotlinx.coroutines.Dispatchers
13-
import kotlinx.coroutines.ExperimentalCoroutinesApi
1413
import kotlinx.coroutines.channels.ReceiveChannel
1514
import kotlinx.coroutines.reactive.publish
1615
import org.reactivestreams.Publisher
@@ -45,7 +44,6 @@ data class SchemaParserOptions internal constructor(
4544
fun newOptions() = Builder()
4645

4746
@JvmStatic
48-
@ExperimentalCoroutinesApi
4947
fun defaultOptions() = Builder().build()
5048
}
5149

@@ -164,7 +162,6 @@ data class SchemaParserOptions internal constructor(
164162
this.allowUndeclaredDirectives = allowUndeclaredDirectives
165163
}
166164

167-
@ExperimentalCoroutinesApi
168165
fun build(): SchemaParserOptions {
169166
val coroutineContextProvider = coroutineContextProvider
170167
?: DefaultCoroutineContextProvider(Dispatchers.Default)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ internal class TypeClassMatcher(private val definitionsByName: Map<String, TypeD
6868
realType is Class<*> && realType.isArray ->
6969
match(potentialMatch, graphQLType.type, realType.componentType)
7070
// e.g. a property map value: the element type is unknown, so match it as Object too
71-
realType == Object::class.java ->
71+
realType == Any::class.java ->
7272
match(potentialMatch, graphQLType.type, realType)
7373
else ->
7474
throw error(potentialMatch, "Java class is not a List or generic type information was lost: $realType")

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ internal class FieldResolverScanner(val options: SchemaParserOptions) {
5656
}
5757
}
5858

59-
if (java.util.Map::class.java.isAssignableFrom(search.type.unwrap())) {
59+
if (Map::class.java.isAssignableFrom(search.type.unwrap())) {
6060
return MapFieldResolver(field, search, options, search.type.unwrap())
6161
}
6262

@@ -128,7 +128,7 @@ internal class FieldResolverScanner(val options: SchemaParserOptions) {
128128
.filter { !Modifier.isPrivate(it.modifiers) }
129129
// discard any methods that are coming off the root of the class hierarchy
130130
// to avoid issues with duplicate method declarations
131-
.filter { it.declaringClass != Object::class.java }
131+
.filter { it.declaringClass != Any::class.java }
132132
// subscription resolvers must return a publisher
133133
.filter { !search.isSubscription || resolverMethodReturnsPublisher(it) }
134134
.toList()

‎src/main/kotlin/graphql/kickstart/tools/resolver/MapFieldResolver.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ internal class MapFieldResolver(
3636
val resolvedType = TypeResolver().resolve(mapClass)
3737
val typeParameters = resolvedType.typeParametersFor(Map::class.java)
3838

39-
return typeParameters.elementAtOrElse(1) { Object::class.java }
39+
return typeParameters.elementAtOrElse(1) { Any::class.java }
4040
}
4141

4242
override fun createDataFetcher(): DataFetcher<*> {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ internal class MethodFieldResolver(
157157
is ListType -> List::class.java.isAssignableFrom(this.typeResolver.getRawClass(genericParameterType))
158158
&& isConcreteScalarType(environment, type.type, this.typeResolver.resolve(genericParameterType))
159159

160-
is TypeName -> environment.graphQLSchema?.getType(type.name!!)?.let { isScalar(it) && type.name != "ID" }
160+
is TypeName -> environment.graphQLSchema.getType(type.name!!)?.let { isScalar(it) && type.name != "ID" }
161161
?: false
162162

163163
is NonNullType -> isConcreteScalarType(environment, type.type, genericParameterType)

‎src/main/kotlin/module-info.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
requires kotlinx.coroutines.reactive;
66

77
requires com.graphqljava;
8+
// graphql-java's nullability annotations, only needed at compile time
9+
requires static org.jspecify;
810

911
requires com.fasterxml.jackson.core;
1012
requires com.fasterxml.jackson.kotlin;

0 commit comments

Comments
 (0)