Skip to content

Commit 11240be

Browse files
artembilangaryrussell
authored andcommitted
GH-2358: Register IntGraphController for WebFlux
Fixes #2358 The WebFlux on the server side can deal with MVC `@Controllers` as well without any Servlet environment. * Enable `IntegrationGraphController` when we not only in the Servlet environment, but also in the WebFlux * Upgrade to SF-5.0.4 and fix WebFlux tests to meet the latest requirements (https://jira.spring.io/browse/SPR-16337) * Move `WEB_FLUX_PRESENT` to the `HttpContextUtils`; deprecate it in the `WebFluxContextUtils` * Mention WebFlux ability for the `IntegrationGraphController` in the `graph.adoc`
1 parent a4130c9 commit 11240be

File tree

10 files changed

+115
-31
lines changed

10 files changed

+115
-31
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ subprojects { subproject ->
138138
springSecurityVersion = '5.0.1.RELEASE'
139139
springSocialTwitterVersion = '1.1.2.RELEASE'
140140
springRetryVersion = '1.2.2.RELEASE'
141-
springVersion = project.hasProperty('springVersion') ? project.springVersion : '5.0.3.RELEASE'
141+
springVersion = project.hasProperty('springVersion') ? project.springVersion : '5.0.4.BUILD-SNAPSHOT'
142142
springWsVersion = '3.0.0.RELEASE'
143143
tomcatVersion = "8.5.23"
144144
xmlUnitVersion = '1.6'

spring-integration-http/src/main/java/org/springframework/integration/http/config/EnableIntegrationGraphController.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016 the original author or authors.
2+
* Copyright 2016-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,13 +28,15 @@
2828
import org.springframework.integration.http.support.HttpContextUtils;
2929

3030
/**
31-
* Enables the {@link IntegrationGraphController} if {@code DispatcherServlet} is present in the classpath.
31+
* Enables the {@link IntegrationGraphController} if
32+
* {@code org.springframework.web.servlet.DispatcherServlet} or
33+
* {@code org.springframework.web.reactive.DispatcherHandler} is present in the classpath.
3234
*
3335
* @author Artem Bilan
3436
*
3537
* @since 4.3
3638
*
37-
* @see IntegrationGraphController
39+
* @see IntegrationGraphController
3840
*/
3941
@Target(ElementType.TYPE)
4042
@Retention(RetentionPolicy.RUNTIME)
@@ -64,6 +66,6 @@
6466
* @return the URLs.
6567
* @since 4.3.5
6668
*/
67-
String[] allowedOrigins() default {};
69+
String[] allowedOrigins() default { };
6870

6971
}

spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrarImportSelector.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,12 +34,13 @@ class IntegrationGraphControllerRegistrarImportSelector implements ImportSelecto
3434

3535
@Override
3636
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
37-
if (HttpContextUtils.WEB_MVC_PRESENT) {
37+
if (HttpContextUtils.WEB_MVC_PRESENT || HttpContextUtils.WEB_FLUX_PRESENT) {
3838
return new String[] { IntegrationGraphControllerRegistrar.class.getName() };
3939
}
4040
else {
4141
logger.warn("The 'IntegrationGraphController' isn't registered with the application context because" +
42-
" there is no 'org.springframework.web.servlet.DispatcherServlet' in the classpath.");
42+
" there is no 'org.springframework.web.servlet.DispatcherServlet' or" +
43+
" 'org.springframework.web.reactive.DispatcherHandler' in the classpath.");
4344
return new String[0];
4445
}
4546
}

spring-integration-http/src/main/java/org/springframework/integration/http/support/HttpContextUtils.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2017 the original author or authors.
2+
* Copyright 2013-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,15 +39,25 @@ private HttpContextUtils() {
3939
}
4040

4141
/**
42-
* The {@code boolean} flag to indicate if the
43-
* {@code org.springframework.web.servlet.DispatcherServlet}
44-
* is present in the CLASSPATH to allow to register the Integration server components,
42+
* A {@code boolean} flag to indicate if the
43+
* {@code org.springframework.web.servlet.DispatcherServlet} is present in the
44+
* CLASSPATH to allow the registration of Integration server components,
4545
* e.g. {@code IntegrationGraphController}.
4646
*/
4747
public static final boolean WEB_MVC_PRESENT =
4848
ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet",
4949
HttpContextUtils.class.getClassLoader());
5050

