Skip to content

Commit 79423f0

Browse files
committed
fix: mark InstrumentationState callback params as @nullable
createState()/createStateAsync() may return null, and the default SimplePerformantInstrumentation.createState() does. After @NullMarked on instrumentation classes (#4272), unannotated state parameters were treated as non-null in Kotlin, causing NPEs for stateless subclasses. Annotate callback state parameters as @nullable to match the optional- state runtime contract. ChainedInstrumentation asserts non-null when casting its own materialized ChainedInstrumentationState. Fixes #4433
1 parent 2586a62 commit 79423f0

9 files changed

Lines changed: 147 additions & 92 deletions

File tree

‎src/main/java/graphql/analysis/MaxQueryComplexityInstrumentation.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import graphql.execution.instrumentation.parameters.InstrumentationValidationParameters;
1313
import graphql.validation.ValidationError;
1414
import org.jspecify.annotations.NullMarked;
15+
import org.jspecify.annotations.Nullable;
1516

1617
import java.util.List;
1718
import java.util.concurrent.CompletableFuture;
@@ -85,15 +86,15 @@ public CompletableFuture<InstrumentationState> createStateAsync(InstrumentationC
8586
}
8687

8788
@Override
88-
public InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters, InstrumentationState rawState) {
89+
public InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters, @Nullable InstrumentationState rawState) {
8990
State state = ofState(rawState);
9091
// for API backwards compatibility reasons we capture the validation parameters, so we can put them into QueryComplexityInfo
9192
state.instrumentationValidationParameters.set(parameters);
9293
return noOp();
9394
}
9495

