-
Notifications
You must be signed in to change notification settings - Fork 631
Description
Describe the issue
NullPointerException in StreamBridge when functionToInvoke returns null in StreamBridge. This happens reliably when an exception occurs when sending a message using StreamBridge with an object that fails to find a converter. I have a related issue in spring-cloud-function.
This happens for example when attempting to pass a NestedRuntimeException which has a self reference and throws a self-directed error. This results in no converter matching, and a null returned from functionToInvoke.
spring-cloud/spring-cloud-function#1237
I believe this is a valid issue because the RecordRecoverableProcessor added recently expects the following error handling BiConsumer BiConsumer<Record<KIn, VIn>, Exception>. Because the BiConsumer expects Exception, this means all exceptions handled that extend spring's NestedRuntimeException will throw this error if the caller decides to try to send the exception through StreamBridge.
It happens in postProcessResult on the following line
if (this.messageConverter != null && this.CLOUD_EVENT_CLASS != null && this.CLOUD_EVENT_CLASS.isAssignableFrom(result.getClass())) {
convertedResult = this.messageConverter.toMessage(result, input.getHeaders());
}with the error
java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "result" is nullbecause result is being inserted as null.
PR submitted for context (and potential resolution) #3079
To Reproduce
(Fastest way with a debugger)
-
Locate the unit test
test_2249()in StreamBridgeTests -
Place a breakpoint on the following line in the StreamBridge.send method using a debugger
resultMessage = (Message<?>) this.functionInvocationHelper.postProcessResult(resultMessage, null);-
In the spring-cloud-stream project, execute the unit test
test_2249()in StreamBridgeTests -
Manually override resultMessage to null, continue the test and you will be met with the following error:
java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "result" is null(Unit test method)
This test can be added into StreamBridgeTests to verify
@Test
void test() {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(
EmptyConfiguration.class)).web(WebApplicationType.NONE).run(
"--spring.cloud.stream.source=outputA;outputB",
"--spring.cloud.stream.bindings.outputA-out-0.producer.partition-count=3",
"--spring.cloud.stream.bindings.outputB-out-0.destination=outputB",
"--spring.jmx.enabled=false")) {
StreamBridge streamBridge = context.getBean(StreamBridge.class);
streamBridge.send("outputA-out-0",
// Random object example that will guarantee fail to find a converter
new CodecException("someString")
);
}
}Version of the framework
4.3.0-SNAPSHOT (verified in main)
Expected behavior
A null check before postProcessResult is executed with a thrown exception or logging.
I think this will routinely catch developers who use RecordRecoverableProcessor and attempt to send a NestedRuntimeException inheriting exception (or any other scenario where functionToInvoke can result in null)