51+
/**
52+
* A {@code boolean} flag to indicate if the
53+
* {@code org.springframework.web.reactive.DispatcherHandler} is present in the
54+
* CLASSPATH to allow the registration of Integration server reactive components,
55+
* e.g. {@code IntegrationGraphController}.
56+
*/
57+
public static final boolean WEB_FLUX_PRESENT =
58+
ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler",
59+
HttpContextUtils.class.getClassLoader());
60+
5161
/**
5262
* The name for the infrastructure
5363
* {@link org.springframework.integration.http.inbound.IntegrationRequestMappingHandlerMapping} bean.

spring-integration-webflux/src/main/java/org/springframework/integration/webflux/config/WebFluxIntegrationConfigurationInitializer.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 the original author or authors.
2+
* Copyright 2017-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
2828
import org.springframework.beans.factory.support.RootBeanDefinition;
2929
import org.springframework.integration.config.IntegrationConfigurationInitializer;
3030
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
31+
import org.springframework.integration.http.support.HttpContextUtils;
3132
import org.springframework.integration.webflux.inbound.IntegrationHandlerResultHandler;
3233
import org.springframework.integration.webflux.inbound.WebFluxIntegrationRequestMappingHandlerMapping;
3334
import org.springframework.integration.webflux.support.WebFluxContextUtils;
@@ -66,7 +67,7 @@ public void initialize(ConfigurableListableBeanFactory beanFactory) throws Beans
6667
* the HTTP server components.
6768
*/
6869
private void registerReactiveRequestMappingHandlerMappingIfNecessary(BeanDefinitionRegistry registry) {
69-
if (WebFluxContextUtils.WEB_FLUX_PRESENT &&
70+
if (HttpContextUtils.WEB_FLUX_PRESENT &&
7071
!registry.containsBeanDefinition(WebFluxContextUtils.HANDLER_MAPPING_BEAN_NAME)) {
7172
BeanDefinitionBuilder requestMappingBuilder =
7273
BeanDefinitionBuilder.genericBeanDefinition(WebFluxIntegrationRequestMappingHandlerMapping.class);

spring-integration-webflux/src/main/java/org/springframework/integration/webflux/support/WebFluxContextUtils.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package org.springframework.integration.webflux.support;
1818

19-
import org.springframework.util.ClassUtils;
19+
import org.springframework.integration.http.support.HttpContextUtils;
2020

2121
/**
2222
* Utility class for accessing WebFlux integration components
@@ -36,10 +36,11 @@ private WebFluxContextUtils() {
3636
* The {@code boolean} flag to indicate if the
3737
* {@code org.springframework.web.reactive.result.method.RequestMappingInfo}
3838
* is present in the CLASSPATH to allow to register the Integration server reactive components.
39+
* @deprecated since 5.0.2 in favor of {@link HttpContextUtils#WEB_FLUX_PRESENT}.
40+
* Will be removed in the 5.1.
3941
*/
40-
public static final boolean WEB_FLUX_PRESENT =
41-
ClassUtils.isPresent("org.springframework.web.reactive.result.method.RequestMappingInfo",
42-
WebFluxContextUtils.class.getClassLoader());
42+
@Deprecated
43+
public static final boolean WEB_FLUX_PRESENT = HttpContextUtils.WEB_FLUX_PRESENT;
4344

4445
/**
4546
* The name for the infrastructure

spring-integration-webflux/src/test/java/org/springframework/integration/webflux/dsl/WebFluxDslTests.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -129,9 +129,7 @@ public void testWebFluxFlowWithReplyPayloadToFlux() {
129129
response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
130130

131131
DataBufferFactory bufferFactory = response.bufferFactory();
132-
return response.writeWith(
133-
Flux.just(bufferFactory.wrap("FOO".getBytes()),
134-
bufferFactory.wrap("BAR".getBytes())))
132+
return response.writeWith(Mono.just(bufferFactory.wrap("FOO\nBAR\n".getBytes())))
135133
.then(Mono.defer(response::setComplete));
136134
});
137135

@@ -198,7 +196,7 @@ public void testHttpReactiveProxyFlow() throws Exception {
198196
@SuppressWarnings("unchecked")
199197
public void testHttpReactivePost() {
200198
this.webTestClient.post().uri("/reactivePost")
201-
.body(Flux.just("foo", "bar", "baz"), String.class)
199+
.body(Mono.just("foo\nbar\nbaz"), String.class)
202200
.exchange()
203201
.expectStatus().isAccepted();
204202

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.integration.webflux.management;
18+
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
22+
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.context.annotation.Configuration;
24+
import org.springframework.http.MediaType;
25+
import org.springframework.integration.config.EnableIntegration;
26+
import org.springframework.integration.http.config.EnableIntegrationGraphController;
27+
import org.springframework.test.annotation.DirtiesContext;
28+
import org.springframework.test.context.TestPropertySource;
29+
import org.springframework.test.context.junit4.SpringRunner;
30+
import org.springframework.test.context.web.WebAppConfiguration;
31+
import org.springframework.test.web.reactive.server.WebTestClient;
32+
import org.springframework.web.context.WebApplicationContext;
33+
import org.springframework.web.reactive.config.EnableWebFlux;
34+
35+
/**
36+
* @author Artem Bilan
37+
*
38+
* @since 5.0.2
39+
*/
40+
@RunWith(SpringRunner.class)
41+
@WebAppConfiguration
42+
@TestPropertySource(properties = "spring.application.name:testApplication")
43+
@DirtiesContext
44+
public class IntegrationGraphControllerTests {
45+
46+
@Autowired
47+
private WebApplicationContext wac;
48+
49+
@Test
50+
public void testIntegrationGraphGet() {
51+
WebTestClient webTestClient =
52+
WebTestClient.bindToApplicationContext(this.wac)
53+
.build();
54+
55+
webTestClient.get().uri("/testIntegration")
56+
.accept(MediaType.APPLICATION_JSON_UTF8)
57+
.exchange()
58+
.expectStatus().isOk()
59+
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
60+
.expectBody()
61+
.jsonPath("$.nodes..name").isArray()
62+
.jsonPath("$.contentDescriptor.name").isEqualTo("testApplication")
63+
.jsonPath("$.links").exists();
64+
}
65+
66+
@Configuration
67+
@EnableWebFlux
68+
@EnableIntegration
69+
@EnableIntegrationGraphController(path = "/testIntegration")
70+
public static class ContextConfiguration {
71+
72+
}
73+
74+
}

spring-integration-webflux/src/test/java/org/springframework/integration/webflux/outbound/WebFluxRequestExecutingMessageHandlerTests.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 the original author or authors.
2+
* Copyright 2017-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -198,10 +198,7 @@ public void testFluxReply() {
198198

199199
DataBufferFactory bufferFactory = response.bufferFactory();
200200

201-
Flux<DataBuffer> data =
202-
Flux.just(bufferFactory.wrap("foo".getBytes()),
203-
bufferFactory.wrap("bar".getBytes()),
204-
bufferFactory.wrap("baz".getBytes()));
201+
Mono<DataBuffer> data = Mono.just(bufferFactory.wrap("foo\nbar\nbaz".getBytes()));
205202

206203
return response.writeWith(data)
207204
.then(Mono.defer(response::setComplete));

src/reference/asciidoc/graph.adoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ See also <<programming-tips>> for more information.
202202

203203
=== Integration Graph Controller
204204

205-
If your application is WEB-based (or built on top of Spring Boot using an embedded web container) and the Spring Integration HTTP module (see <<http>>) is present on the classpath, you can use a `IntegrationGraphController` to expose the `IntegrationGraphServer` functionality as a REST service.
205+
If your application is WEB-based (or built on top of Spring Boot using an embedded web container) and the Spring Integration HTTP or WebFlux module (see <<http>> and <<webflux>>) is present on the classpath, you can use a `IntegrationGraphController` to expose the `IntegrationGraphServer` functionality as a REST service.
206206
For this purpose, the `@EnableIntegrationGraphController` `@Configuration` class annotation and the `<int-http:graph-controller/>` XML element, are available in the HTTP module.
207207
Together with the `@EnableWebMvc` annotation (or `<mvc:annotation-driven/>` for xml definitions), this configuration registers an `IntegrationGraphController` `@RestController` where its `@RequestMapping.path` can be configured on the `@EnableIntegrationGraphController` annotation or `<int-http:graph-controller/>` element.
208208
The default path is `/integration`.
@@ -242,8 +242,8 @@ For more sophistication, you can configure the CORS mappings using standard Spri
242242
[source,java]
243243
----
244244
@Configuration
245-
@EnableWebMvc
246-
@EnableWebSecurity
245+
@EnableWebMvc // or @EnableWebFlux
246+
@EnableWebSecurity // or @EnableWebFluxSecurity
247247
@EnableIntegration
248248
@EnableIntegrationGraphController(path = "/testIntegration", allowedOrigins="http://localhost:9090")
249249
public class IntegrationConfiguration extends WebSecurityConfigurerAdapter {

0 commit comments

Comments
 (0)