Fix CORS registration for IntGraphController
We fail with `NoClassDefFoundError` when we use `@EnableIntegrationGraphController` in WebFlux env without Spring MVC. Another issue that we don't register CORS for WebFlux * Extract top-level package protected classes for MVC and WebFlux to register CORS in the appropriate environment according classpath * Adjust `HttpIntegrationConfigurationInitializer` and `WebFluxIntegrationConfigurationInitializer` for native compatibility * Add `@Indexed` for `@MessagingGateway` for indexer support in Spring Boot and Spring Native **Cherry-pick to `5.4.x` & `5.3.x`**
This commit is contained in:
@@ -537,6 +537,7 @@ project('spring-integration-http') {
|
||||
api 'org.springframework:spring-webmvc'
|
||||
providedImplementation "javax.servlet:javax.servlet-api:$servletApiVersion"
|
||||
optionalApi "com.rometools:rome:$romeToolsVersion"
|
||||
optionalApi 'org.springframework:spring-webflux'
|
||||
|
||||
testImplementation project(':spring-integration-security')
|
||||
testImplementation "org.hamcrest:hamcrest-core:$hamcrestVersion"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -22,6 +22,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.stereotype.Indexed;
|
||||
|
||||
/**
|
||||
* A stereotype annotation to provide an Integration Messaging Gateway Proxy
|
||||
* ({@code <gateway/>}) as an abstraction over the messaging API. The target
|
||||
@@ -44,6 +46,7 @@ import java.lang.annotation.Target;
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Indexed
|
||||
public @interface MessagingGateway {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2020 the original author or authors.
|
||||
* Copyright 2014-2021 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.
|
||||
@@ -25,7 +25,6 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.integration.config.IntegrationConfigurationInitializer;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.http.inbound.IntegrationRequestMappingHandlerMapping;
|
||||
|
||||
/**
|
||||
@@ -55,8 +54,7 @@ public class HttpIntegrationConfigurationInitializer implements IntegrationConfi
|
||||
* which could also be overridden by the user by simply registering
|
||||
* a {@link IntegrationRequestMappingHandlerMapping} {@code <bean>} with 'id'
|
||||
* {@link HttpContextUtils#HANDLER_MAPPING_BEAN_NAME}.
|
||||
* <p>
|
||||
* In addition, checks if the {@code javax.servlet.Servlet} class is present on the classpath.
|
||||
* <p> In addition, checks if the {@code javax.servlet.Servlet} 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.
|
||||
*/
|
||||
@@ -64,9 +62,14 @@ public class HttpIntegrationConfigurationInitializer implements IntegrationConfi
|
||||
if (HttpContextUtils.WEB_MVC_PRESENT &&
|
||||
!registry.containsBeanDefinition(HttpContextUtils.HANDLER_MAPPING_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder requestMappingBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationRequestMappingHandlerMapping.class);
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationRequestMappingHandlerMapping.class,
|
||||
() -> {
|
||||
IntegrationRequestMappingHandlerMapping mapping =
|
||||
new IntegrationRequestMappingHandlerMapping();
|
||||
mapping.setOrder(0);
|
||||
return mapping;
|
||||
});
|
||||
requestMappingBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
requestMappingBuilder.addPropertyValue(IntegrationNamespaceUtils.ORDER, 0);
|
||||
registry.registerBeanDefinition(HttpContextUtils.HANDLER_MAPPING_BEAN_NAME,
|
||||
requestMappingBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
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.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
@@ -43,8 +44,6 @@ import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.graph.IntegrationGraphServer;
|
||||
import org.springframework.integration.http.management.IntegrationGraphController;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* Registers the necessary beans for {@link EnableIntegrationGraphController}.
|
||||
@@ -54,7 +53,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
class IntegrationGraphControllerRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
public class IntegrationGraphControllerRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog(IntegrationGraphControllerRegistrar.class);
|
||||
|
||||
@@ -81,10 +80,21 @@ class IntegrationGraphControllerRegistrar implements ImportBeanDefinitionRegistr
|
||||
String path = (String) annotationAttributes.get("value");
|
||||
String[] allowedOrigins = (String[]) annotationAttributes.get("allowedOrigins");
|
||||
if (allowedOrigins != null && allowedOrigins.length > 0) {
|
||||
AbstractBeanDefinition controllerCorsConfigurer =
|
||||
new RootBeanDefinition(IntegrationGraphCorsConfigurer.class,
|
||||
() -> new IntegrationGraphCorsConfigurer(path, allowedOrigins));
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(controllerCorsConfigurer, registry);
|
||||
AbstractBeanDefinition controllerCorsConfigurer = null;
|
||||
if (HttpContextUtils.WEB_MVC_PRESENT) {
|
||||
controllerCorsConfigurer = webMvcControllerCorsConfigurerBean(path, allowedOrigins);
|
||||
}
|
||||
else if (HttpContextUtils.WEB_FLUX_PRESENT) {
|
||||
controllerCorsConfigurer = webFluxControllerCorsConfigurerBean(path, allowedOrigins);
|
||||
}
|
||||
|
||||
if (controllerCorsConfigurer != null) {
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(controllerCorsConfigurer, registry);
|
||||
}
|
||||
else {
|
||||
LOGGER.warn("Nor Spring MVC, neither WebFlux is present to configure CORS origins " +
|
||||
"for Integration Graph Controller.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!registry.containsBeanDefinition(HttpContextUtils.GRAPH_CONTROLLER_BEAN_NAME)) {
|
||||
@@ -107,7 +117,22 @@ class IntegrationGraphControllerRegistrar implements ImportBeanDefinitionRegistr
|
||||
}
|
||||
}
|
||||
|
||||
private static final class GraphControllerPropertiesPopulator implements BeanFactoryPostProcessor, EnvironmentAware {
|
||||
private static AbstractBeanDefinition webMvcControllerCorsConfigurerBean(String path, String[] allowedOrigins) {
|
||||
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
||||
beanDefinition.setBeanClass(WebMvcIntegrationGraphCorsConfigurer.class);
|
||||
beanDefinition.setInstanceSupplier(() -> new WebMvcIntegrationGraphCorsConfigurer(path, allowedOrigins));
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
private static AbstractBeanDefinition webFluxControllerCorsConfigurerBean(String path, String[] allowedOrigins) {
|
||||
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
||||
beanDefinition.setBeanClass(WebFluxIntegrationGraphCorsConfigurer.class);
|
||||
beanDefinition.setInstanceSupplier(() -> new WebFluxIntegrationGraphCorsConfigurer(path, allowedOrigins));
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
private static final class GraphControllerPropertiesPopulator
|
||||
implements BeanFactoryPostProcessor, EnvironmentAware {
|
||||
|
||||
private final Map<String, Object> properties = new HashMap<>();
|
||||
|
||||
@@ -131,22 +156,4 @@ class IntegrationGraphControllerRegistrar implements ImportBeanDefinitionRegistr
|
||||
|
||||
}
|
||||
|
||||
private static final class IntegrationGraphCorsConfigurer implements WebMvcConfigurer {
|
||||
|
||||
private final String path;
|
||||
|
||||
private final String[] allowedOrigins;
|
||||
|
||||
private IntegrationGraphCorsConfigurer(String path, String[] allowedOrigins) { // NOSONAR
|
||||
this.path = path;
|
||||
this.allowedOrigins = allowedOrigins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping(this.path).allowedOrigins(this.allowedOrigins).allowedMethods("GET");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2021 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
|
||||
*
|
||||
* https://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.http.config;
|
||||
|
||||
import org.springframework.web.reactive.config.CorsRegistry;
|
||||
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
||||
|
||||
/**
|
||||
* The {@link WebFluxConfigurer} implementation for CORS mapping on the Integration Graph Controller.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 5.3.9
|
||||
*
|
||||
* @see EnableIntegrationGraphController
|
||||
*/
|
||||
final class WebFluxIntegrationGraphCorsConfigurer implements WebFluxConfigurer {
|
||||
|
||||
private final String path;
|
||||
|
||||
private final String[] allowedOrigins;
|
||||
|
||||
WebFluxIntegrationGraphCorsConfigurer(String path, String[] allowedOrigins) { // NOSONAR
|
||||
this.path = path;
|
||||
this.allowedOrigins = allowedOrigins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping(this.path).allowedOrigins(this.allowedOrigins).allowedMethods("GET");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2021 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
|
||||
*
|
||||
* https://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.http.config;
|
||||
|
||||
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* The {@link WebMvcConfigurer} implementation for CORS mapping on the Integration Graph Controller.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 5.3.9
|
||||
*
|
||||
* @see EnableIntegrationGraphController
|
||||
*/
|
||||
final class WebMvcIntegrationGraphCorsConfigurer implements WebMvcConfigurer {
|
||||
|
||||
private final String path;
|
||||
|
||||
private final String[] allowedOrigins;
|
||||
|
||||
WebMvcIntegrationGraphCorsConfigurer(String path, String[] allowedOrigins) { // NOSONAR
|
||||
this.path = path;
|
||||
this.allowedOrigins = allowedOrigins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping(this.path).allowedOrigins(this.allowedOrigins).allowedMethods("GET");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2020 the original author or authors.
|
||||
* Copyright 2017-2021 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.
|
||||
@@ -27,7 +27,6 @@ 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.config.HttpContextUtils;
|
||||
import org.springframework.integration.webflux.inbound.IntegrationHandlerResultHandler;
|
||||
import org.springframework.integration.webflux.inbound.WebFluxIntegrationRequestMappingHandlerMapping;
|
||||
@@ -69,15 +68,22 @@ public class WebFluxIntegrationConfigurationInitializer implements IntegrationCo
|
||||
private void registerReactiveRequestMappingHandlerMappingIfNecessary(BeanDefinitionRegistry registry) {
|
||||
if (HttpContextUtils.WEB_FLUX_PRESENT &&
|
||||
!registry.containsBeanDefinition(WebFluxContextUtils.HANDLER_MAPPING_BEAN_NAME)) {
|
||||
|
||||
BeanDefinitionBuilder requestMappingBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(WebFluxIntegrationRequestMappingHandlerMapping.class);
|
||||
BeanDefinitionBuilder.genericBeanDefinition(WebFluxIntegrationRequestMappingHandlerMapping.class,
|
||||
() -> {
|
||||
WebFluxIntegrationRequestMappingHandlerMapping mapping =
|
||||
new WebFluxIntegrationRequestMappingHandlerMapping();
|
||||
mapping.setOrder(0);
|
||||
return mapping;
|
||||
});
|
||||
requestMappingBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
requestMappingBuilder.addPropertyValue(IntegrationNamespaceUtils.ORDER, 0);
|
||||
registry.registerBeanDefinition(WebFluxContextUtils.HANDLER_MAPPING_BEAN_NAME,
|
||||
requestMappingBuilder.getBeanDefinition());
|
||||
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(
|
||||
new RootBeanDefinition(IntegrationHandlerResultHandler.class), registry);
|
||||
new RootBeanDefinition(IntegrationHandlerResultHandler.class, IntegrationHandlerResultHandler::new),
|
||||
registry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user