Skip to content

Commit

Permalink
Avoid duplicate error logging when multiple destinations per binding
Browse files Browse the repository at this point in the history
  • Loading branch information
hightea committed Sep 5, 2024
1 parent 64dd18c commit a64a6e5
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.function.Consumer;
import java.util.function.Function;

import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;

import org.springframework.boot.WebApplicationType;
Expand All @@ -29,6 +30,9 @@
import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.handler.BridgeHandler;
import org.springframework.messaging.support.GenericMessage;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -99,7 +103,7 @@ void configurationWithoutBinderSpecificErrorHandler() {

@Test
void errorBindingWithMultipleDestinationPerBinding() {
new SpringApplicationBuilder(
ApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(NoErrorHandler.class))
.web(WebApplicationType.NONE)
.run("--spring.cloud.stream.bindings.process-in-0.consumer.max-attempts=1",
Expand All @@ -108,6 +112,27 @@ void errorBindingWithMultipleDestinationPerBinding() {
"--spring.jmx.enabled=false");

// must not fail GH-2599
InputDestination source = context.getBean(InputDestination.class);
source.send(new GenericMessage<byte[]>("Hello".getBytes()));
// We validate that error is logged only once : BridgeHandler to bean 'errorChannel' subscribed only once
BinderErrorChannel binderErrorChannel = context.getBean(BinderErrorChannel.class);
assertThat(binderErrorChannel.getSubscriberCount())
.isEqualTo(2); // binderProvidedErrorHandler and BridgeHandler to bean 'errorChannel'
// The BridgeHandler bean associated with this binding bridges to 'errorChannel' bean
assertThat(
context.getBeansOfType(BridgeHandler.class)
.entrySet()
.stream()
.filter(entry -> entry.getKey().endsWith("process-in-0.errors.bridge"))
.findAny())
.isPresent()
.get()
.satisfies(bridgeHandler -> assertThat(bridgeHandler.getValue().getOutputChannel())
.isNotNull()
.asInstanceOf(InstanceOfAssertFactories.type(AbstractMessageChannel.class))
.extracting(AbstractMessageChannel::getBeanName)
.isEqualTo(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)
);
}

@EnableAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -886,10 +886,14 @@ protected final ErrorInfrastructure registerErrorInfrastructure(

// Setup a bridge to global errorChannel to ensure logging of errors could be controlled via standard SI way
if (this.getApplicationContext().containsBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME) && this.isSubscribable(binderErrorChannel)) {
SubscribableChannel globalErrorChannel = this.getApplicationContext().getBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME, SubscribableChannel.class);
BridgeHandler bridge = new BridgeHandler();
bridge.setOutputChannel(globalErrorChannel);
binderErrorChannel.subscribe(bridge);
String errorBridgeHandlerName = getErrorBridgeName(destination, group, consumerProperties);
if (!getApplicationContext().containsBean(errorBridgeHandlerName)) {
SubscribableChannel globalErrorChannel = this.getApplicationContext().getBean(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME, SubscribableChannel.class);
BridgeHandler bridge = new BridgeHandler();
bridge.setOutputChannel(globalErrorChannel);
binderErrorChannel.subscribe(bridge);
((GenericApplicationContext) getApplicationContext()).registerBean(errorBridgeHandlerName, BridgeHandler.class, () -> bridge);
}
}
return new ErrorInfrastructure(binderErrorChannel, recoverer, binderProvidedErrorHandler);
}
Expand Down

0 comments on commit a64a6e5

Please sign in to comment.