INT-4443: Use SimpleEC for uriVariablesExpression
JIRA: https://jira.spring.io/browse/INT-4443 **cherry-pick to 5.0.x, 4.3.x** Polishing; use data binding accessor in test evaluation contexts. Add `.withInstanceMethods()` See https://jira.spring.io/browse/SPR-16588?focusedCommentId=158041&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-158041 * Polishing according PR comments # Conflicts: # build.gradle # src/reference/asciidoc/changes-4.3-5.0.adoc # Conflicts: # build.gradle # spring-integration-core/src/main/java/org/springframework/integration/expression/ExpressionUtils.java # spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java # spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java # spring-integration-http/src/main/java/org/springframework/integration/http/outbound/AbstractHttpRequestExecutingMessageHandler.java # spring-integration-http/src/main/resources/org/springframework/integration/http/config/spring-integration-http-4.3.xsd # spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java # spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java # src/reference/asciidoc/changes-4.2-4.3.adoc # src/reference/asciidoc/http.adoc
This commit is contained in:
committed by
Artem Bilan
parent
ed79a9521c
commit
705d33a30c
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.integration.expression.SpelPropertyAccessorRegistrar;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract class for integration evaluation context factory beans.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 4.3.15
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractEvaluationContextFactoryBean implements ApplicationContextAware, InitializingBean {
|
||||
|
||||
private Map<String, PropertyAccessor> propertyAccessors = new LinkedHashMap<String, PropertyAccessor>();
|
||||
|
||||
private Map<String, Method> functions = new LinkedHashMap<String, Method>();
|
||||
|
||||
private TypeConverter typeConverter = new StandardTypeConverter();
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
protected TypeConverter getTypeConverter() {
|
||||
return this.typeConverter;
|
||||
}
|
||||
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public void setPropertyAccessors(Map<String, PropertyAccessor> accessors) {
|
||||
Assert.isTrue(!this.initialized, "'propertyAccessors' can't be changed after initialization.");
|
||||
Assert.notNull(accessors, "'accessors' must not be null.");
|
||||
Assert.noNullElements(accessors.values().toArray(), "'accessors' cannot have null values.");
|
||||
this.propertyAccessors = new LinkedHashMap<String, PropertyAccessor>(accessors);
|
||||
}
|
||||
|
||||
public Map<String, PropertyAccessor> getPropertyAccessors() {
|
||||
return this.propertyAccessors;
|
||||
}
|
||||
|
||||
public void setFunctions(Map<String, Method> functionsArg) {
|
||||
Assert.isTrue(!this.initialized, "'functions' can't be changed after initialization.");
|
||||
Assert.notNull(functionsArg, "'functions' must not be null.");
|
||||
Assert.noNullElements(functionsArg.values().toArray(), "'functions' cannot have null values.");
|
||||
this.functions = new LinkedHashMap<String, Method>(functionsArg);
|
||||
}
|
||||
|
||||
public Map<String, Method> getFunctions() {
|
||||
return this.functions;
|
||||
}
|
||||
|
||||
protected void initialize(String beanName) throws Exception {
|
||||
if (this.applicationContext != null) {
|
||||
ConversionService conversionService = IntegrationUtils.getConversionService(getApplicationContext());
|
||||
if (conversionService != null) {
|
||||
this.typeConverter = new StandardTypeConverter(conversionService);
|
||||
}
|
||||
|
||||
Map<String, SpelFunctionFactoryBean> functionFactoryBeanMap = BeanFactoryUtils
|
||||
.beansOfTypeIncludingAncestors(this.applicationContext, SpelFunctionFactoryBean.class);
|
||||
for (SpelFunctionFactoryBean spelFunctionFactoryBean : functionFactoryBeanMap.values()) {
|
||||
if (!getFunctions().containsKey(spelFunctionFactoryBean.getFunctionName())) {
|
||||
getFunctions().put(spelFunctionFactoryBean.getFunctionName(), spelFunctionFactoryBean.getObject());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
SpelPropertyAccessorRegistrar propertyAccessorRegistrar =
|
||||
this.applicationContext.getBean(SpelPropertyAccessorRegistrar.class);
|
||||
for (Entry<String, PropertyAccessor> entry : propertyAccessorRegistrar.getPropertyAccessors()
|
||||
.entrySet()) {
|
||||
if (!getPropertyAccessors().containsKey(entry.getKey())) {
|
||||
getPropertyAccessors().put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
// There is no 'SpelPropertyAccessorRegistrar' bean in the application context.
|
||||
}
|
||||
|
||||
ApplicationContext parent = this.applicationContext.getParent();
|
||||
|
||||
if (parent != null && parent.containsBean(beanName)) {
|
||||
AbstractEvaluationContextFactoryBean parentFactoryBean = parent.getBean("&" + beanName, getClass());
|
||||
|
||||
for (Entry<String, PropertyAccessor> entry : parentFactoryBean.getPropertyAccessors().entrySet()) {
|
||||
if (!getPropertyAccessors().containsKey(entry.getKey())) {
|
||||
getPropertyAccessors().put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<String, Method> entry : parentFactoryBean.getFunctions().entrySet()) {
|
||||
if (!getFunctions().containsKey(entry.getKey())) {
|
||||
getFunctions().put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
@@ -17,17 +17,9 @@
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
@@ -36,11 +28,8 @@ import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.TypeLocator;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.expression.SpelPropertyAccessorRegistrar;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -73,107 +62,28 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public class IntegrationEvaluationContextFactoryBean implements FactoryBean<StandardEvaluationContext>,
|
||||
ApplicationContextAware, InitializingBean {
|
||||
|
||||
private volatile Map<String, PropertyAccessor> propertyAccessors = new LinkedHashMap<String, PropertyAccessor>();
|
||||
|
||||
private volatile Map<String, Method> functions = new LinkedHashMap<String, Method>();
|
||||
|
||||
private TypeConverter typeConverter = new StandardTypeConverter();
|
||||
public class IntegrationEvaluationContextFactoryBean extends AbstractEvaluationContextFactoryBean
|
||||
implements FactoryBean<StandardEvaluationContext> {
|
||||
|
||||
private volatile TypeLocator typeLocator;
|
||||
|
||||
private BeanResolver beanResolver;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private volatile boolean initialized;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public void setPropertyAccessors(Map<String, PropertyAccessor> accessors) {
|
||||
Assert.isTrue(!this.initialized, "'propertyAccessors' can't be changed after initialization.");
|
||||
Assert.notNull(accessors, "'accessors' must not be null.");
|
||||
Assert.noNullElements(accessors.values().toArray(), "'accessors' cannot have null values.");
|
||||
this.propertyAccessors = new LinkedHashMap<String, PropertyAccessor>(accessors);
|
||||
}
|
||||
|
||||
public Map<String, PropertyAccessor> getPropertyAccessors() {
|
||||
return this.propertyAccessors;
|
||||
}
|
||||
|
||||
public void setFunctions(Map<String, Method> functionsArg) {
|
||||
Assert.isTrue(!this.initialized, "'functions' can't be changed after initialization.");
|
||||
Assert.notNull(functionsArg, "'functions' must not be null.");
|
||||
Assert.noNullElements(functionsArg.values().toArray(), "'functions' cannot have null values.");
|
||||
this.functions = new LinkedHashMap<String, Method>(functionsArg);
|
||||
}
|
||||
|
||||
public Map<String, Method> getFunctions() {
|
||||
return this.functions;
|
||||
}
|
||||
|
||||
public void setTypeLocator(TypeLocator typeLocator) {
|
||||
this.typeLocator = typeLocator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (this.applicationContext != null) {
|
||||
this.beanResolver = new BeanFactoryResolver(this.applicationContext);
|
||||
ConversionService conversionService = IntegrationUtils.getConversionService(this.applicationContext);
|
||||
if (conversionService != null) {
|
||||
this.typeConverter = new StandardTypeConverter(conversionService);
|
||||
}
|
||||
|
||||
Map<String, SpelFunctionFactoryBean> functionFactoryBeanMap =
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, SpelFunctionFactoryBean.class);
|
||||
for (SpelFunctionFactoryBean spelFunctionFactoryBean : functionFactoryBeanMap.values()) {
|
||||
if (!this.functions.containsKey(spelFunctionFactoryBean.getFunctionName())) {
|
||||
this.functions.put(spelFunctionFactoryBean.getFunctionName(), spelFunctionFactoryBean.getObject());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
SpelPropertyAccessorRegistrar propertyAccessorRegistrar =
|
||||
this.applicationContext.getBean(SpelPropertyAccessorRegistrar.class);
|
||||
for (Entry<String, PropertyAccessor> entry : propertyAccessorRegistrar.getPropertyAccessors().entrySet()) {
|
||||
if (!this.propertyAccessors.containsKey(entry.getKey())) {
|
||||
this.propertyAccessors.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
// There is no 'SpelPropertyAccessorRegistrar' bean in the application context.
|
||||
}
|
||||
|
||||
ApplicationContext parent = this.applicationContext.getParent();
|
||||
|
||||
if (parent != null && parent.containsBean(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME)) {
|
||||
IntegrationEvaluationContextFactoryBean parentFactoryBean =
|
||||
parent.getBean("&" + IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME,
|
||||
IntegrationEvaluationContextFactoryBean.class);
|
||||
|
||||
for (Entry<String, PropertyAccessor> entry : parentFactoryBean.getPropertyAccessors().entrySet()) {
|
||||
if (!this.propertyAccessors.containsKey(entry.getKey())) {
|
||||
this.propertyAccessors.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<String, Method> entry : parentFactoryBean.getFunctions().entrySet()) {
|
||||
if (!this.functions.containsKey(entry.getKey())) {
|
||||
this.functions.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getApplicationContext() != null) {
|
||||
this.beanResolver = new BeanFactoryResolver(getApplicationContext());
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
initialize(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -184,15 +94,15 @@ public class IntegrationEvaluationContextFactoryBean implements FactoryBean<Stan
|
||||
}
|
||||
|
||||
evaluationContext.setBeanResolver(this.beanResolver);
|
||||
evaluationContext.setTypeConverter(this.typeConverter);
|
||||
evaluationContext.setTypeConverter(getTypeConverter());
|
||||
|
||||
for (PropertyAccessor propertyAccessor : this.propertyAccessors.values()) {
|
||||
for (PropertyAccessor propertyAccessor : getPropertyAccessors().values()) {
|
||||
evaluationContext.addPropertyAccessor(propertyAccessor);
|
||||
}
|
||||
|
||||
evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
|
||||
for (Entry<String, Method> functionEntry : this.functions.entrySet()) {
|
||||
for (Entry<String, Method> functionEntry : getFunctions().entrySet()) {
|
||||
evaluationContext.registerFunction(functionEntry.getKey(), functionEntry.getValue());
|
||||
}
|
||||
|
||||
@@ -204,9 +114,4 @@ public class IntegrationEvaluationContextFactoryBean implements FactoryBean<Stan
|
||||
return StandardEvaluationContext.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -194,6 +194,17 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
|
||||
".expression.IntegrationEvaluationContextAwareBeanPostProcessor");
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(integrationEvalContextBPP, registry);
|
||||
}
|
||||
if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME)) {
|
||||
BeanDefinitionBuilder integrationEvaluationContextBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationSimpleEvaluationContextFactoryBean.class);
|
||||
integrationEvaluationContextBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
|
||||
BeanDefinitionHolder integrationEvaluationContextHolder =
|
||||
new BeanDefinitionHolder(integrationEvaluationContextBuilder.getBeanDefinition(),
|
||||
IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME);
|
||||
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, registry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.expression.SpelPropertyAccessorRegistrar;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* {@link FactoryBean} to populate {@link SimpleEvaluationContext} instances enhanced with:
|
||||
* <ul>
|
||||
* <li>
|
||||
* a {@link TypeConverter} based on the {@link ConversionService} from the application context.
|
||||
* </li>
|
||||
* <li>
|
||||
* a set of provided {@link PropertyAccessor}s including a default {@link MapAccessor}.
|
||||
* </li>
|
||||
* <li>
|
||||
* a set of provided SpEL functions.
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* After initialization this factory populates functions and property accessors from
|
||||
* {@link SpelFunctionFactoryBean}s and {@link SpelPropertyAccessorRegistrar}, respectively.
|
||||
* Functions and property accessors are also inherited from any parent context.
|
||||
* </p>
|
||||
* <p>
|
||||
* This factory returns a new instance for each reference - {@link #isSingleton()} returns false.
|
||||
* </p>
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 4.3.15
|
||||
*/
|
||||
public class IntegrationSimpleEvaluationContextFactoryBean extends AbstractEvaluationContextFactoryBean
|
||||
implements FactoryBean<SimpleEvaluationContext> {
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
initialize(IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SimpleEvaluationContext getObject() throws Exception {
|
||||
Collection<PropertyAccessor> accessors = getPropertyAccessors().values();
|
||||
PropertyAccessor[] accessorArray = accessors.toArray(new PropertyAccessor[accessors.size() + 2]);
|
||||
accessorArray[accessors.size()] = new MapAccessor();
|
||||
accessorArray[accessors.size() + 1] = DataBindingPropertyAccessor.forReadOnlyAccess();
|
||||
SimpleEvaluationContext evaluationContext =
|
||||
SimpleEvaluationContext.forPropertyAccessors(accessorArray)
|
||||
.withTypeConverter(getTypeConverter())
|
||||
.withInstanceMethods()
|
||||
.build();
|
||||
for (Entry<String, Method> functionEntry : getFunctions().entrySet()) {
|
||||
evaluationContext.setVariable(functionEntry.getKey(), functionEntry.getValue());
|
||||
}
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return SimpleEvaluationContext.class;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.integration.context;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.config.IntegrationConfigUtils;
|
||||
import org.springframework.integration.metadata.MetadataStore;
|
||||
@@ -48,6 +49,8 @@ public abstract class IntegrationContextUtils {
|
||||
|
||||
public static final String INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME = "integrationEvaluationContext";
|
||||
|
||||
public static final String INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME = "integrationSimpleEvaluationContext";
|
||||
|
||||
public static final String INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME = "integrationHeaderChannelRegistry";
|
||||
|
||||
public static final String INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME = "integrationGlobalProperties";
|
||||
@@ -120,12 +123,24 @@ public abstract class IntegrationContextUtils {
|
||||
|
||||
/**
|
||||
* @param beanFactory BeanFactory for lookup, must not be null.
|
||||
* @return the instance of {@link StandardEvaluationContext} bean whose name is "integrationEvaluationContext" .
|
||||
* @return the instance of {@link StandardEvaluationContext} bean whose name is
|
||||
* {@value #INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME}.
|
||||
*/
|
||||
public static StandardEvaluationContext getEvaluationContext(BeanFactory beanFactory) {
|
||||
return getBeanOfType(beanFactory, INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, StandardEvaluationContext.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param beanFactory BeanFactory for lookup, must not be null.
|
||||
* @return the instance of {@link SimpleEvaluationContext} bean whose name is
|
||||
* {@value #INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME}.
|
||||
* @since 4.3.15
|
||||
*/
|
||||
public static SimpleEvaluationContext getSimpleEvaluationContext(BeanFactory beanFactory) {
|
||||
return getBeanOfType(beanFactory, INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME,
|
||||
SimpleEvaluationContext.class);
|
||||
}
|
||||
|
||||
private static <T> T getBeanOfType(BeanFactory beanFactory, String beanName, Class<T> type) {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
if (!beanFactory.containsBean(beanName)) {
|
||||
@@ -149,7 +164,8 @@ public abstract class IntegrationContextUtils {
|
||||
Properties properties = new Properties();
|
||||
properties.putAll(IntegrationProperties.defaults());
|
||||
if (beanFactory != null) {
|
||||
Properties userProperties = getBeanOfType(beanFactory, INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME, Properties.class);
|
||||
Properties userProperties =
|
||||
getBeanOfType(beanFactory, INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME, Properties.class);
|
||||
if (userProperties != null) {
|
||||
properties.putAll(userProperties);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-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.
|
||||
@@ -16,18 +16,22 @@
|
||||
|
||||
package org.springframework.integration.expression;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.support.DataBindingPropertyAccessor;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext.Builder;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Utility class with static methods for helping with establishing environments for
|
||||
* SpEL expressions.
|
||||
@@ -40,32 +44,22 @@ import org.apache.commons.logging.LogFactory;
|
||||
public abstract class ExpressionUtils {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ExpressionUtils.class);
|
||||
/**
|
||||
* Create a {@link StandardEvaluationContext} with a {@link MapAccessor} in its
|
||||
* property accessor property and the supplied {@link ConversionService} in its
|
||||
* conversionService property.
|
||||
* @param conversionService the conversion service.
|
||||
* @return the evaluation context.
|
||||
*/
|
||||
private static StandardEvaluationContext createStandardEvaluationContext(ConversionService conversionService,
|
||||
BeanFactory beanFactory) {
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
if (conversionService != null) {
|
||||
evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService));
|
||||
}
|
||||
if (beanFactory != null) {
|
||||
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
|
||||
}
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create a context with no BeanFactory, usually in tests.
|
||||
* @return The evaluation context.
|
||||
*/
|
||||
public static StandardEvaluationContext createStandardEvaluationContext() {
|
||||
return doCreateContext(null);
|
||||
return (StandardEvaluationContext) doCreateContext(null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create a context with no BeanFactory, usually in tests.
|
||||
* @return The evaluation context.
|
||||
* @since 4.3.15
|
||||
*/
|
||||
public static SimpleEvaluationContext createSimpleEvaluationContext() {
|
||||
return (SimpleEvaluationContext) doCreateContext(null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,22 +72,73 @@ public abstract class ExpressionUtils {
|
||||
if (beanFactory == null) {
|
||||
logger.warn("Creating EvaluationContext with no beanFactory", new RuntimeException("No beanFactory"));
|
||||
}
|
||||
return doCreateContext(beanFactory);
|
||||
return (StandardEvaluationContext) doCreateContext(beanFactory, false);
|
||||
}
|
||||
|
||||
private static StandardEvaluationContext doCreateContext(BeanFactory beanFactory) {
|
||||
/**
|
||||
* Obtains the context from the beanFactory if not null; emits a warning if the beanFactory
|
||||
* is null.
|
||||
* @param beanFactory The bean factory.
|
||||
* @return The evaluation context.
|
||||
* @since 4.3.15
|
||||
*/
|
||||
public static SimpleEvaluationContext createSimpleEvaluationContext(BeanFactory beanFactory) {
|
||||
if (beanFactory == null) {
|
||||
logger.warn("Creating EvaluationContext with no beanFactory", new RuntimeException("No beanFactory"));
|
||||
}
|
||||
return (SimpleEvaluationContext) doCreateContext(beanFactory, true);
|
||||
}
|
||||
|
||||
private static EvaluationContext doCreateContext(BeanFactory beanFactory, boolean simple) {
|
||||
ConversionService conversionService = null;
|
||||
StandardEvaluationContext evaluationContext = null;
|
||||
EvaluationContext evaluationContext = null;
|
||||
if (beanFactory != null) {
|
||||
evaluationContext = IntegrationContextUtils.getEvaluationContext(beanFactory);
|
||||
evaluationContext =
|
||||
simple
|
||||
? IntegrationContextUtils.getSimpleEvaluationContext(beanFactory)
|
||||
: IntegrationContextUtils.getEvaluationContext(beanFactory);
|
||||
}
|
||||
if (evaluationContext == null) {
|
||||
if (beanFactory != null) {
|
||||
conversionService = IntegrationUtils.getConversionService(beanFactory);
|
||||
}
|
||||
evaluationContext = createStandardEvaluationContext(conversionService, beanFactory);
|
||||
evaluationContext = createEvaluationContext(conversionService, beanFactory, simple);
|
||||
}
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link StandardEvaluationContext} with a {@link MapAccessor} in its
|
||||
* property accessor property and the supplied {@link ConversionService} in its
|
||||
* conversionService property.
|
||||
* @param conversionService the conversion service.
|
||||
* @param beanFactory the bean factory.
|
||||
* @param simple true if simple.
|
||||
* @return the evaluation context.
|
||||
*/
|
||||
private static EvaluationContext createEvaluationContext(ConversionService conversionService,
|
||||
BeanFactory beanFactory, boolean simple) {
|
||||
|
||||
if (simple) {
|
||||
Builder ecBuilder = SimpleEvaluationContext.forPropertyAccessors(
|
||||
new MapAccessor(), DataBindingPropertyAccessor.forReadOnlyAccess())
|
||||
.withInstanceMethods();
|
||||
if (conversionService != null) {
|
||||
ecBuilder.withConversionService(conversionService);
|
||||
}
|
||||
return ecBuilder.build();
|
||||
}
|
||||
else {
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
if (conversionService != null) {
|
||||
evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService));
|
||||
}
|
||||
if (beanFactory != null) {
|
||||
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
|
||||
}
|
||||
return evaluationContext;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.serializer.support.SerializingConverter;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.annotation.Aggregator;
|
||||
import org.springframework.integration.annotation.BridgeFrom;
|
||||
import org.springframework.integration.annotation.BridgeTo;
|
||||
@@ -695,7 +696,7 @@ public class EnableIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void testIntegrationEvaluationContextCustomization() {
|
||||
EvaluationContext evaluationContext = this.context.getBean(EvaluationContext.class);
|
||||
EvaluationContext evaluationContext = this.context.getBean(StandardEvaluationContext.class);
|
||||
List<?> propertyAccessors = TestUtils.getPropertyValue(evaluationContext, "propertyAccessors", List.class);
|
||||
assertEquals(4, propertyAccessors.size());
|
||||
assertThat(propertyAccessors.get(0), instanceOf(JsonPropertyAccessor.class));
|
||||
|
||||
Reference in New Issue
Block a user