RMI Support

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
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-rmi</artifactId>
    <version>5.3.0.RELEASE</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-rmi:5.3.0.RELEASE"

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:

<bean id="rmiOutGateway" class=org.spf.integration.rmi.RmiOutboundGateway>
    <constructor-arg value="rmi://host"/>
    <property name="replyChannel" value="replies"/>
</bean>

Inbound RMI

To receive messages over RMI, you need to use an RmiInboundGateway. You can configure the gateway as shown in the following example:

<bean id="rmiInGateway" class=org.spf.integration.rmi.RmiInboundGateway>
    <property name="requestChannel" value="requests"/>
</bean>
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 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:

<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:

<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:

@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:

@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.