GH-2118 Wrap publishing ApplicationEvent in try/catch

. . . to ensure that any exceptions resulting from custom implementation of ApplicationLstener does not harm the application
There will now be a WARN message and the stacj trace under DEBUG, but the application will continue to function.

Resolves #2118
This commit is contained in:
Oleg Zhurakousky
2021-03-22 18:30:02 +01:00
parent c750083df6
commit 6c2dbc4708
2 changed files with 30 additions and 3 deletions

View File

@@ -917,7 +917,15 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
private void doPublishEvent(ApplicationEvent event) {
if (this.applicationEventPublisher != null) {
this.applicationEventPublisher.publishEvent(event);
try {
this.applicationEventPublisher.publishEvent(event);
}
catch (Exception e) {
logger.warn("Failed while publishing event " + event + ". "
+ "From the framework perspective this is harmless and typically "
+ "happens when use implement custom ApplicationListener");
logger.debug(e);
}
}
}

View File

@@ -44,6 +44,7 @@ import org.springframework.cloud.function.context.config.ContextFunctionCatalogA
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.binder.Binding;
import org.springframework.cloud.stream.binder.BindingCreatedEvent;
import org.springframework.cloud.stream.binder.test.FunctionBindingTestUtils;
import org.springframework.cloud.stream.binder.test.InputDestination;
import org.springframework.cloud.stream.binder.test.OutputDestination;
@@ -52,6 +53,7 @@ import org.springframework.cloud.stream.binding.BindingsLifecycleController;
import org.springframework.cloud.stream.binding.BindingsLifecycleController.State;
import org.springframework.cloud.stream.messaging.DirectWithAttributesChannel;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.channel.QueueChannel;
@@ -84,10 +86,11 @@ public class ImplicitFunctionBindingTests {
}
@Test
public void testExplicitChannelConfiguration() {
public void testFailedApplicationListenerConfiguration() {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(ExplicitChannelConfiguration.class))
TestChannelBinderConfiguration.getCompleteConfiguration(FailedApplicationListenerConfiguration.class))
.web(WebApplicationType.NONE)
.run("--spring.jmx.enabled=false", "--spring.cloud.function.definition=echo")) {
@@ -1510,6 +1513,22 @@ public class ImplicitFunctionBindingTests {
}
}
@EnableAutoConfiguration
public static class FailedApplicationListenerConfiguration {
@Bean
public Function<String, String> echo() {
return x -> x;
}
@Bean
public ApplicationListener<BindingCreatedEvent> bindingCreatedEventListener() {
return bindingCreatedEvent -> {
throw new RuntimeException("Test");
};
}
}
public static class Person {
private String name;
private int id;