9596
@Override
96-
public InstrumentationContext<ExecutionResult> beginExecuteOperation(InstrumentationExecuteOperationParameters instrumentationExecuteOperationParameters, InstrumentationState rawState) {
97+
public InstrumentationContext<ExecutionResult> beginExecuteOperation(InstrumentationExecuteOperationParameters instrumentationExecuteOperationParameters, @Nullable InstrumentationState rawState) {
9798
State state = ofState(rawState);
9899
QueryComplexityCalculator queryComplexityCalculator = newQueryComplexityCalculator(instrumentationExecuteOperationParameters.getExecutionContext());
99100
int totalComplexity = queryComplexityCalculator.calculate();

‎src/main/java/graphql/analysis/MaxQueryDepthInstrumentation.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public MaxQueryDepthInstrumentation(int maxDepth, Function<QueryDepthInfo, Boole
4949
}
5050

5151
@Override
52-
public InstrumentationContext<ExecutionResult> beginExecuteOperation(InstrumentationExecuteOperationParameters parameters, InstrumentationState state) {
52+
public InstrumentationContext<ExecutionResult> beginExecuteOperation(InstrumentationExecuteOperationParameters parameters, @Nullable InstrumentationState state) {
5353
QueryTraverser queryTraverser = newQueryTraverser(parameters.getExecutionContext());
5454
int depth = queryTraverser.reducePreOrder((env, acc) -> Math.max(getPathLength(env.getParentEnvironment()), acc), 0);
5555
if (depth > maxDepth) {

‎src/main/java/graphql/execution/instrumentation/ChainedInstrumentation.java‎

Lines changed: 40 additions & 31 deletions
Large diffs are not rendered by default.

‎src/main/java/graphql/execution/instrumentation/Instrumentation.java‎

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,13 @@ default InstrumentationState createState(InstrumentationCreateStateParameters pa
7373
* This is called right at the start of query execution, and it's the first step in the instrumentation chain.
7474
*
7575
* @param parameters the parameters to this step
76-
* @param state the state created during the call to {@link #createStateAsync(InstrumentationCreateStateParameters)}
76+
* @param state the state created during the call to {@link #createStateAsync(InstrumentationCreateStateParameters)},
77+
* or {@code null} when createState/createStateAsync returns null
7778
*
7879
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
7980
*/
8081
@Nullable
81-
default InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters, InstrumentationState state) {
82+
default InstrumentationContext<ExecutionResult> beginExecution(InstrumentationExecutionParameters parameters, @Nullable InstrumentationState state) {
8283
return noOp();
8384
}
8485

@@ -91,7 +92,7 @@ default InstrumentationContext<ExecutionResult> beginExecution(InstrumentationEx
9192
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
9293
*/
9394
@Nullable
94-
default InstrumentationContext<Document> beginParse(InstrumentationExecutionParameters parameters, InstrumentationState state) {
95+
default InstrumentationContext<Document> beginParse(InstrumentationExecutionParameters parameters, @Nullable InstrumentationState state) {
9596
return noOp();
9697
}
9798

@@ -104,7 +105,7 @@ default InstrumentationContext<Document> beginParse(InstrumentationExecutionPara
104105
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
105106
*/
106107
@Nullable
107-
default InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters, InstrumentationState state) {
108+
default InstrumentationContext<List<ValidationError>> beginValidation(InstrumentationValidationParameters parameters, @Nullable InstrumentationState state) {
108109
return noOp();
109110
}
110111

@@ -117,7 +118,7 @@ default InstrumentationContext<List<ValidationError>> beginValidation(Instrument
117118
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
118119
*/
119120
@Nullable
120-
default InstrumentationContext<ExecutionResult> beginExecuteOperation(InstrumentationExecuteOperationParameters parameters, InstrumentationState state) {
121+
default InstrumentationContext<ExecutionResult> beginExecuteOperation(InstrumentationExecuteOperationParameters parameters, @Nullable InstrumentationState state) {
121122
return noOp();
122123
}
123124

@@ -132,7 +133,7 @@ default InstrumentationContext<ExecutionResult> beginExecuteOperation(Instrument
132133
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
133134
*/
134135
@Nullable
135-
default InstrumentationContext<Void> beginReactiveResults(InstrumentationReactiveResultsParameters parameters, InstrumentationState state) {
136+
default InstrumentationContext<Void> beginReactiveResults(InstrumentationReactiveResultsParameters parameters, @Nullable InstrumentationState state) {
136137
return noOp();
137138
}
138139

@@ -146,7 +147,7 @@ default InstrumentationContext<Void> beginReactiveResults(InstrumentationReactiv
146147
* @return a nullable {@link ExecutionStrategyInstrumentationContext} object that will be called back when the step ends (assuming it's not null)
147148
*/
148149
@Nullable
149-
default ExecutionStrategyInstrumentationContext beginExecutionStrategy(InstrumentationExecutionStrategyParameters parameters, InstrumentationState state) {
150+
default ExecutionStrategyInstrumentationContext beginExecutionStrategy(InstrumentationExecutionStrategyParameters parameters, @Nullable InstrumentationState state) {
150151
return ExecutionStrategyInstrumentationContext.NOOP;
151152
}
152153

@@ -160,7 +161,7 @@ default ExecutionStrategyInstrumentationContext beginExecutionStrategy(Instrumen
160161
* @return a nullable {@link ExecutionStrategyInstrumentationContext} object that will be called back when the step ends (assuming it's not null)
161162
*/
162163
@Nullable
163-
default ExecuteObjectInstrumentationContext beginExecuteObject(InstrumentationExecutionStrategyParameters parameters, InstrumentationState state) {
164+
default ExecuteObjectInstrumentationContext beginExecuteObject(InstrumentationExecutionStrategyParameters parameters, @Nullable InstrumentationState state) {
164165
return ExecuteObjectInstrumentationContext.NOOP;
165166
}
166167

@@ -176,7 +177,7 @@ default ExecuteObjectInstrumentationContext beginExecuteObject(InstrumentationEx
176177
*/
177178
@ExperimentalApi
178179
@Nullable
179-
default InstrumentationContext<Object> beginDeferredField(InstrumentationFieldParameters parameters, InstrumentationState state) {
180+
default InstrumentationContext<Object> beginDeferredField(InstrumentationFieldParameters parameters, @Nullable InstrumentationState state) {
180181
return noOp();
181182
}
182183

@@ -189,7 +190,7 @@ default InstrumentationContext<Object> beginDeferredField(InstrumentationFieldPa
189190
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
190191
*/
191192
@Nullable
192-
default InstrumentationContext<ExecutionResult> beginSubscribedFieldEvent(InstrumentationFieldParameters parameters, InstrumentationState state) {
193+
default InstrumentationContext<ExecutionResult> beginSubscribedFieldEvent(InstrumentationFieldParameters parameters, @Nullable InstrumentationState state) {
193194
return noOp();
194195
}
195196

@@ -202,7 +203,7 @@ default InstrumentationContext<ExecutionResult> beginSubscribedFieldEvent(Instru
202203
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
203204
*/
204205
@Nullable
205-
default InstrumentationContext<Object> beginFieldExecution(InstrumentationFieldParameters parameters, InstrumentationState state) {
206+
default InstrumentationContext<Object> beginFieldExecution(InstrumentationFieldParameters parameters, @Nullable InstrumentationState state) {
206207
return noOp();
207208
}
208209

@@ -219,7 +220,7 @@ default InstrumentationContext<Object> beginFieldExecution(InstrumentationFieldP
219220
*/
220221
@Deprecated(since = "2024-04-18")
221222
@Nullable
222-
default InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters, InstrumentationState state) {
223+
default InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetchParameters parameters, @Nullable InstrumentationState state) {
223224
return noOp();
224225
}
225226

@@ -239,7 +240,7 @@ default InstrumentationContext<Object> beginFieldFetch(InstrumentationFieldFetch
239240
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
240241
*/
241242
@Nullable
242-
default FieldFetchingInstrumentationContext beginFieldFetching(InstrumentationFieldFetchParameters parameters, InstrumentationState state) {
243+
default FieldFetchingInstrumentationContext beginFieldFetching(InstrumentationFieldFetchParameters parameters, @Nullable InstrumentationState state) {
243244
InstrumentationContext<Object> ctx = beginFieldFetch(parameters, state);
244245
if (ctx == noOp()) {
245246
return FieldFetchingInstrumentationContext.NOOP;
@@ -256,7 +257,7 @@ default FieldFetchingInstrumentationContext beginFieldFetching(InstrumentationFi
256257
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
257258
*/
258259
@Nullable
259-
default InstrumentationContext<Object> beginFieldCompletion(InstrumentationFieldCompleteParameters parameters, InstrumentationState state) {
260+
default InstrumentationContext<Object> beginFieldCompletion(InstrumentationFieldCompleteParameters parameters, @Nullable InstrumentationState state) {
260261
return noOp();
261262
}
262263

@@ -269,7 +270,7 @@ default InstrumentationContext<Object> beginFieldCompletion(InstrumentationField
269270
* @return a nullable {@link InstrumentationContext} object that will be called back when the step ends (assuming it's not null)
270271
*/
271272
@Nullable
272-
default InstrumentationContext<Object> beginFieldListCompletion(InstrumentationFieldCompleteParameters parameters, InstrumentationState state) {
273+
default InstrumentationContext<Object> beginFieldListCompletion(InstrumentationFieldCompleteParameters parameters, @Nullable InstrumentationState state) {
273274
return noOp();
274275
}
275276

@@ -284,7 +285,7 @@ default InstrumentationContext<Object> beginFieldListCompletion(InstrumentationF
284285
* @return a non-null instrumented ExecutionInput, the default is to return to the same object
285286
*/
286287
@NonNull
287-
default ExecutionInput instrumentExecutionInput(ExecutionInput executionInput, InstrumentationExecutionParameters parameters, InstrumentationState state) {
288+
default ExecutionInput instrumentExecutionInput(ExecutionInput executionInput, InstrumentationExecutionParameters parameters, @Nullable InstrumentationState state) {
288289
return executionInput;
289290
}
290291

@@ -298,7 +299,7 @@ default ExecutionInput instrumentExecutionInput(ExecutionInput executionInput, I
298299
* @return a non-null instrumented DocumentAndVariables, the default is to return to the same objects
299300
*/
300301
@NonNull
301-
default DocumentAndVariables instrumentDocumentAndVariables(DocumentAndVariables documentAndVariables, InstrumentationExecutionParameters parameters, InstrumentationState state) {
302+
default DocumentAndVariables instrumentDocumentAndVariables(DocumentAndVariables documentAndVariables, InstrumentationExecutionParameters parameters, @Nullable InstrumentationState state) {
302303
return documentAndVariables;
303304
}
304305

@@ -313,7 +314,7 @@ default DocumentAndVariables instrumentDocumentAndVariables(DocumentAndVariables
313314
* @return a non-null instrumented GraphQLSchema, the default is to return to the same object
314315
*/
315316
@NonNull
316-
default GraphQLSchema instrumentSchema(GraphQLSchema schema, InstrumentationExecutionParameters parameters, InstrumentationState state) {
317+
default GraphQLSchema instrumentSchema(GraphQLSchema schema, InstrumentationExecutionParameters parameters, @Nullable InstrumentationState state) {
317318
return schema;
318319
}
319320

@@ -328,7 +329,7 @@ default GraphQLSchema instrumentSchema(GraphQLSchema schema, InstrumentationExec
328329
* @return a non-null instrumented ExecutionContext, the default is to return to the same object
329330
*/
330331
@NonNull
331-
default ExecutionContext instrumentExecutionContext(ExecutionContext executionContext, InstrumentationExecutionParameters parameters, InstrumentationState state) {
332+
default ExecutionContext instrumentExecutionContext(ExecutionContext executionContext, InstrumentationExecutionParameters parameters, @Nullable InstrumentationState state) {
332333
return executionContext;
333334
}
334335

@@ -345,7 +346,7 @@ default ExecutionContext instrumentExecutionContext(ExecutionContext executionCo
345346
* @return a non-null instrumented DataFetcher, the default is to return to the same object
346347
*/
347348
@NonNull
348-
default DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher, InstrumentationFieldFetchParameters parameters, InstrumentationState state) {
349+
default DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher, InstrumentationFieldFetchParameters parameters, @Nullable InstrumentationState state) {
349350
return dataFetcher;
350351
}
351352

@@ -359,7 +360,7 @@ default DataFetcher<?> instrumentDataFetcher(DataFetcher<?> dataFetcher, Instrum
359360
* @return a new execution result completable future
360361
*/
361362
@NonNull
362-
default CompletableFuture<ExecutionResult> instrumentExecutionResult(ExecutionResult executionResult, InstrumentationExecutionParameters parameters, InstrumentationState state) {
363+
default CompletableFuture<ExecutionResult> instrumentExecutionResult(ExecutionResult executionResult, InstrumentationExecutionParameters parameters, @Nullable InstrumentationState state) {
363364
return CompletableFuture.completedFuture(executionResult);
364365
}
365366
}

0 commit comments

Comments
 (0)