Clean up of RMI in the docs
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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">
|
||||
...
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -41,7 +41,7 @@ The schema does not allow a `<request-handler-advice-chain>` as a child element
|
||||
|
||||
However, a `<request-handler-advice-chain>` can be added to individual reply-producing endpoints within a `<chain>` 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 `<handler-retry-advice>` 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 `<bean>` definitions.
|
||||
For more complex environments (custom policies etc.), use normal `<bean>` 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 `<request-handler-advice-chain>` element (for example, through configuring `<tx:advice>`), 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 `<request-handler-advice-chain>` element (for example, through configuring `<tx:advice>`), 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 `<request-handler-advice-chain>`, a `<transactional>` element has been added to all `<outbound-gateway>` and `<service-activator>` and related components.
|
||||
The following example shows `<transactional>` in use:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<int-rmi:outbound-gateway remote-channel="foo" host="localhost"
|
||||
request-channel="good" reply-channel="reply" port="#{@port}">
|
||||
<int-rmi:transactional/>
|
||||
</int-rmi:outbound-gateway>
|
||||
<int-jdbc:outbound-gateway query="select * from things where id=:headers[id]">
|
||||
<int-jdbc:transactional/>
|
||||
</int-jdbc:outbound-gateway>
|
||||
|
||||
<bean id="transactionManager" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="org.springframework.transaction.TransactionManager"/>
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -569,7 +569,6 @@ The affected modules are
|
||||
* `http`
|
||||
* `jms`
|
||||
* `mail`
|
||||
* `rmi`
|
||||
* `security`
|
||||
* `stream`
|
||||
* `ws`
|
||||
|
||||
@@ -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"]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-rmi</artifactId>
|
||||
<version>{project-version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
.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]
|
||||
----
|
||||
<bean id="rmiOutGateway" class=org.spf.integration.rmi.RmiOutboundGateway>
|
||||
<constructor-arg value="rmi://host"/>
|
||||
<property name="replyChannel" value="replies"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
[[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]
|
||||
----
|
||||
<bean id="rmiInGateway" class=org.spf.integration.rmi.RmiInboundGateway>
|
||||
<property name="requestChannel" value="requests"/>
|
||||
</bean>
|
||||
----
|
||||
====
|
||||
|
||||
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]
|
||||
----
|
||||
<int-rmi:inbound-gateway id="gatewayWithDefaults" request-channel="testChannel"/>
|
||||
|
||||
<int-rmi:inbound-gateway id="gatewayWithCustomProperties" request-channel="testChannel"
|
||||
expect-reply="false" request-timeout="123" reply-timeout="456"/>
|
||||
|
||||
<int-rmi:inbound-gateway id="gatewayWithHost" request-channel="testChannel"
|
||||
registry-host="localhost"/>
|
||||
|
||||
<int-rmi:inbound-gateway id="gatewayWithPort" request-channel="testChannel"
|
||||
registry-port="1234" error-channel="rmiErrorChannel"/>
|
||||
|
||||
<int-rmi:inbound-gateway id="gatewayWithExecutorRef" request-channel="testChannel"
|
||||
remote-invocation-executor="invocationExecutor"/>
|
||||
----
|
||||
====
|
||||
|
||||
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]
|
||||
----
|
||||
<int-rmi:outbound-gateway id="gateway"
|
||||
request-channel="localChannel"
|
||||
remote-channel="testChannel"
|
||||
host="localhost"/>
|
||||
----
|
||||
====
|
||||
|
||||
=== 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.
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user