Skip to content

Commit

Permalink
INT-4315: Add WebFlux module
Browse files Browse the repository at this point in the history
JIRA: https://jira.spring.io/browse/INT-4315

Move Reactive components outside of HTTP module to the new WebFlux one,
including XSD, tests and documentation
Make an appropriate polishing for the `http.adoc` with cross-link
to the `webflux.adoc`

Exclude transitive `spring-webmvc` for the `spring-integration-webflux`
  • Loading branch information
artembilan authored and garyrussell committed Aug 11, 2017
1 parent 4fd32d2 commit 84d60f4
Show file tree
Hide file tree
Showing 52 changed files with 1,657 additions and 1,003 deletions.
23 changes: 17 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -396,17 +396,13 @@ project('spring-integration-http') {
description = 'Spring Integration HTTP Support'
dependencies {
compile project(":spring-integration-core")
compile "org.springframework:spring-web:$springVersion"
compile ("org.springframework:spring-webmvc:$springVersion", optional)
compile ("org.springframework:spring-webflux:$springVersion", optional)
compile "org.springframework:spring-webmvc:$springVersion"
compile ("javax.servlet:javax.servlet-api:$servletApiVersion", provided)
compile ("com.rometools:rome:$romeToolsVersion", optional)
compile ("io.projectreactor.ipc:reactor-netty:$reactorNettyVersion" , optional)

testCompile project(":spring-integration-security")
testCompile "org.springframework.security:spring-security-config:$springSecurityVersion"
testCompile "org.springframework.security:spring-security-test:$springSecurityVersion"
testCompile "io.projectreactor:reactor-test:$reactorVersion"
}
}

Expand Down Expand Up @@ -642,7 +638,6 @@ project('spring-integration-twitter') {
exclude group: 'org.springframework', module: 'spring-expression'
exclude group: 'org.springframework', module: 'spring-web'
exclude group: 'org.springframework', module: 'spring-webmvc'

}
compile("javax.activation:activation:$javaxActivationVersion", optional)
testCompile project(":spring-integration-redis")
Expand All @@ -651,6 +646,22 @@ project('spring-integration-twitter') {
}
}

project('spring-integration-webflux') {
description = 'Spring Integration HTTP Support'
dependencies {
compile (project(":spring-integration-http")) {
exclude group: 'org.springframework', module: 'spring-webmvc'
}
compile "org.springframework:spring-webflux:$springVersion"
compile ("io.projectreactor.ipc:reactor-netty:$reactorNettyVersion" , optional)

testCompile "org.springframework:spring-webmvc:$springVersion"
testCompile "org.springframework.security:spring-security-config:$springSecurityVersion"
testCompile "org.springframework.security:spring-security-test:$springSecurityVersion"
testCompile "io.projectreactor:reactor-test:$reactorVersion"
}
}

