GH-3450: Expose PubSub requireSubscribers option (#3459)

* GH-3450: Expose PubSub requireSubscribers option

Fixes https://github.com/spring-projects/spring-integration/issues/3450

* Add `PublishSubscribeChannel` ctors with the `requireSubscribers` option
with a direct delegation to the same option of underlying `BroadcastingDispatcher`
* Add factory methods to the `Channels` & `MessageChannels` to expose
this new `requireSubscribers` option
* Expose an XML `require-subscribers` attribute for the `<publish-subscribe-channel`
* Document this new `requireSubscribers` option
* Introduce a global `spring.integration.channels.error.requireSubscribers` property
for a default `errorChannel`
* Document this property and explain its default `true` in the `error-handling.adoc`
* Remove docs for `spring.integration.postProcessDynamicBeans` since it purpose was
removed since version `5.1` in favor of "always post-process behavior" as it was
always with all the `BeanPostProcessor`s

* * Fix language in docs according review

* * Add more docs about `requireSubscribers` and cross-links between chapters
This commit is contained in:
Artem Bilan
2021-01-12 13:35:41 -05:00
committed by GitHub
parent f294331945
commit 478a79c74b
15 changed files with 181 additions and 76 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2019 the original author or authors.
* Copyright 2016-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,18 +16,23 @@
package org.springframework.integration.channel;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.Mockito.mock;
import java.util.concurrent.Executor;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.MessageDispatchingException;
import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.support.GenericMessage;
/**
* @author Gary Russell
* @author Artem Bilan
*
* @since 5.0
*
*/
@@ -36,17 +41,21 @@ public class PublishSubscribeChannelTests {
@Test
public void testEarlySubscribe() {
PublishSubscribeChannel channel = new PublishSubscribeChannel(mock(Executor.class));
try {
channel.subscribe(m -> { });
channel.setBeanFactory(mock(BeanFactory.class));
channel.afterPropertiesSet();
fail("expected Exception");
}
catch (IllegalStateException e) {
assertThat(e.getMessage()).isEqualTo("When providing an Executor, you cannot subscribe() until the " +
"channel "
+ "bean is fully initialized by the framework. Do not subscribe in a @Bean definition");
}
channel.subscribe(m -> { });
channel.setBeanFactory(mock(BeanFactory.class));
assertThatIllegalStateException()
.isThrownBy(channel::afterPropertiesSet)
.withMessage("When providing an Executor, you cannot subscribe() until the channel "
+ "bean is fully initialized by the framework. Do not subscribe in a @Bean definition");
}
@Test
public void testRequireSubscribers() {
PublishSubscribeChannel channel = new PublishSubscribeChannel(true);
assertThatExceptionOfType(MessageDeliveryException.class)
.isThrownBy(() -> channel.send(new GenericMessage<>("test")))
.withCauseInstanceOf(MessageDispatchingException.class)
.withMessageContaining("Dispatcher has no subscribers");
}
}

View File

@@ -3,16 +3,10 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
xmlns:beans="http://www.springframework.org/schema/c"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<util:properties id="integrationGlobalProperties">
<prop key="spring.integration.postProcessDynamicBeans">true</prop>
</util:properties>
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="inputA">
<int:interceptors>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,30 +18,29 @@ package org.springframework.integration.config.xml;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.MessageChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
/**
* @author Oleg Zhurakousky
* @author Artem Bilan
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SpringJUnitConfig
public class ErrorChannelAutoCreationTests {
@Autowired
private MessageChannel errorChannel;
// see INT-1899
@Test
public void testErrorChannelIsPubSub() {
assertThat(errorChannel.getClass()).isEqualTo(PublishSubscribeChannel.class);
assertThat(this.errorChannel).isInstanceOf(PublishSubscribeChannel.class);
assertThat(TestUtils.getPropertyValue(this.errorChannel, "dispatcher.requireSubscribers", Boolean.class))
.isTrue();
}
}