INT-4066: Expose RMI Factory Bean

JIRA: https://jira.spring.io/browse/INT-4066

Allow customization.

Rename To RmiProxyFactoryBeanConfigurer

Polishing

More Polishing

Polishing
This commit is contained in:
Gary Russell
2016-08-16 16:04:07 -04:00
committed by Artem Bilan
parent 2a0e56ba6c
commit 77d0becd97
6 changed files with 127 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -37,14 +37,33 @@ public class RmiOutboundGateway extends AbstractReplyProducingMessageHandler {
private final RequestReplyExchanger proxy;
private final RmiProxyFactoryBeanConfigurer configurer;
/**
* Construct an instance with a `RequestReplyExchanger` built from the
* default {@link RmiProxyFactoryBean}.
* @param url the url.
*/
public RmiOutboundGateway(String url) {
this.proxy = this.createProxy(url);
this(url, null);
}
/**
* Construct an instance with a `RequestReplyExchanger` built from the
* default {@link RmiProxyFactoryBean} which can be modified by the
* configurer.
* @param url the url.
* @param configurer the {@link RmiProxyFactoryBeanConfigurer}.
* @since 4.3.2
*/
public RmiOutboundGateway(String url, RmiProxyFactoryBeanConfigurer configurer) {
this.configurer = configurer;
this.proxy = createProxy(url);
}
public void setReplyChannel(MessageChannel replyChannel) {
this.setOutputChannel(replyChannel);
setOutputChannel(replyChannel);
}
@Override
@@ -64,7 +83,10 @@ public class RmiOutboundGateway extends AbstractReplyProducingMessageHandler {
try {
Message<?> reply = this.proxy.exchange(requestMessage);
if (reply != null) {
reply = this.getMessageBuilderFactory().fromMessage(reply).copyHeadersIfAbsent(message.getHeaders()).build();
reply = getMessageBuilderFactory()
.fromMessage(reply)
.copyHeadersIfAbsent(message.getHeaders())
.build();
}
return reply;
}
@@ -72,7 +94,8 @@ public class RmiOutboundGateway extends AbstractReplyProducingMessageHandler {
throw new MessageHandlingException(message, e);
}
catch (RemoteAccessException e) {
throw new MessageHandlingException(message, "Remote failure in RmiOutboundGateway: " + this.getComponentName(), e);
throw new MessageHandlingException(message, "Remote failure in RmiOutboundGateway: " +
this.getComponentName(), e);
}
}
@@ -82,8 +105,26 @@ public class RmiOutboundGateway extends AbstractReplyProducingMessageHandler {
proxyFactory.setServiceUrl(url);
proxyFactory.setLookupStubOnStartup(false);
proxyFactory.setRefreshStubOnConnectFailure(true);
if (this.configurer != null) {
this.configurer.configure(proxyFactory);
}
proxyFactory.afterPropertiesSet();
return (RequestReplyExchanger) proxyFactory.getObject();
}
/**
* Allows configuration of the proxy factory bean before the RMI proxy is created.
* @since 4.3.2
*/
public interface RmiProxyFactoryBeanConfigurer {
/**
* Perform additional configuration of the factory bean before the
* {@code RequestReplyExchanger} is created.
* @param factoryBean the factory bean.
*/
void configure(RmiProxyFactoryBean factoryBean);
}
}

View File

@@ -20,9 +20,11 @@ import java.rmi.registry.Registry;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundGatewayParser;
import org.springframework.integration.rmi.RmiInboundGateway;
import org.springframework.integration.rmi.RmiOutboundGateway;
import org.springframework.util.StringUtils;
/**
@@ -34,7 +36,7 @@ public class RmiOutboundGatewayParser extends AbstractOutboundGatewayParser {
@Override
protected String getGatewayClassName(Element element) {
return "org.springframework.integration.rmi.RmiOutboundGateway";
return RmiOutboundGateway.class.getName();
}
@Override
@@ -50,4 +52,11 @@ public class RmiOutboundGatewayParser extends AbstractOutboundGatewayParser {
return "rmi://" + host + ":" + port + "/" + RmiInboundGateway.SERVICE_NAME_PREFIX + remoteChannel;
}
@Override
protected void postProcessGateway(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
if (StringUtils.hasText(element.getAttribute("configurer"))) {
builder.addConstructorArgReference(element.getAttribute("configurer"));
}
}
}

View File

@@ -114,6 +114,20 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="configurer" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Specify a 'RmiProxyFactoryBeanConfigurer' to further configure the RmiProxyFactoryBean
before it creates the proxy - use this, for example,
to customize the RemoteInvocationFactory.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.rmi.RmiOutboundGateway$RmiProxyFactoryBeanConfigurer"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

View File

@@ -16,6 +16,7 @@
order="23"
request-channel="localChannel"
remote-channel="testChannel"
configurer="configurer"
host="localhost"/>
<channel id="advisedChannel"/>
@@ -30,6 +31,11 @@
</rmi:request-handler-advice-chain>
</rmi:outbound-gateway>
<beans:bean id="configurer" class="org.mockito.Mockito" factory-method="mock">
<beans:constructor-arg
value="org.springframework.integration.rmi.RmiOutboundGateway$RmiProxyFactoryBeanConfigurer" />
</beans:bean>
<beans:bean id="advice"
class="org.springframework.integration.rmi.config.RmiOutboundGatewayParserTests$FooAdvice" />

View File

@@ -19,8 +19,11 @@ package org.springframework.integration.rmi.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -39,6 +42,7 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -70,6 +74,9 @@ public class RmiOutboundGatewayParserTests {
@Autowired
private PollableChannel replyChannel;
@Autowired
private RmiOutboundGateway.RmiProxyFactoryBeanConfigurer configurer;
@Autowired
@Qualifier("gateway.handler")
RmiOutboundGateway gateway;
@@ -89,9 +96,11 @@ public class RmiOutboundGatewayParserTests {
}
@Test
public void testOrder() {
public void testProperties() {
assertEquals(23, TestUtils.getPropertyValue(gateway, "order"));
assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
assertSame(this.configurer, TestUtils.getPropertyValue(this.gateway, "configurer"));
verify(this.configurer).configure(any(RmiProxyFactoryBean.class));
}
@Test

View File

@@ -75,3 +75,44 @@ The following code snippet shows the different configuration for an outbound rmi
remote-channel="testChannel"
host="localhost"/>
----
=== Configuring with Java Configuration
[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;
}
----
Starting with _version 4.3_, the outbound gateway has a second constructor that takes a RmiProxyFactoryBeanConfigurer instance along with the service url argument.
This allows further configuration before the proxy is created; for example, to inject a Spring Security `ContextPropagatingRemoteInvocationFactory`:
[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_, this can be set using the XML namespace, using the `configurer` attribute.