project('spring-integration-websocket') {
description = 'Spring Integration WebSockets Support'
dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.integration.config.IntegrationConfigurationInitializer;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.http.inbound.IntegrationHandlerResultHandler;
import org.springframework.integration.http.inbound.IntegrationRequestMappingHandlerMapping;
import org.springframework.integration.http.inbound.ReactiveIntegrationRequestMappingHandlerMapping;
import org.springframework.integration.http.support.HttpContextUtils;

/**
Expand All @@ -48,7 +44,6 @@ public class HttpIntegrationConfigurationInitializer implements IntegrationConfi
public void initialize(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof BeanDefinitionRegistry) {
registerRequestMappingHandlerMappingIfNecessary((BeanDefinitionRegistry) beanFactory);
registerReactiveRequestMappingHandlerMappingIfNecessary((BeanDefinitionRegistry) beanFactory);
}
else {
logger.warn("'IntegrationRequestMappingHandlerMapping' isn't registered because 'beanFactory'" +
Expand Down Expand Up @@ -78,30 +73,4 @@ private void registerRequestMappingHandlerMappingIfNecessary(BeanDefinitionRegis
}
}

/**
* Registers a {@link ReactiveIntegrationRequestMappingHandlerMapping}
* which could also be overridden by the user by simply registering
* a {@link ReactiveIntegrationRequestMappingHandlerMapping} {@code <bean>} with 'id'
* {@link HttpContextUtils#REACTIVE_HANDLER_MAPPING_BEAN_NAME}.
* <p>
* In addition, checks if the {@code org.springframework.web.reactive.result.method.RequestMappingInfo}
* class is present on the classpath.
* When Spring Integration HTTP is used only as an HTTP client, there is no reason to use and register
* the HTTP server components.
*/
private void registerReactiveRequestMappingHandlerMappingIfNecessary(BeanDefinitionRegistry registry) {
if (HttpContextUtils.WEB_FLUX_PRESENT &&
!registry.containsBeanDefinition(HttpContextUtils.REACTIVE_HANDLER_MAPPING_BEAN_NAME)) {
BeanDefinitionBuilder requestMappingBuilder =
BeanDefinitionBuilder.genericBeanDefinition(ReactiveIntegrationRequestMappingHandlerMapping.class);
requestMappingBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
requestMappingBuilder.addPropertyValue(IntegrationNamespaceUtils.ORDER, 0);
registry.registerBeanDefinition(HttpContextUtils.REACTIVE_HANDLER_MAPPING_BEAN_NAME,
requestMappingBuilder.getBeanDefinition());

BeanDefinitionReaderUtils.registerWithGeneratedName(
new RootBeanDefinition(IntegrationHandlerResultHandler.class), registry);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ public void init() {
registerBeanDefinitionParser("inbound-gateway", new HttpInboundEndpointParser(true));
registerBeanDefinitionParser("outbound-channel-adapter", new HttpOutboundChannelAdapterParser());
registerBeanDefinitionParser("outbound-gateway", new HttpOutboundGatewayParser());
registerBeanDefinitionParser("outbound-reactive-channel-adapter", new HttpOutboundChannelAdapterParser());
registerBeanDefinitionParser("outbound-reactive-gateway", new HttpOutboundGatewayParser());
registerBeanDefinitionParser("graph-controller", new IntegrationGraphControllerParser());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@

import org.w3c.dom.Element;

import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.integration.http.outbound.ReactiveHttpRequestExecutingMessageHandler;
import org.springframework.util.StringUtils;

/**
Expand All @@ -42,41 +42,13 @@ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAda

@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder;
boolean reactive = element.getLocalName().contains("reactive");
if (reactive) {
builder = BeanDefinitionBuilder.genericBeanDefinition(ReactiveHttpRequestExecutingMessageHandler.class);
}
else {
builder = BeanDefinitionBuilder.genericBeanDefinition(HttpRequestExecutingMessageHandler.class);
}
BeanDefinitionBuilder builder = getBuilder(element, parserContext);

builder.addPropertyValue("expectReply", false);
HttpAdapterParsingUtils.configureUrlConstructorArg(element, parserContext, builder);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encode-uri");
HttpAdapterParsingUtils.setHttpMethodOrExpression(element, parserContext, builder);

if (reactive) {
String webClientRef = element.getAttribute("web-client");

if (StringUtils.hasText(webClientRef)) {
builder.addConstructorArgReference(webClientRef);
}
}
else {
String restTemplateRef = element.getAttribute("rest-template");

if (StringUtils.hasText(restTemplateRef)) {
HttpAdapterParsingUtils.verifyNoRestTemplateAttributes(element, parserContext);
builder.addConstructorArgReference(restTemplateRef);
}
else {
for (String referenceAttributeName : HttpAdapterParsingUtils.SYNC_REST_TEMPLATE_REFERENCE_ATTRIBUTES) {
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName);
}
}
}

String headerMapper = element.getAttribute("header-mapper");
String mappedRequestHeaders = element.getAttribute("mapped-request-headers");
if (StringUtils.hasText(headerMapper)) {
Expand All @@ -101,4 +73,24 @@ else if (StringUtils.hasText(mappedRequestHeaders)) {
return builder.getBeanDefinition();
}

protected BeanDefinitionBuilder getBuilder(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(HttpRequestExecutingMessageHandler.class);

String restTemplateRef = element.getAttribute("rest-template");

if (StringUtils.hasText(restTemplateRef)) {
HttpAdapterParsingUtils.verifyNoRestTemplateAttributes(element, parserContext);
builder.getBeanDefinition()
.getConstructorArgumentValues()
.addIndexedArgumentValue(1, new RuntimeBeanReference(restTemplateRef));
}
else {
for (String referenceAttributeName : HttpAdapterParsingUtils.SYNC_REST_TEMPLATE_REFERENCE_ATTRIBUTES) {
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName);
}
}
return builder;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

import org.w3c.dom.Element;

import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler;
import org.springframework.integration.http.outbound.ReactiveHttpRequestExecutingMessageHandler;
import org.springframework.util.StringUtils;

/**
Expand All @@ -44,39 +44,12 @@ protected String getInputChannelAttributeName() {

@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder;
boolean reactive = element.getLocalName().contains("reactive");
if (reactive) {
builder = BeanDefinitionBuilder.genericBeanDefinition(ReactiveHttpRequestExecutingMessageHandler.class);
}
else {
builder = BeanDefinitionBuilder.genericBeanDefinition(HttpRequestExecutingMessageHandler.class);
}
BeanDefinitionBuilder builder = getBuilder(element, parserContext);

HttpAdapterParsingUtils.configureUrlConstructorArg(element, parserContext, builder);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encode-uri");
HttpAdapterParsingUtils.setHttpMethodOrExpression(element, parserContext, builder);

if (reactive) {
String webClientRef = element.getAttribute("web-client");
if (StringUtils.hasText(webClientRef)) {
builder.addConstructorArgReference(webClientRef);
}
}
else {
String restTemplateRef = element.getAttribute("rest-template");

if (StringUtils.hasText(restTemplateRef)) {
HttpAdapterParsingUtils.verifyNoRestTemplateAttributes(element, parserContext);
builder.addConstructorArgReference(restTemplateRef);
}
else {
for (String referenceAttributeName : HttpAdapterParsingUtils.SYNC_REST_TEMPLATE_REFERENCE_ATTRIBUTES) {
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName);
}
}
}

String headerMapper = element.getAttribute("header-mapper");
String mappedRequestHeaders = element.getAttribute("mapped-request-headers");
String mappedResponseHeaders = element.getAttribute("mapped-response-headers");
Expand Down Expand Up @@ -113,4 +86,24 @@ protected BeanDefinitionBuilder parseHandler(Element element, ParserContext pars
return builder;
}

protected BeanDefinitionBuilder getBuilder(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(HttpRequestExecutingMessageHandler.class);

String restTemplateRef = element.getAttribute("rest-template");

if (StringUtils.hasText(restTemplateRef)) {
HttpAdapterParsingUtils.verifyNoRestTemplateAttributes(element, parserContext);
builder.getBeanDefinition()
.getConstructorArgumentValues()
.addIndexedArgumentValue(1, new RuntimeBeanReference(restTemplateRef));
}
else {
for (String referenceAttributeName : HttpAdapterParsingUtils.SYNC_REST_TEMPLATE_REFERENCE_ATTRIBUTES) {
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, referenceAttributeName);
}
}
return builder;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public BaseHttpMessageHandlerSpec(E handler) {
this.target.setHeaderMapper(this.headerMapper);
}

S expectReply(boolean expectReply) {
protected S expectReply(boolean expectReply) {
this.target.setExpectReply(expectReply);
return _this();
}
Expand Down
Loading

0 comments on commit 84d60f4

Please sign in to comment.