Skip to content

Commit d4a0300

Browse files
artembilangaryrussell
authored andcommitted
Fix ambiguity for NullChannel instances bean name
When we use explicitly `new NullChannel()` in DSL definition, we don't provide a bean name and just end up with an explicit `nullChannel` component name in the class. This way it clashes with the global `errorChannel`, but since instances are different we get a `BeanDefinitionOverrideException` * Remove explicit `nullChannel` component name in the `NullChannel` in favor of the generated name as it is done for any regular beans * Some internal polishing in the `NullChannel` * Some polishing in the `IntegrationFlowBeanPostProcessor` to deal with `NullChannel` as with any other regular `AbstractMessageChannel`s and generate a proper name for it within the scope of the current `IntegrationFlow`
1 parent 59c69ed commit d4a0300

File tree

3 files changed

+44
-17
lines changed

3 files changed

+44
-17
lines changed

spring-integration-core/src/main/java/org/springframework/integration/channel/NullChannel.java

+13-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,10 +31,10 @@
3131
import org.springframework.integration.support.management.Statistics;
3232
import org.springframework.integration.support.management.metrics.MetricsCaptor;
3333
import org.springframework.integration.support.management.metrics.TimerFacade;
34+
import org.springframework.lang.Nullable;
3435
import org.springframework.messaging.Message;
3536
import org.springframework.messaging.PollableChannel;
3637
import org.springframework.util.Assert;
37-
import org.springframework.util.StringUtils;
3838

3939
/**
4040
* A channel implementation that essentially behaves like "/dev/null".
@@ -54,13 +54,13 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
5454

5555
private final ManagementOverrides managementOverrides = new ManagementOverrides();
5656

57-
private volatile AbstractMessageChannelMetrics channelMetrics = new DefaultMessageChannelMetrics("nullChannel");
57+
private AbstractMessageChannelMetrics channelMetrics = new DefaultMessageChannelMetrics("nullChannel");
5858

59-
private volatile boolean countsEnabled;
59+
private boolean countsEnabled;
6060

61-
private volatile boolean statsEnabled;
61+
private boolean statsEnabled;
6262

63-
private volatile boolean loggingEnabled = true;
63+
private boolean loggingEnabled = true;
6464

6565
private String beanName;
6666

@@ -71,7 +71,7 @@ public class NullChannel implements PollableChannel, MessageChannelMetrics,
7171
@Override
7272
public void setBeanName(String beanName) {
7373
this.beanName = beanName;
74-
this.channelMetrics = new DefaultMessageChannelMetrics(getComponentName());
74+
this.channelMetrics = new DefaultMessageChannelMetrics(this.beanName);
7575
}
7676

7777
@Override
@@ -86,13 +86,14 @@ public void setLoggingEnabled(boolean loggingEnabled) {
8686
}
8787

8888
@Override
89+
@Nullable
8990
public String getComponentName() {
90-
return StringUtils.hasText(this.beanName) ? this.beanName : "nullChannel";
91+
return this.beanName;
9192
}
9293

9394
@Override
9495
public String getComponentType() {
95-
return "channel";
96+
return "null-channel";
9697
}
9798

9899
@Override
@@ -246,7 +247,7 @@ private TimerFacade sendTimer() {
246247
if (this.successTimer == null) {
247248
this.successTimer = this.metricsCaptor.timerBuilder(SEND_TIMER_NAME)
248249
.tag("type", "channel")
249-
.tag("name", getComponentName() == null ? "unknown" : getComponentName())
250+
.tag("name", getComponentName() == null ? "nullChannel" : getComponentName())
250251
.tag("result", "success")
251252
.tag("exception", "none")
252253
.description("Subflow process time")
@@ -257,15 +258,15 @@ private TimerFacade sendTimer() {
257258

258259
@Override
259260
public Message<?> receive() {
260-
if (this.loggingEnabled && this.logger.isDebugEnabled()) {
261+
if (this.loggingEnabled) {
261262
this.logger.debug("receive called on null channel");
262263
}
263264
return null;
264265
}
265266

266267
@Override
267268
public Message<?> receive(long timeout) {
268-
return this.receive();
269+
return receive();
269270
}
270271

271272
@Override

spring-integration-core/src/main/java/org/springframework/integration/dsl/context/IntegrationFlowBeanPostProcessor.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2018 the original author or authors.
2+
* Copyright 2016-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@
5252
import org.springframework.integration.channel.AbstractMessageChannel;
5353
import org.springframework.integration.channel.DirectChannel;
5454
import org.springframework.integration.channel.FixedSubscriberChannel;
55+
import org.springframework.integration.channel.NullChannel;
5556
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
5657
import org.springframework.integration.config.IntegrationConfigUtils;
5758
import org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean;
@@ -175,8 +176,8 @@ else if (useFlowIdAsPrefix) {
175176
}
176177
else {
177178
if (noBeanPresentForComponent(component, flowBeanName)) {
178-
if (component instanceof AbstractMessageChannel) {
179-
String channelBeanName = ((AbstractMessageChannel) component).getComponentName();
179+
if (component instanceof AbstractMessageChannel || component instanceof NullChannel) {
180+
String channelBeanName = ((NamedComponent) component).getComponentName();
180181
if (channelBeanName == null) {
181182
channelBeanName = entry.getValue();
182183
if (channelBeanName == null) {
@@ -263,7 +264,7 @@ else if (component instanceof AnnotationGatewayProxyFactoryBean) {
263264
registerComponent(gateway, gatewayId, flowBeanName,
264265
beanDefinition -> {
265266
((AbstractBeanDefinition) beanDefinition)
266-
.setSource(new DescriptiveResource(gateway.getObjectType().getName()));
267+
.setSource(new DescriptiveResource("" + gateway.getObjectType()));
267268
});
268269

269270
targetIntegrationComponents.put(component, gatewayId);

spring-integration-core/src/test/java/org/springframework/integration/dsl/flows/IntegrationFlowTests.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2018 the original author or authors.
2+
* Copyright 2016-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -504,6 +504,26 @@ public void testNullChannelInTheEndOfFlow() {
504504
this.nullChannel.setCountsEnabled(false);
505505
}
506506

507+
@Autowired
508+
@Qualifier("flowWithLocalNullChannel.input")
509+
private MessageChannel flowWithLocalNullChannelInput;
510+
511+
@Autowired
512+
@Qualifier("flowWithLocalNullChannel.channel#0")
513+
private NullChannel localNullChannel;
514+
515+
@Test
516+
public void testLocalNullChannel() {
517+
this.localNullChannel.setCountsEnabled(true);
518+
519+
this.flowWithLocalNullChannelInput.send(new GenericMessage<>("foo"));
520+
521+
assertEquals(1, this.localNullChannel.getSendCount());
522+
523+
assertNotSame(this.nullChannel, this.localNullChannel);
524+
}
525+
526+
507527
@Autowired
508528
private EventDrivenConsumer flow1WithPrototypeHandlerConsumer;
509529

@@ -892,6 +912,11 @@ public IntegrationFlow flowWithNullChannel() {
892912
.nullChannel();
893913
}
894914

915+
@Bean
916+
public IntegrationFlow flowWithLocalNullChannel() {
917+
return f -> f.channel(new NullChannel());
918+
}
919+
895920
@Bean
896921
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
897922
public AbstractReplyProducingMessageHandler myHandler() {

0 commit comments

Comments
 (0)