|
16 | 16 |
|
17 | 17 | package org.springframework.boot.autoconfigure.integration; |
18 | 18 |
|
| 19 | +import java.util.concurrent.BlockingQueue; |
| 20 | +import java.util.concurrent.LinkedBlockingQueue; |
| 21 | + |
19 | 22 | import javax.management.MBeanServer; |
20 | 23 | import javax.sql.DataSource; |
21 | 24 |
|
22 | 25 | import io.rsocket.transport.ClientTransport; |
23 | 26 | import io.rsocket.transport.netty.client.TcpClientTransport; |
| 27 | +import org.assertj.core.api.InstanceOfAssertFactories; |
24 | 28 | import org.junit.jupiter.api.Test; |
25 | 29 |
|
26 | 30 | import org.springframework.beans.DirectFieldAccessor; |
|
37 | 41 | import org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration; |
38 | 42 | import org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration; |
39 | 43 | import org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration; |
| 44 | +import org.springframework.boot.context.properties.source.MutuallyExclusiveConfigurationPropertiesException; |
40 | 45 | import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; |
41 | 46 | import org.springframework.boot.sql.init.DatabaseInitializationMode; |
42 | 47 | import org.springframework.boot.sql.init.DatabaseInitializationSettings; |
|
47 | 52 | import org.springframework.core.io.ResourceLoader; |
48 | 53 | import org.springframework.integration.annotation.IntegrationComponentScan; |
49 | 54 | import org.springframework.integration.annotation.MessagingGateway; |
| 55 | +import org.springframework.integration.annotation.ServiceActivator; |
| 56 | +import org.springframework.integration.channel.QueueChannel; |
50 | 57 | import org.springframework.integration.config.IntegrationManagementConfigurer; |
51 | 58 | import org.springframework.integration.context.IntegrationContextUtils; |
52 | 59 | import org.springframework.integration.endpoint.MessageProcessorMessageSource; |
|
55 | 62 | import org.springframework.integration.rsocket.IntegrationRSocketEndpoint; |
56 | 63 | import org.springframework.integration.rsocket.ServerRSocketConnector; |
57 | 64 | import org.springframework.integration.rsocket.ServerRSocketMessageHandler; |
| 65 | +import org.springframework.integration.scheduling.PollerMetadata; |
58 | 66 | import org.springframework.integration.support.channel.HeaderChannelRegistry; |
59 | 67 | import org.springframework.jdbc.BadSqlGrammarException; |
60 | 68 | import org.springframework.jdbc.core.JdbcOperations; |
61 | 69 | import org.springframework.jmx.export.MBeanExporter; |
62 | 70 | import org.springframework.messaging.Message; |
| 71 | +import org.springframework.messaging.MessageHandler; |
63 | 72 | import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; |
64 | 73 | import org.springframework.scheduling.TaskScheduler; |
| 74 | +import org.springframework.scheduling.support.CronTrigger; |
65 | 75 |
|
66 | 76 | import static org.assertj.core.api.Assertions.assertThat; |
67 | 77 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
@@ -390,6 +400,53 @@ void whenTheUserDefinesTheirOwnDatabaseInitializerThenTheAutoConfiguredIntegrati |
390 | 400 | .hasBean("customInitializer")); |
391 | 401 | } |
392 | 402 |
|
| 403 | + @Test |
| 404 | + void defaultPoller() { |
| 405 | + this.contextRunner.withUserConfiguration(PollingConsumerConfiguration.class).run((context) -> { |
| 406 | + assertThat(context).hasSingleBean(PollerMetadata.class); |
| 407 | + PollerMetadata metadata = context.getBean(PollerMetadata.DEFAULT_POLLER, PollerMetadata.class); |
| 408 | + assertThat(metadata.getMaxMessagesPerPoll()).isEqualTo(PollerMetadata.MAX_MESSAGES_UNBOUNDED); |
| 409 | + assertThat(metadata.getReceiveTimeout()).isEqualTo(PollerMetadata.DEFAULT_RECEIVE_TIMEOUT); |
| 410 | + assertThat(metadata.getTrigger()).isNull(); |
| 411 | + }); |
| 412 | + } |
| 413 | + |
| 414 | + @Test |
| 415 | + void whenCustomPollerPropertiesAreSetThenTheyAreReflectedInPollerMetadata() { |
| 416 | + this.contextRunner.withUserConfiguration(PollingConsumerConfiguration.class) |
| 417 | + .withPropertyValues("spring.integration.poller.cron=* * * ? * *", |
| 418 | + "spring.integration.poller.max-messages-per-poll=1", |
| 419 | + "spring.integration.poller.receive-timeout=10s") |
| 420 | + .run((context) -> { |
| 421 | + assertThat(context).hasSingleBean(PollerMetadata.class); |
| 422 | + PollerMetadata metadata = context.getBean(PollerMetadata.DEFAULT_POLLER, PollerMetadata.class); |
| 423 | + assertThat(metadata.getMaxMessagesPerPoll()).isEqualTo(1L); |
| 424 | + assertThat(metadata.getReceiveTimeout()).isEqualTo(10000L); |
| 425 | + assertThat(metadata.getTrigger()).asInstanceOf(InstanceOfAssertFactories.type(CronTrigger.class)) |
| 426 | + .satisfies((trigger) -> assertThat(trigger.getExpression()).isEqualTo("* * * ? * *")); |
| 427 | + }); |
| 428 | + } |
| 429 | + |
| 430 | + @Test |
| 431 | + void whenPollerPropertiesForMultipleTriggerTypesAreSetThenRefreshFails() { |
| 432 | + this.contextRunner |
| 433 | + .withPropertyValues("spring.integration.poller.cron=* * * ? * *", |
| 434 | + "spring.integration.poller.fixed-delay=1s") |
| 435 | + .run((context) -> assertThat(context).hasFailed().getFailure() |
| 436 | + .hasRootCauseExactlyInstanceOf(MutuallyExclusiveConfigurationPropertiesException.class) |
| 437 | + .getRootCause() |
| 438 | + .asInstanceOf( |
| 439 | + InstanceOfAssertFactories.type(MutuallyExclusiveConfigurationPropertiesException.class)) |
| 440 | + .satisfies((ex) -> { |
| 441 | + assertThat(ex.getConfiguredNames()).containsExactlyInAnyOrder( |
| 442 | + "spring.integration.poller.cron", "spring.integration.poller.fixed-delay"); |
| 443 | + assertThat(ex.getMutuallyExclusiveNames()).containsExactlyInAnyOrder( |
| 444 | + "spring.integration.poller.cron", "spring.integration.poller.fixed-delay", |
| 445 | + "spring.integration.poller.fixed-rate"); |
| 446 | + })); |
| 447 | + |
| 448 | + } |
| 449 | + |
393 | 450 | @Configuration(proxyBeanMethods = false) |
394 | 451 | static class CustomMBeanExporter { |
395 | 452 |
|
@@ -478,4 +535,25 @@ IntegrationDataSourceInitializer customInitializer(DataSource dataSource, Resour |
478 | 535 |
|
479 | 536 | } |
480 | 537 |
|
| 538 | + @Configuration(proxyBeanMethods = false) |
| 539 | + static class PollingConsumerConfiguration { |
| 540 | + |
| 541 | + @Bean |
| 542 | + QueueChannel testChannel() { |
| 543 | + return new QueueChannel(); |
| 544 | + } |
| 545 | + |
| 546 | + @Bean |
| 547 | + BlockingQueue<Message<?>> sink() { |
| 548 | + return new LinkedBlockingQueue<>(); |
| 549 | + } |
| 550 | + |
| 551 | + @ServiceActivator(inputChannel = "testChannel") |
| 552 | + @Bean |
| 553 | + MessageHandler handler(BlockingQueue<Message<?>> sink) { |
| 554 | + return sink::add; |
| 555 | + } |
| 556 | + |
| 557 | + } |
| 558 | + |
481 | 559 | } |
0 commit comments