|
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 | +import java.util.concurrent.TimeUnit; |
| 22 | + |
19 | 23 | import javax.management.MBeanServer;
|
20 | 24 | import javax.sql.DataSource;
|
21 | 25 |
|
22 | 26 | import io.rsocket.transport.ClientTransport;
|
23 | 27 | import io.rsocket.transport.netty.client.TcpClientTransport;
|
24 | 28 | import org.junit.jupiter.api.Test;
|
| 29 | +import reactor.core.publisher.Mono; |
25 | 30 |
|
26 | 31 | import org.springframework.beans.DirectFieldAccessor;
|
27 | 32 | import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
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;
|
| 73 | +import org.springframework.messaging.support.GenericMessage; |
64 | 74 | import org.springframework.scheduling.TaskScheduler;
|
| 75 | +import org.springframework.scheduling.support.CronTrigger; |
65 | 76 |
|
66 | 77 | import static org.assertj.core.api.Assertions.assertThat;
|
67 | 78 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
@@ -390,6 +401,54 @@ void whenTheUserDefinesTheirOwnDatabaseInitializerThenTheAutoConfiguredIntegrati
|
390 | 401 | .hasBean("customInitializer"));
|
391 | 402 | }
|
392 | 403 |
|
| 404 | + @Test |
| 405 | + void defaultPoller() { |
| 406 | + this.contextRunner.withUserConfiguration(PollingConsumerConfiguration.class).run((context) -> { |
| 407 | + assertThat(context).hasSingleBean(PollerMetadata.class).getBean(PollerMetadata.DEFAULT_POLLER) |
| 408 | + .hasFieldOrPropertyWithValue("maxMessagesPerPoll", (long) PollerMetadata.MAX_MESSAGES_UNBOUNDED) |
| 409 | + .hasFieldOrPropertyWithValue("receiveTimeout", PollerMetadata.DEFAULT_RECEIVE_TIMEOUT) |
| 410 | + .hasFieldOrPropertyWithValue("trigger", null); |
| 411 | + |
| 412 | + GenericMessage<String> testMessage = new GenericMessage<>("test"); |
| 413 | + context.getBean("testChannel", QueueChannel.class).send(testMessage); |
| 414 | + @SuppressWarnings("unchecked") |
| 415 | + BlockingQueue<Message<?>> sink = context.getBean("sink", BlockingQueue.class); |
| 416 | + assertThat(sink.poll(10, TimeUnit.SECONDS)).isSameAs(testMessage); |
| 417 | + }); |
| 418 | + } |
| 419 | + |
| 420 | + @Test |
| 421 | + void customPollerProperties() { |
| 422 | + this.contextRunner.withUserConfiguration(PollingConsumerConfiguration.class) |
| 423 | + .withPropertyValues("spring.integration.poller.cron=* * * ? * *", |
| 424 | + "spring.integration.poller.max-messages-per-poll=1", |
| 425 | + "spring.integration.poller.receive-timeout=10s") |
| 426 | + .run((context) -> { |
| 427 | + assertThat(context).hasSingleBean(PollerMetadata.class) |
| 428 | + .getBean(PollerMetadata.DEFAULT_POLLER, PollerMetadata.class) |
| 429 | + .hasFieldOrPropertyWithValue("maxMessagesPerPoll", 1L) |
| 430 | + .hasFieldOrPropertyWithValue("receiveTimeout", 10000L) |
| 431 | + .extracting(PollerMetadata::getTrigger).isInstanceOf(CronTrigger.class) |
| 432 | + .hasFieldOrPropertyWithValue("expression", "* * * ? * *"); |
| 433 | + |
| 434 | + GenericMessage<String> testMessage = new GenericMessage<>("test"); |
| 435 | + context.getBean("testChannel", QueueChannel.class).send(testMessage); |
| 436 | + @SuppressWarnings("unchecked") |
| 437 | + BlockingQueue<Message<?>> sink = context.getBean("sink", BlockingQueue.class); |
| 438 | + assertThat(sink.poll(10, TimeUnit.SECONDS)).isSameAs(testMessage); |
| 439 | + }); |
| 440 | + } |
| 441 | + |
| 442 | + @Test |
| 443 | + void triggerPropertiesAreMutuallyExclusive() { |
| 444 | + this.contextRunner |
| 445 | + .withPropertyValues("spring.integration.poller.cron=* * * ? * *", |
| 446 | + "spring.integration.poller.fixed-delay=1s") |
| 447 | + .run((context) -> assertThat(context).hasFailed().getFailure() |
| 448 | + .hasRootCauseExactlyInstanceOf(IllegalArgumentException.class).hasMessageContaining( |
| 449 | + "The 'cron', 'fixedDelay' and 'fixedRate' are mutually exclusive 'spring.integration.poller' properties.")); |
| 450 | + } |
| 451 | + |
393 | 452 | @Configuration(proxyBeanMethods = false)
|
394 | 453 | static class CustomMBeanExporter {
|
395 | 454 |
|
@@ -478,4 +537,25 @@ IntegrationDataSourceInitializer customInitializer(DataSource dataSource, Resour
|
478 | 537 |
|
479 | 538 | }
|
480 | 539 |
|
| 540 | + @Configuration(proxyBeanMethods = false) |
| 541 | + static class PollingConsumerConfiguration { |
| 542 | + |
| 543 | + @Bean |
| 544 | + QueueChannel testChannel() { |
| 545 | + return new QueueChannel(); |
| 546 | + } |
| 547 | + |
| 548 | + @Bean |
| 549 | + BlockingQueue<Message<?>> sink() { |
| 550 | + return new LinkedBlockingQueue<>(); |
| 551 | + } |
| 552 | + |
| 553 | + @ServiceActivator(inputChannel = "testChannel") |
| 554 | + @Bean |
| 555 | + MessageHandler handler(BlockingQueue<Message<?>> sink) { |
| 556 | + return sink::add; |
| 557 | + } |
| 558 | + |
| 559 | + } |
| 560 | + |
481 | 561 | }
|
0 commit comments