Functional gateway bean definitions
* Rework `MessagingGatewayRegistrar` to parse messaging gateway annotation an `<gateway>` XML using a supplier variant for bean definition. Such a feature is required by Spring Native - otherwise we would need to register reflection info for to many internal Spring Integration classes * Such a change should benefit from regular JDK perspective, too - we don't do reflection for this kind of bean registrations
This commit is contained in:
committed by
Gary Russell
parent
1ac163330e
commit
db4f120dac
@@ -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.
|
||||
@@ -18,30 +18,39 @@ package org.springframework.integration.config;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.EmbeddedValueResolver;
|
||||
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.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.annotation.AnnotationConstants;
|
||||
import org.springframework.integration.annotation.MessagingGateway;
|
||||
import org.springframework.integration.gateway.GatewayMethodMetadata;
|
||||
import org.springframework.integration.gateway.GatewayProxyFactoryBean;
|
||||
import org.springframework.integration.gateway.MethodArgsMessageMapper;
|
||||
import org.springframework.integration.util.MessagingAnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -58,6 +67,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class MessagingGatewayRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
private static final String PROXY_DEFAULT_METHODS_ATTR = "proxyDefaultMethods";
|
||||
|
||||
@Override
|
||||
@@ -72,11 +83,14 @@ public class MessagingGatewayRegistrar implements ImportBeanDefinitionRegistrar
|
||||
annotationAttributes.put("serviceInterface", importingClassMetadata.getClassName());
|
||||
annotationAttributes.put(PROXY_DEFAULT_METHODS_ATTR,
|
||||
"" + annotationAttributes.remove(PROXY_DEFAULT_METHODS_ATTR));
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(parse(annotationAttributes), registry);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(gatewayProxyBeanDefinition(annotationAttributes, registry),
|
||||
registry);
|
||||
}
|
||||
}
|
||||
|
||||
public BeanDefinitionHolder parse(Map<String, Object> gatewayAttributes) { // NOSONAR complexity
|
||||
public BeanDefinitionHolder gatewayProxyBeanDefinition(Map<String, Object> gatewayAttributes,
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
String defaultPayloadExpression = (String) gatewayAttributes.get("defaultPayloadExpression");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -98,91 +112,145 @@ public class MessagingGatewayRegistrar implements ImportBeanDefinitionRegistrar
|
||||
Assert.state(!hasMapper || !hasDefaultHeaders,
|
||||
"'defaultHeaders' are not allowed when a 'mapper' is provided");
|
||||
|
||||
BeanDefinitionBuilder gatewayProxyBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(GatewayProxyFactoryBean.class);
|
||||
ConfigurableBeanFactory beanFactory = obtainBeanFactory(registry);
|
||||
EmbeddedValueResolver embeddedValueResolver = new EmbeddedValueResolver(beanFactory);
|
||||
Class<?> serviceInterface = getServiceInterface((String) gatewayAttributes.get("serviceInterface"), beanFactory);
|
||||
|
||||
if (hasDefaultHeaders || hasDefaultPayloadExpression) {
|
||||
BeanDefinitionBuilder methodMetadataBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(GatewayMethodMetadata.class);
|
||||
|
||||
if (hasDefaultPayloadExpression) {
|
||||
methodMetadataBuilder.addPropertyValue("payloadExpression",
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
|
||||
.addConstructorArgValue(defaultPayloadExpression)
|
||||
.getBeanDefinition());
|
||||
}
|
||||
|
||||
if (hasDefaultHeaders) {
|
||||
Map<String, Object> headerExpressions = new ManagedMap<>();
|
||||
for (Map<String, Object> header : defaultHeaders) {
|
||||
String headerValue = (String) header.get("value");
|
||||
String headerExpression = (String) header.get("expression");
|
||||
boolean hasValue = StringUtils.hasText(headerValue);
|
||||
|
||||
if (hasValue == StringUtils.hasText(headerExpression)) {
|
||||
throw new BeanDefinitionStoreException("exactly one of 'value' or 'expression' " +
|
||||
"is required on a gateway's header.");
|
||||
@SuppressWarnings("unchecked")
|
||||
AbstractBeanDefinition beanDefinition = new RootBeanDefinition(GatewayProxyFactoryBean.class,
|
||||
() -> {
|
||||
GatewayProxyFactoryBean proxyFactoryBean = new GatewayProxyFactoryBean(serviceInterface);
|
||||
if (StringUtils.hasText(defaultRequestChannel)) {
|
||||
proxyFactoryBean.setDefaultRequestChannelName(defaultRequestChannel);
|
||||
}
|
||||
if (StringUtils.hasText(defaultReplyChannel)) {
|
||||
proxyFactoryBean.setDefaultReplyChannelName(defaultReplyChannel);
|
||||
}
|
||||
if (StringUtils.hasText(errorChannel)) {
|
||||
proxyFactoryBean.setErrorChannelName(errorChannel);
|
||||
}
|
||||
if (StringUtils.hasText(proxyDefaultMethods)) {
|
||||
boolean actualProxyDefaultMethods =
|
||||
Boolean.parseBoolean(embeddedValueResolver.resolveStringValue(proxyDefaultMethods));
|
||||
proxyFactoryBean.setProxyDefaultMethods(actualProxyDefaultMethods);
|
||||
}
|
||||
if (StringUtils.hasText(mapper)) {
|
||||
proxyFactoryBean.setMapper(beanFactory.getBean(mapper, MethodArgsMessageMapper.class));
|
||||
}
|
||||
|
||||
BeanDefinition expressionDef =
|
||||
new RootBeanDefinition(hasValue ? LiteralExpression.class : ExpressionFactoryBean.class);
|
||||
expressionDef.getConstructorArgumentValues()
|
||||
.addGenericArgumentValue(hasValue ? headerValue : headerExpression);
|
||||
if (asyncExecutor == null || AnnotationConstants.NULL.equals(asyncExecutor)) {
|
||||
proxyFactoryBean.setAsyncExecutor(null);
|
||||
}
|
||||
else if (StringUtils.hasText(asyncExecutor)) {
|
||||
proxyFactoryBean.setAsyncExecutor(beanFactory.getBean(asyncExecutor, Executor.class));
|
||||
}
|
||||
|
||||
headerExpressions.put((String) header.get("name"), expressionDef);
|
||||
}
|
||||
methodMetadataBuilder.addPropertyValue("headerExpressions", headerExpressions);
|
||||
}
|
||||
if (hasDefaultHeaders || hasDefaultPayloadExpression) {
|
||||
GatewayMethodMetadata globalMethodMetadata =
|
||||
createGlobalMethodMetadata(defaultPayloadExpression, defaultHeaders,
|
||||
hasDefaultPayloadExpression, hasDefaultHeaders, embeddedValueResolver);
|
||||
proxyFactoryBean.setGlobalMethodMetadata(globalMethodMetadata);
|
||||
}
|
||||
|
||||
gatewayProxyBuilder.addPropertyValue("globalMethodMetadata", methodMetadataBuilder.getBeanDefinition());
|
||||
}
|
||||
Map<String, AbstractBeanDefinition> methodDefinitions =
|
||||
(Map<String, AbstractBeanDefinition>) gatewayAttributes.get("methods");
|
||||
|
||||
if (methodDefinitions != null) {
|
||||
Map<String, GatewayMethodMetadata> methodMetadataMap =
|
||||
methodDefinitions.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Entry::getKey,
|
||||
entry -> (GatewayMethodMetadata) entry.getValue().getInstanceSupplier().get()));
|
||||
|
||||
if (StringUtils.hasText(defaultRequestChannel)) {
|
||||
gatewayProxyBuilder.addPropertyValue("defaultRequestChannelName", defaultRequestChannel);
|
||||
}
|
||||
if (StringUtils.hasText(defaultReplyChannel)) {
|
||||
gatewayProxyBuilder.addPropertyValue("defaultReplyChannelName", defaultReplyChannel);
|
||||
}
|
||||
if (StringUtils.hasText(errorChannel)) {
|
||||
gatewayProxyBuilder.addPropertyValue("errorChannelName", errorChannel);
|
||||
}
|
||||
if (asyncExecutor == null || AnnotationConstants.NULL.equals(asyncExecutor)) {
|
||||
gatewayProxyBuilder.addPropertyValue("asyncExecutor", null);
|
||||
}
|
||||
else if (StringUtils.hasText(asyncExecutor)) {
|
||||
gatewayProxyBuilder.addPropertyReference("asyncExecutor", asyncExecutor);
|
||||
}
|
||||
if (StringUtils.hasText(mapper)) {
|
||||
gatewayProxyBuilder.addPropertyReference("mapper", mapper);
|
||||
}
|
||||
if (StringUtils.hasText(proxyDefaultMethods)) {
|
||||
gatewayProxyBuilder.addPropertyValue(PROXY_DEFAULT_METHODS_ATTR, proxyDefaultMethods);
|
||||
}
|
||||
proxyFactoryBean.setMethodMetadataMap(methodMetadataMap);
|
||||
}
|
||||
|
||||
gatewayProxyBuilder.addPropertyValue("defaultRequestTimeoutExpressionString",
|
||||
gatewayAttributes.get("defaultRequestTimeout"));
|
||||
gatewayProxyBuilder.addPropertyValue("defaultReplyTimeoutExpressionString",
|
||||
gatewayAttributes.get("defaultReplyTimeout"));
|
||||
gatewayProxyBuilder.addPropertyValue("methodMetadataMap", gatewayAttributes.get("methods"));
|
||||
String actualDefaultRequestTimeout =
|
||||
embeddedValueResolver.resolveStringValue(
|
||||
(String) gatewayAttributes.get("defaultRequestTimeout"));
|
||||
if (actualDefaultRequestTimeout != null) {
|
||||
proxyFactoryBean.setDefaultRequestTimeoutExpressionString(actualDefaultRequestTimeout);
|
||||
}
|
||||
String actualDefaultReplyTimeout =
|
||||
embeddedValueResolver.resolveStringValue(
|
||||
(String) gatewayAttributes.get("defaultReplyTimeout"));
|
||||
if (actualDefaultReplyTimeout != null) {
|
||||
proxyFactoryBean.setDefaultReplyTimeoutExpressionString(actualDefaultReplyTimeout);
|
||||
}
|
||||
return proxyFactoryBean;
|
||||
});
|
||||
|
||||
|
||||
String serviceInterface = (String) gatewayAttributes.get("serviceInterface");
|
||||
if (!StringUtils.hasText(serviceInterface)) {
|
||||
serviceInterface = "org.springframework.integration.gateway.RequestReplyExchanger";
|
||||
}
|
||||
String id = (String) gatewayAttributes.get("name");
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = Introspector.decapitalize(serviceInterface.substring(serviceInterface.lastIndexOf('.') + 1));
|
||||
String serviceInterfaceName = serviceInterface.getName();
|
||||
id = Introspector.decapitalize(serviceInterfaceName.substring(serviceInterfaceName.lastIndexOf('.') + 1));
|
||||
}
|
||||
|
||||
gatewayProxyBuilder.addConstructorArgValue(serviceInterface);
|
||||
|
||||
AbstractBeanDefinition beanDefinition = gatewayProxyBuilder.getBeanDefinition();
|
||||
beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, serviceInterface);
|
||||
return new BeanDefinitionHolder(beanDefinition, id);
|
||||
}
|
||||
|
||||
private static ConfigurableBeanFactory obtainBeanFactory(BeanDefinitionRegistry registry) {
|
||||
if (registry instanceof ConfigurableBeanFactory) {
|
||||
return (ConfigurableBeanFactory) registry;
|
||||
}
|
||||
else if (registry instanceof ConfigurableApplicationContext) {
|
||||
return ((ConfigurableApplicationContext) registry).getBeanFactory();
|
||||
}
|
||||
throw new IllegalArgumentException("The provided 'BeanDefinitionRegistry' must be an instance " +
|
||||
"of 'ConfigurableBeanFactory' or 'ConfigurableApplicationContext', but given is: "
|
||||
+ registry.getClass());
|
||||
}
|
||||
|
||||
private static Class<?> getServiceInterface(String serviceInterface, ConfigurableBeanFactory beanFactory) {
|
||||
String actualServiceInterface = beanFactory.resolveEmbeddedValue(serviceInterface);
|
||||
if (!StringUtils.hasText(actualServiceInterface)) {
|
||||
return org.springframework.integration.gateway.RequestReplyExchanger.class;
|
||||
}
|
||||
try {
|
||||
return ClassUtils.forName(actualServiceInterface, beanFactory.getBeanClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new BeanDefinitionStoreException("Cannot parse class for service interface", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static GatewayMethodMetadata createGlobalMethodMetadata(String defaultPayloadExpression,
|
||||
Map<String, Object>[] defaultHeaders, boolean hasDefaultPayloadExpression,
|
||||
boolean hasDefaultHeaders, EmbeddedValueResolver embeddedValueResolver) {
|
||||
|
||||
GatewayMethodMetadata gatewayMethodMetadata = new GatewayMethodMetadata();
|
||||
|
||||
if (hasDefaultPayloadExpression) {
|
||||
String actualPayloadExpression = embeddedValueResolver.resolveStringValue(defaultPayloadExpression);
|
||||
gatewayMethodMetadata.setPayloadExpression(EXPRESSION_PARSER.parseExpression(actualPayloadExpression));
|
||||
}
|
||||
|
||||
if (hasDefaultHeaders) {
|
||||
Map<String, Expression> headerExpressions = new HashMap<>();
|
||||
for (Map<String, Object> header : defaultHeaders) {
|
||||
String headerValue = (String) header.get("value");
|
||||
String headerExpression = (String) header.get("expression");
|
||||
boolean hasValue = StringUtils.hasText(headerValue);
|
||||
|
||||
if (hasValue == StringUtils.hasText(headerExpression)) {
|
||||
throw new BeanDefinitionStoreException("exactly one of 'value' or 'expression' " +
|
||||
"is required on a gateway's header.");
|
||||
}
|
||||
|
||||
Expression expression =
|
||||
hasValue
|
||||
? new LiteralExpression(embeddedValueResolver.resolveStringValue(headerValue))
|
||||
: EXPRESSION_PARSER.parseExpression(
|
||||
embeddedValueResolver.resolveStringValue(headerExpression));
|
||||
|
||||
headerExpressions.put((String) header.get("name"), expression);
|
||||
}
|
||||
gatewayMethodMetadata.setHeaderExpressions(headerExpressions);
|
||||
}
|
||||
return gatewayMethodMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO until SPR-11710 will be resolved.
|
||||
* Captures the meta-annotation attribute values, in order.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-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,13 +25,20 @@ import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.EmbeddedValueResolver;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.ExpressionFactoryBean;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.config.MessagingGatewayRegistrar;
|
||||
import org.springframework.integration.gateway.GatewayMethodMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -49,6 +56,8 @@ import org.springframework.util.xml.DomUtils;
|
||||
*/
|
||||
public class GatewayParser implements BeanDefinitionParser {
|
||||
|
||||
private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
private final MessagingGatewayRegistrar registrar = new MessagingGatewayRegistrar();
|
||||
|
||||
@Override
|
||||
@@ -88,7 +97,8 @@ public class GatewayParser implements BeanDefinitionParser {
|
||||
|
||||
gatewayAttributes.put("proxyDefaultMethods", element.getAttribute("proxy-default-methods"));
|
||||
|
||||
BeanDefinitionHolder gatewayHolder = this.registrar.parse(gatewayAttributes);
|
||||
BeanDefinitionHolder gatewayHolder =
|
||||
this.registrar.gatewayProxyBeanDefinition(gatewayAttributes, parserContext.getRegistry());
|
||||
if (isNested) {
|
||||
return gatewayHolder.getBeanDefinition();
|
||||
}
|
||||
@@ -116,51 +126,81 @@ public class GatewayParser implements BeanDefinitionParser {
|
||||
|
||||
private void methods(final Element element, ParserContext parserContext,
|
||||
final Map<String, Object> gatewayAttributes) {
|
||||
|
||||
List<Element> methodElements = DomUtils.getChildElementsByTagName(element, "method");
|
||||
if (!CollectionUtils.isEmpty(methodElements)) {
|
||||
Map<String, BeanDefinition> methodMetadataMap = new ManagedMap<>();
|
||||
|
||||
ConfigurableBeanFactory beanFactory = obtainBeanFactory(parserContext.getRegistry());
|
||||
Map<String, AbstractBeanDefinition> methodMetadataMap = new HashMap<>();
|
||||
for (Element methodElement : methodElements) {
|
||||
String methodName = methodElement.getAttribute(AbstractBeanDefinitionParser.NAME_ATTRIBUTE);
|
||||
BeanDefinitionBuilder methodMetadataBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
GatewayMethodMetadata.class);
|
||||
methodMetadataBuilder.addPropertyValue("requestChannelName",
|
||||
methodElement.getAttribute("request-channel"));
|
||||
methodMetadataBuilder.addPropertyValue("replyChannelName", methodElement.getAttribute("reply-channel"));
|
||||
methodMetadataBuilder.addPropertyValue("requestTimeout", methodElement.getAttribute("request-timeout"));
|
||||
methodMetadataBuilder.addPropertyValue("replyTimeout", methodElement.getAttribute("reply-timeout"));
|
||||
|
||||
boolean hasMapper = StringUtils.hasText(element.getAttribute("mapper"));
|
||||
String payloadExpression = methodElement.getAttribute("payload-expression");
|
||||
Assert.state(!hasMapper || !StringUtils.hasText(payloadExpression),
|
||||
"'payload-expression' is not allowed when a 'mapper' is provided");
|
||||
AbstractBeanDefinition gatewayMethodMetadataBd =
|
||||
new RootBeanDefinition(GatewayMethodMetadata.class,
|
||||
() -> createGatewayMethodMetadata(element, beanFactory, methodElement));
|
||||
|
||||
if (StringUtils.hasText(payloadExpression)) {
|
||||
methodMetadataBuilder.addPropertyValue("payloadExpression",
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
|
||||
.addConstructorArgValue(payloadExpression)
|
||||
.getBeanDefinition());
|
||||
}
|
||||
|
||||
List<Element> invocationHeaders = DomUtils.getChildElementsByTagName(methodElement, "header");
|
||||
if (!CollectionUtils.isEmpty(invocationHeaders)) {
|
||||
Assert.state(!hasMapper, "header elements are not allowed when a 'mapper' is provided");
|
||||
|
||||
Map<String, Object> headerExpressions = new ManagedMap<>();
|
||||
for (Element headerElement : invocationHeaders) {
|
||||
BeanDefinition expressionDef = IntegrationNamespaceUtils
|
||||
.createExpressionDefinitionFromValueOrExpression("value", "expression", parserContext,
|
||||
headerElement, true);
|
||||
|
||||
headerExpressions.put(headerElement.getAttribute(AbstractBeanDefinitionParser.NAME_ATTRIBUTE),
|
||||
expressionDef);
|
||||
}
|
||||
methodMetadataBuilder.addPropertyValue("headerExpressions", headerExpressions);
|
||||
}
|
||||
methodMetadataMap.put(methodName, methodMetadataBuilder.getBeanDefinition());
|
||||
methodMetadataMap.put(methodName, gatewayMethodMetadataBd);
|
||||
}
|
||||
|
||||
gatewayAttributes.put("methods", methodMetadataMap);
|
||||
}
|
||||
}
|
||||
|
||||
private static ConfigurableBeanFactory obtainBeanFactory(BeanDefinitionRegistry registry) {
|
||||
if (registry instanceof ConfigurableBeanFactory) {
|
||||
return (ConfigurableBeanFactory) registry;
|
||||
}
|
||||
else if (registry instanceof ConfigurableApplicationContext) {
|
||||
return ((ConfigurableApplicationContext) registry).getBeanFactory();
|
||||
}
|
||||
throw new IllegalArgumentException("The provided 'BeanDefinitionRegistry' must be an instance " +
|
||||
"of 'ConfigurableBeanFactory' or 'ConfigurableApplicationContext', but given is: "
|
||||
+ registry.getClass());
|
||||
}
|
||||
|
||||
private GatewayMethodMetadata createGatewayMethodMetadata(Element element,
|
||||
ConfigurableBeanFactory beanFactory, Element methodElement) {
|
||||
|
||||
EmbeddedValueResolver embeddedValueResolver = new EmbeddedValueResolver(beanFactory);
|
||||
GatewayMethodMetadata gatewayMethodMetadata = new GatewayMethodMetadata();
|
||||
gatewayMethodMetadata.setRequestChannelName(methodElement.getAttribute("request-channel"));
|
||||
gatewayMethodMetadata.setReplyChannelName(methodElement.getAttribute("reply-channel"));
|
||||
gatewayMethodMetadata.setRequestTimeout(
|
||||
embeddedValueResolver.resolveStringValue(methodElement.getAttribute("request-timeout")));
|
||||
gatewayMethodMetadata.setReplyTimeout(
|
||||
embeddedValueResolver.resolveStringValue(methodElement.getAttribute("reply-timeout")));
|
||||
|
||||
boolean hasMapper = StringUtils.hasText(element.getAttribute("mapper"));
|
||||
String payloadExpression = methodElement.getAttribute("payload-expression");
|
||||
Assert.state(!hasMapper || !StringUtils.hasText(payloadExpression),
|
||||
"'payload-expression' is not allowed when a 'mapper' is provided");
|
||||
|
||||
if (StringUtils.hasText(payloadExpression)) {
|
||||
gatewayMethodMetadata.setPayloadExpression(
|
||||
EXPRESSION_PARSER.parseExpression(embeddedValueResolver.resolveStringValue(payloadExpression)));
|
||||
}
|
||||
|
||||
List<Element> invocationHeaders = DomUtils.getChildElementsByTagName(methodElement, "header");
|
||||
if (!CollectionUtils.isEmpty(invocationHeaders)) {
|
||||
Assert.state(!hasMapper, "header elements are not allowed when a 'mapper' is provided");
|
||||
|
||||
Map<String, Expression> headerExpressions = new HashMap<>();
|
||||
for (Element headerElement : invocationHeaders) {
|
||||
String headerValue = headerElement.getAttribute("value");
|
||||
String headerExpression = headerElement.getAttribute("expression");
|
||||
Expression expression =
|
||||
StringUtils.hasText(headerValue)
|
||||
? new LiteralExpression(embeddedValueResolver.resolveStringValue(headerValue))
|
||||
: EXPRESSION_PARSER.parseExpression(
|
||||
embeddedValueResolver.resolveStringValue(headerExpression));
|
||||
|
||||
headerExpressions.put(headerElement.getAttribute(AbstractBeanDefinitionParser.NAME_ATTRIBUTE),
|
||||
expression);
|
||||
}
|
||||
gatewayMethodMetadata.setHeaderExpressions(headerExpressions);
|
||||
}
|
||||
return gatewayMethodMetadata;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ public class GatewayParserTests {
|
||||
ConfigurableListableBeanFactory beanFactory = ((GenericApplicationContext) context).getBeanFactory();
|
||||
Object attribute =
|
||||
beanFactory.getMergedBeanDefinition("&oneWay").getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE);
|
||||
assertThat(attribute).isEqualTo(TestService.class.getName());
|
||||
assertThat(attribute).isEqualTo(TestService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -189,7 +189,7 @@ public class GatewayParserTests {
|
||||
ConfigurableListableBeanFactory beanFactory = ((GenericApplicationContext) context).getBeanFactory();
|
||||
Object attribute =
|
||||
beanFactory.getMergedBeanDefinition("&defaultConfig").getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE);
|
||||
assertThat(attribute).isEqualTo(RequestReplyExchanger.class.getName());
|
||||
assertThat(attribute).isEqualTo(RequestReplyExchanger.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user