GH-2358: Register IntGraphController for WebFlux
Fixes https://github.com/spring-projects/spring-integration/issues/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`
This commit is contained in:
committed by
Gary Russell
parent
a4130c9e59
commit
11240be555
@@ -138,7 +138,7 @@ subprojects { subproject ->
|
||||
springSecurityVersion = '5.0.1.RELEASE'
|
||||
springSocialTwitterVersion = '1.1.2.RELEASE'
|
||||
springRetryVersion = '1.2.2.RELEASE'
|
||||
springVersion = project.hasProperty('springVersion') ? project.springVersion : '5.0.3.RELEASE'
|
||||
springVersion = project.hasProperty('springVersion') ? project.springVersion : '5.0.4.BUILD-SNAPSHOT'
|
||||
springWsVersion = '3.0.0.RELEASE'
|
||||
tomcatVersion = "8.5.23"
|
||||
xmlUnitVersion = '1.6'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2018 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.
|
||||
@@ -28,13 +28,15 @@ import org.springframework.integration.http.management.IntegrationGraphControlle
|
||||
import org.springframework.integration.http.support.HttpContextUtils;
|
||||
|
||||
/**
|
||||
* Enables the {@link IntegrationGraphController} if {@code DispatcherServlet} is present in the classpath.
|
||||
* Enables the {@link IntegrationGraphController} if
|
||||
* {@code org.springframework.web.servlet.DispatcherServlet} or
|
||||
* {@code org.springframework.web.reactive.DispatcherHandler} is present in the classpath.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 4.3
|
||||
*
|
||||
* @see IntegrationGraphController
|
||||
* @see IntegrationGraphController
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -64,6 +66,6 @@ public @interface EnableIntegrationGraphController {
|
||||
* @return the URLs.
|
||||
* @since 4.3.5
|
||||
*/
|
||||
String[] allowedOrigins() default {};
|
||||
String[] allowedOrigins() default { };
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2016-2018 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.
|
||||
@@ -34,12 +34,13 @@ class IntegrationGraphControllerRegistrarImportSelector implements ImportSelecto
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
if (HttpContextUtils.WEB_MVC_PRESENT) {
|
||||
if (HttpContextUtils.WEB_MVC_PRESENT || HttpContextUtils.WEB_FLUX_PRESENT) {
|
||||
return new String[] { IntegrationGraphControllerRegistrar.class.getName() };
|
||||
}
|
||||
else {
|
||||
logger.warn("The 'IntegrationGraphController' isn't registered with the application context because" +
|
||||
" there is no 'org.springframework.web.servlet.DispatcherServlet' in the classpath.");
|
||||
" there is no 'org.springframework.web.servlet.DispatcherServlet' or" +
|
||||
" 'org.springframework.web.reactive.DispatcherHandler' in the classpath.");
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
* Copyright 2013-2018 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.
|
||||
@@ -39,15 +39,25 @@ public final class HttpContextUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@code boolean} flag to indicate if the
|
||||
* {@code org.springframework.web.servlet.DispatcherServlet}
|
||||
* is present in the CLASSPATH to allow to register the Integration server components,
|
||||
* A {@code boolean} flag to indicate if the
|
||||
* {@code org.springframework.web.servlet.DispatcherServlet} is present in the
|
||||
* CLASSPATH to allow the registration of Integration server components,
|
||||
* e.g. {@code IntegrationGraphController}.
|
||||
*/
|
||||
public static final boolean WEB_MVC_PRESENT =
|
||||
ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet",
|
||||
HttpContextUtils.class.getClassLoader());
|
||||
|
||||
/**
|
||||
* A {@code boolean} flag to indicate if the
|
||||
* {@code org.springframework.web.reactive.DispatcherHandler} is present in the
|
||||
* CLASSPATH to allow the registration of Integration server reactive components,
|
||||
* e.g. {@code IntegrationGraphController}.
|
||||
*/
|
||||
public static final boolean WEB_FLUX_PRESENT =
|
||||
ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler",
|
||||
HttpContextUtils.class.getClassLoader());
|
||||
|
||||
/**
|
||||
* The name for the infrastructure
|
||||
* {@link org.springframework.integration.http.inbound.IntegrationRequestMappingHandlerMapping} bean.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2017-2018 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.
|
||||
@@ -28,6 +28,7 @@ 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.support.HttpContextUtils;
|
||||
import org.springframework.integration.webflux.inbound.IntegrationHandlerResultHandler;
|
||||
import org.springframework.integration.webflux.inbound.WebFluxIntegrationRequestMappingHandlerMapping;
|
||||
import org.springframework.integration.webflux.support.WebFluxContextUtils;
|
||||
@@ -66,7 +67,7 @@ public class WebFluxIntegrationConfigurationInitializer implements IntegrationCo
|
||||
* the HTTP server components.
|
||||
*/
|
||||
private void registerReactiveRequestMappingHandlerMappingIfNecessary(BeanDefinitionRegistry registry) {
|
||||
if (WebFluxContextUtils.WEB_FLUX_PRESENT &&
|
||||
if (HttpContextUtils.WEB_FLUX_PRESENT &&
|
||||
!registry.containsBeanDefinition(WebFluxContextUtils.HANDLER_MAPPING_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder requestMappingBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(WebFluxIntegrationRequestMappingHandlerMapping.class);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.integration.webflux.support;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.integration.http.support.HttpContextUtils;
|
||||
|
||||
/**
|
||||
* Utility class for accessing WebFlux integration components
|
||||
@@ -36,10 +36,11 @@ public final class WebFluxContextUtils {
|
||||
* The {@code boolean} flag to indicate if the
|
||||
* {@code org.springframework.web.reactive.result.method.RequestMappingInfo}
|
||||
* is present in the CLASSPATH to allow to register the Integration server reactive components.
|
||||
* @deprecated since 5.0.2 in favor of {@link HttpContextUtils#WEB_FLUX_PRESENT}.
|
||||
* Will be removed in the 5.1.
|
||||
*/
|
||||
public static final boolean WEB_FLUX_PRESENT =
|
||||
ClassUtils.isPresent("org.springframework.web.reactive.result.method.RequestMappingInfo",
|
||||
WebFluxContextUtils.class.getClassLoader());
|
||||
@Deprecated
|
||||
public static final boolean WEB_FLUX_PRESENT = HttpContextUtils.WEB_FLUX_PRESENT;
|
||||
|
||||
/**
|
||||
* The name for the infrastructure
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2017 the original author or authors.
|
||||
* Copyright 2016-2018 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.
|
||||
@@ -129,9 +129,7 @@ public class WebFluxDslTests {
|
||||
response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
|
||||
|
||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
||||
return response.writeWith(
|
||||
Flux.just(bufferFactory.wrap("FOO".getBytes()),
|
||||
bufferFactory.wrap("BAR".getBytes())))
|
||||
return response.writeWith(Mono.just(bufferFactory.wrap("FOO\nBAR\n".getBytes())))
|
||||
.then(Mono.defer(response::setComplete));
|
||||
});
|
||||
|
||||
@@ -198,7 +196,7 @@ public class WebFluxDslTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testHttpReactivePost() {
|
||||
this.webTestClient.post().uri("/reactivePost")
|
||||
.body(Flux.just("foo", "bar", "baz"), String.class)
|
||||
.body(Mono.just("foo\nbar\nbaz"), String.class)
|
||||
.exchange()
|
||||
.expectStatus().isAccepted();
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.webflux.management;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.http.config.EnableIntegrationGraphController;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.reactive.config.EnableWebFlux;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 5.0.2
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@TestPropertySource(properties = "spring.application.name:testApplication")
|
||||
@DirtiesContext
|
||||
public class IntegrationGraphControllerTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext wac;
|
||||
|
||||
@Test
|
||||
public void testIntegrationGraphGet() {
|
||||
WebTestClient webTestClient =
|
||||
WebTestClient.bindToApplicationContext(this.wac)
|
||||
.build();
|
||||
|
||||
webTestClient.get().uri("/testIntegration")
|
||||
.accept(MediaType.APPLICATION_JSON_UTF8)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||
.expectBody()
|
||||
.jsonPath("$.nodes..name").isArray()
|
||||
.jsonPath("$.contentDescriptor.name").isEqualTo("testApplication")
|
||||
.jsonPath("$.links").exists();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebFlux
|
||||
@EnableIntegration
|
||||
@EnableIntegrationGraphController(path = "/testIntegration")
|
||||
public static class ContextConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2017-2018 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.
|
||||
@@ -198,10 +198,7 @@ public class WebFluxRequestExecutingMessageHandlerTests {
|
||||
|
||||
DataBufferFactory bufferFactory = response.bufferFactory();
|
||||
|
||||
Flux<DataBuffer> data =
|
||||
Flux.just(bufferFactory.wrap("foo".getBytes()),
|
||||
bufferFactory.wrap("bar".getBytes()),
|
||||
bufferFactory.wrap("baz".getBytes()));
|
||||
Mono<DataBuffer> data = Mono.just(bufferFactory.wrap("foo\nbar\nbaz".getBytes()));
|
||||
|
||||
return response.writeWith(data)
|
||||
.then(Mono.defer(response::setComplete));
|
||||
|
||||
@@ -202,7 +202,7 @@ See also <<programming-tips>> for more information.
|
||||
|
||||
=== Integration Graph Controller
|
||||
|
||||
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.
|
||||
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.
|
||||
For this purpose, the `@EnableIntegrationGraphController` `@Configuration` class annotation and the `<int-http:graph-controller/>` XML element, are available in the HTTP module.
|
||||
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.
|
||||
The default path is `/integration`.
|
||||
@@ -242,8 +242,8 @@ For more sophistication, you can configure the CORS mappings using standard Spri
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@EnableWebMvc // or @EnableWebFlux
|
||||
@EnableWebSecurity // or @EnableWebFluxSecurity
|
||||
@EnableIntegration
|
||||
@EnableIntegrationGraphController(path = "/testIntegration", allowedOrigins="http://localhost:9090")
|
||||
public class IntegrationConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
Reference in New Issue
Block a user