From 09ab0af2524b3fdeeaa9e0416ba0e56a890eb8a4 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Fri, 4 Feb 2022 15:14:49 -0500 Subject: [PATCH] Clean up of RMI in the docs --- .../handler/DelayHandlerTests.java | 38 ++--- src/reference/asciidoc/configuration.adoc | 3 - src/reference/asciidoc/gateway.adoc | 1 - src/reference/asciidoc/handler-advice.adoc | 19 ++- src/reference/asciidoc/overview.adoc | 1 - src/reference/asciidoc/rmi.adoc | 151 ------------------ src/reference/asciidoc/whats-new.adoc | 2 +- 7 files changed, 30 insertions(+), 185 deletions(-) delete mode 100644 src/reference/asciidoc/rmi.adoc diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/DelayHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/DelayHandlerTests.java index 1471e5de5b..84cac0e69a 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/DelayHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/DelayHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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,8 +18,10 @@ package org.springframework.integration.handler; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.awaitility.Awaitility.await; import static org.mockito.Mockito.mock; +import java.time.Duration; import java.util.Calendar; import java.util.Date; import java.util.Map; @@ -78,14 +80,14 @@ public class DelayHandlerTests { private final CountDownLatch latch = new CountDownLatch(1); + private final ResultHandler resultHandler = new ResultHandler(); + + private final TestApplicationContext context = TestUtils.createTestApplicationContext(); + private ThreadPoolTaskScheduler taskScheduler; private DelayHandler delayHandler; - private final ResultHandler resultHandler = new ResultHandler(); - - private TestApplicationContext context = TestUtils.createTestApplicationContext(); - @BeforeEach public void setup() { input.setBeanName("input"); @@ -172,7 +174,7 @@ public class DelayHandlerTests { assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); Thread.sleep(50); assertThat(count.get()).isEqualTo(4); - assertThat(TestUtils.getPropertyValue(this.delayHandler, "deliveries", Map.class).size()).isEqualTo(0); + assertThat(TestUtils.getPropertyValue(this.delayHandler, "deliveries", Map.class)).hasSize(0); } @Test @@ -343,10 +345,10 @@ public class DelayHandlerTests { input.send(message); waitForLatch(10000); Message errorMessage = resultHandler.lastMessage; - assertThat(errorMessage.getPayload().getClass()).isEqualTo(MessageDeliveryException.class); + assertThat(errorMessage.getPayload()).isInstanceOf(MessageDeliveryException.class); MessageDeliveryException exceptionPayload = (MessageDeliveryException) errorMessage.getPayload(); assertThat(exceptionPayload.getFailedMessage().getPayload()).isSameAs(message.getPayload()); - assertThat(exceptionPayload.getCause().getClass()).isEqualTo(UnsupportedOperationException.class); + assertThat(exceptionPayload.getCause()).isInstanceOf(UnsupportedOperationException.class); assertThat(resultHandler.lastThread).isNotSameAs(Thread.currentThread()); } @@ -375,10 +377,10 @@ public class DelayHandlerTests { input.send(message); waitForLatch(10000); Message errorMessage = resultHandler.lastMessage; - assertThat(errorMessage.getPayload().getClass()).isEqualTo(MessageDeliveryException.class); + assertThat(errorMessage.getPayload()).isInstanceOf(MessageDeliveryException.class); MessageDeliveryException exceptionPayload = (MessageDeliveryException) errorMessage.getPayload(); assertThat(exceptionPayload.getFailedMessage().getPayload()).isSameAs(message.getPayload()); - assertThat(exceptionPayload.getCause().getClass()).isEqualTo(UnsupportedOperationException.class); + assertThat(exceptionPayload.getCause()).isInstanceOf(UnsupportedOperationException.class); assertThat(resultHandler.lastThread).isNotSameAs(Thread.currentThread()); } @@ -405,10 +407,10 @@ public class DelayHandlerTests { input.send(message); waitForLatch(10000); Message errorMessage = resultHandler.lastMessage; - assertThat(errorMessage.getPayload().getClass()).isEqualTo(MessageDeliveryException.class); + assertThat(errorMessage.getPayload()).isInstanceOf(MessageDeliveryException.class); MessageDeliveryException exceptionPayload = (MessageDeliveryException) errorMessage.getPayload(); assertThat(exceptionPayload.getFailedMessage().getPayload()).isSameAs(message.getPayload()); - assertThat(exceptionPayload.getCause().getClass()).isEqualTo(UnsupportedOperationException.class); + assertThat(exceptionPayload.getCause()).isInstanceOf(UnsupportedOperationException.class); assertThat(resultHandler.lastThread).isNotSameAs(Thread.currentThread()); } @@ -497,7 +499,7 @@ public class DelayHandlerTests { } @Test - public void testRescheduleForTheDateDelay() throws Exception { + public void testRescheduleForTheDateDelay() { this.delayHandler.setDelayExpression(new SpelExpressionParser().parseExpression("payload")); this.delayHandler.setOutputChannel(new DirectChannel()); this.delayHandler.setIgnoreExpressionFailures(false); @@ -522,11 +524,11 @@ public class DelayHandlerTests { this.taskScheduler.afterPropertiesSet(); this.delayHandler.reschedulePersistedMessages(); Queue works = ((ScheduledThreadPoolExecutor) this.taskScheduler.getScheduledExecutor()).getQueue(); - int n = 0; - while (n++ < 2000 && works.size() == 0) { - Thread.sleep(10); - } - assertThat(works.size()).isEqualTo(1); + + await() + .atMost(Duration.ofSeconds(20)) + .pollDelay(Duration.ofMillis(10)) + .until(() -> works.size() == 1); } diff --git a/src/reference/asciidoc/configuration.adoc b/src/reference/asciidoc/configuration.adoc index 42116de520..8cabe625a6 100644 --- a/src/reference/asciidoc/configuration.adoc +++ b/src/reference/asciidoc/configuration.adoc @@ -74,7 +74,6 @@ For example, the following root element shows several of these namespace declara xmlns:int-file="http://www.springframework.org/schema/integration/file" xmlns:int-jms="http://www.springframework.org/schema/integration/jms" xmlns:int-mail="http://www.springframework.org/schema/integration/mail" - xmlns:int-rmi="http://www.springframework.org/schema/integration/rmi" xmlns:int-ws="http://www.springframework.org/schema/integration/ws" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd @@ -86,8 +85,6 @@ For example, the following root element shows several of these namespace declara https://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd http://www.springframework.org/schema/integration/mail https://www.springframework.org/schema/integration/mail/spring-integration-mail.xsd - http://www.springframework.org/schema/integration/rmi - https://www.springframework.org/schema/integration/rmi/spring-integration-rmi.xsd http://www.springframework.org/schema/integration/ws https://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd"> ... diff --git a/src/reference/asciidoc/gateway.adoc b/src/reference/asciidoc/gateway.adoc index b91a2e5a15..03350f03e4 100644 --- a/src/reference/asciidoc/gateway.adoc +++ b/src/reference/asciidoc/gateway.adoc @@ -45,7 +45,6 @@ It lets you configure an interface as a service, as the following example shows: ==== With this configuration defined, the `cafeService` can now be injected into other beans, and the code that invokes the methods on that proxied instance of the `Cafe` interface has no awareness of the Spring Integration API. -The general approach is similar to that of Spring Remoting (RMI, HttpInvoker, and so on). See the <<./samples.adoc#samples,"`Samples`">> Appendix for an example that uses the `gateway` element (in the Cafe demo). The defaults in the preceding configuration are applied to all methods on the gateway interface. diff --git a/src/reference/asciidoc/handler-advice.adoc b/src/reference/asciidoc/handler-advice.adoc index cfbd36f958..1d528f2ca2 100644 --- a/src/reference/asciidoc/handler-advice.adoc +++ b/src/reference/asciidoc/handler-advice.adoc @@ -41,7 +41,7 @@ The schema does not allow a `` as a child element However, a `` can be added to individual reply-producing endpoints within a `` element. An exception is that, in a chain that produces no reply, because the last element in the chain is an `outbound-channel-adapter`, that last element cannot be advised. -If you need to advise such an element, it must be moved outside of the chain (with the `output-channel` of the chain being the `input-channel` of the adapter). +If you need to advise such an element, it must be moved outside the chain (with the `output-channel` of the chain being the `input-channel` of the adapter). The adapter can then be advised as usual. For chains that produce a reply, every child element can be advised. ===== @@ -247,7 +247,7 @@ A `` with no child element uses no back off. If there is no `recovery-channel`, the exception is thrown when retries are exhausted. The namespace can only be used with stateless retry. + -For more complex environments (custom policies etc), use normal `` definitions. +For more complex environments (custom policies etc.), use normal `` definitions. Simple Stateful Retry with Recovery:: To make retry stateful, we need to provide the advice with a `RetryStateGenerator` implementation. @@ -324,7 +324,7 @@ The default configuration retries for all exceptions and the exception classifie If you configure it to, say, retry only on `MyException` and your application throws a `SomeOtherException` where the cause is a `MyException`, retry does not occur. + Since Spring Retry 1.0.3, the `BinaryExceptionClassifier` has a property called `traverseCauses` (the default is `false`). -When `true`, it traverses exception causes until it finds a match or runs out of causes to traverse. +When `true`, it traverses exception causes until it finds a match or runs out of causes traversing. + To use this classifier for retry, use a `SimpleRetryPolicy` created with the constructor that takes the max attempts, the `Map` of `Exception` objects, and the `traverseCauses` boolean. Then you can inject this policy into the `RetryTemplate`. @@ -692,17 +692,16 @@ For example, a `RetryOperationsInterceptor` could be applied to the whole sub-fl ==== Transaction Support Starting with version 5.0, a new `TransactionHandleMessageAdvice` has been introduced to make the whole downstream flow transactional, thanks to the `HandleMessageAdvice` implementation. -When a regular `TransactionInterceptor` is used in the `` element (for example, through configuring ``), a started transaction is only applied only for an internal `AbstractReplyProducingMessageHandler.handleRequestMessage()` and is not propagated to the downstream flow. +When a regular `TransactionInterceptor` is used in the `` element (for example, through configuring ``), a started transaction is applied only for an internal `AbstractReplyProducingMessageHandler.handleRequestMessage()` and is not propagated to the downstream flow. To simplify XML configuration, along with the ``, a `` element has been added to all `` and `` and related components. The following example shows `` in use: [source,xml] ---- - - - + + + @@ -798,14 +797,14 @@ public class MyAdvisedFilter { ---- [[advice-order]] -==== Ordering Advices within an Advice Chain +==== Ordering Advices within Advice Chain Advice classes are "`around`" advices and are applied in a nested fashion. The first advice is the outermost, while the last advice is the innermost (that is, closest to the handler being advised). It is important to put the advice classes in the correct order to achieve the functionality you desire. For example, suppose you want to add a retry advice and a transaction advice. -You may want to place the retry advice advice first, followed by the transaction advice. +You may want to place the retry advice first, followed by the transaction advice. Consequently, each retry is performed in a new transaction. On the other hand, if you want all the attempts and any recovery operations (in the retry `RecoveryCallback`) to be scoped within the transaction, you could put the transaction advice first. diff --git a/src/reference/asciidoc/overview.adoc b/src/reference/asciidoc/overview.adoc index 3c723bccdb..23f0ccc31d 100644 --- a/src/reference/asciidoc/overview.adoc +++ b/src/reference/asciidoc/overview.adoc @@ -569,7 +569,6 @@ The affected modules are * `http` * `jms` * `mail` -* `rmi` * `security` * `stream` * `ws` diff --git a/src/reference/asciidoc/rmi.adoc b/src/reference/asciidoc/rmi.adoc deleted file mode 100644 index fbb91521ca..0000000000 --- a/src/reference/asciidoc/rmi.adoc +++ /dev/null @@ -1,151 +0,0 @@ -[[rmi]] -== RMI Support - -IMPORTANT: this module is deprecated since 5.4 with no replacement and will be removed in 6.0. - -This chapter explains how to use channel adapters that are specific to RMI (Remote Method Invocation) to distribute a system over multiple JVMs. -The first section deals with sending messages over RMI. -The second section shows how to receive messages over RMI. -The last section shows how to define RMI channel adapters by using the namespace support. - -You need to include this dependency into your project: - -==== -.Maven -[source, xml, subs="normal"] ----- - - org.springframework.integration - spring-integration-rmi - {project-version} - ----- - -.Gradle -[source, groovy, subs="normal"] ----- -compile "org.springframework.integration:spring-integration-rmi:{project-version}" ----- -==== - -[[rmi-outbound]] -=== Outbound RMI - -To send messages from a channel over RMI, you can define an `RmiOutboundGateway`. -This gateway uses Spring's `RmiProxyFactoryBean` internally to create a proxy for a remote gateway. -Note that, to invoke a remote interface that does not use Spring Integration, you should use a service activator in combination with Spring's RmiProxyFactoryBean. - -To configure the outbound gateway, you can write a bean definition similar the following: - -==== -[source,xml] ----- - - - - ----- -==== - -[[rmi-inbound]] -=== Inbound RMI - -To receive messages over RMI, you need to use an `RmiInboundGateway`. -You can configure the gateway as shown in the following example: - -==== -[source,xml] ----- - - - ----- -==== - -IMPORTANT: If you use an `errorChannel` on an inbound gateway, it the error flow normally returns a result or throws an exception. -This is because it is likely that there is a corresponding outbound gateway waiting for a response of some kind. -Consuming a message on the error flow and not replying results in no reply for the inbound gateway. -Exceptions (on the main flow when there is no `errorChannel` or on the error flow) propagate to the corresponding inbound gateway. - -[[rmi-namespace]] -=== RMI namespace support - -To configure the inbound gateway, you can use the namespace support for it. -The following code snippet shows the different configuration options that are supported: - -==== -[source,xml] ----- - - - - - - - - - ----- -==== - -You can also use the namespace support to configure the outbound gateway. -The following code snippet shows the different configuration for an outbound RMI gateway: - -==== -[source,xml] ----- - ----- -==== - -=== Configuring with Java Configuration - -The following example shows how to configure an inbound gateway and an outbound gateway with Java: - -==== -[source, java] ----- -@Bean -public RmiInboundGateway inbound() { - RmiInboundGateway gateway = new RmiInboundGateway(); - gateway.setRequestChannel(requestChannel()); - gateway.setRegistryHost("host"); - gateway.setRegistryPort(port); - return gateway; -} - -@Bean -@ServiceActivator(inputChannel="inChannel") -public RmiOutboundGateway outbound() { - RmiOutboundGateway gateway = new RmiOutboundGateway("rmi://host:port/" - + RmiInboundGateway.SERVICE_NAME_PREFIX + "remoteChannelName"); - return gateway; -} ----- -==== - -As of version 4.3, the outbound gateway has a second constructor that takes an `RmiProxyFactoryBeanConfigurer` instance, along with the service url argument. -It allows further configuration before the proxy is created -- for example, to inject a Spring Security `ContextPropagatingRemoteInvocationFactory`, as the following example shows: - -[source, java] ----- -@Bean -@ServiceActivator(inputChannel="inChannel") -public RmiOutboundGateway outbound() { - RmiOutboundGateway gateway = new RmiOutboundGateway("rmi://host:port/" - + RmiInboundGateway.SERVICE_NAME_PREFIX + "remoteChannelName", - pfb -> { - pfb.setRemoteInvocationFactory(new ContextPropagatingRemoteInvocationFactory()); - }); - return gateway; -} ----- - -Starting with version 5.0, you can set this with the XML namespace by using the `configurer` attribute. diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 8b36be2736..9b428ec20d 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -12,7 +12,7 @@ If you are interested in the changes and features that were introduced in earlie If you are interested in more details, see the Issue Tracker tickets that were resolved as part of the 6.0 development process. -In general the project has been moved to Java 17 base line and migrated from Java EE to Jakarta EE. +In general the project has been moved to Java 17 baseline and migrated from Java EE to Jakarta EE. [[x6.0-new-components]] === New Components