Skip to content

Commit 705d33a

Browse files
garyrussellartembilan
authored andcommitted
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
1 parent ed79a95 commit 705d33a

File tree

16 files changed

+512
-155
lines changed

16 files changed

+512
-155
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ subprojects { subproject ->
136136
springSecurityVersion = '4.1.4.RELEASE'
137137
springSocialTwitterVersion = '1.1.2.RELEASE'
138138
springRetryVersion = '1.1.3.RELEASE'
139-
springVersion = project.hasProperty('springVersion') ? project.springVersion : '4.3.14.RELEASE'
139+
springVersion = project.hasProperty('springVersion') ? project.springVersion : '4.3.15.BUILD-SNAPSHOT'
140140
springWsVersion = '2.3.0.RELEASE'
141141
xmlUnitVersion = '1.6'
142142
xstreamVersion = '1.4.7'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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.config;
18+
19+
import java.lang.reflect.Method;
20+
import java.util.LinkedHashMap;
21+
import java.util.Map;
22+
import java.util.Map.Entry;
23+
24+
import org.springframework.beans.BeansException;
25+
import org.springframework.beans.factory.BeanFactoryUtils;
26+
import org.springframework.beans.factory.InitializingBean;
27+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
28+
import org.springframework.context.ApplicationContext;
29+
import org.springframework.context.ApplicationContextAware;
30+
import org.springframework.core.convert.ConversionService;
31+
import org.springframework.expression.PropertyAccessor;
32+
import org.springframework.expression.TypeConverter;
33+
import org.springframework.expression.spel.support.StandardTypeConverter;
34+
import org.springframework.integration.expression.SpelPropertyAccessorRegistrar;
35+
import org.springframework.integration.support.utils.IntegrationUtils;
36+
import org.springframework.util.Assert;
37+
38+
/**
39+
* Abstract class for integration evaluation context factory beans.
40+
*
41+
* @author Gary Russell
42+
*
43+
* @since 4.3.15
44+
*
45+
*/
46+
public abstract class AbstractEvaluationContextFactoryBean implements ApplicationContextAware, InitializingBean {
47+
48+
private Map<String, PropertyAccessor> propertyAccessors = new LinkedHashMap<String, PropertyAccessor>();
49+
50+
private Map<String, Method> functions = new LinkedHashMap<String, Method>();
51+
52+
private TypeConverter typeConverter = new StandardTypeConverter();
53+
54+
private ApplicationContext applicationContext;
55+
56+
private boolean initialized;
57+
58+
protected TypeConverter getTypeConverter() {
59+
return this.typeConverter;
60+
}
61+
62+
protected ApplicationContext getApplicationContext() {
63+
return this.applicationContext;
64+
}
65+
66+
@Override
67+
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
68+
this.applicationContext = applicationContext;
69+
}
70+
71+
public void setPropertyAccessors(Map<String, PropertyAccessor> accessors) {
72+
Assert.isTrue(!this.initialized, "'propertyAccessors' can't be changed after initialization.");
73+
Assert.notNull(accessors, "'accessors' must not be null.");
74+
Assert.noNullElements(accessors.values().toArray(), "'accessors' cannot have null values.");
75+
this.propertyAccessors = new LinkedHashMap<String, PropertyAccessor>(accessors);
76+
}
77+
78+
public Map<String, PropertyAccessor> getPropertyAccessors() {
79+
return this.propertyAccessors;
80+
}
81+
82+
public void setFunctions(Map<String, Method> functionsArg) {
83+
Assert.isTrue(!this.initialized, "'functions' can't be changed after initialization.");
84+
Assert.notNull(functionsArg, "'functions' must not be null.");
85+
Assert.noNullElements(functionsArg.values().toArray(), "'functions' cannot have null values.");
86+
this.functions = new LinkedHashMap<String, Method>(functionsArg);
87+
}
88+
89+
public Map<String, Method> getFunctions() {
90+
return this.functions;
91+
}
92+
93+
protected void initialize(String beanName) throws Exception {
94+
if (this.applicationContext != null) {
95+
ConversionService conversionService = IntegrationUtils.getConversionService(getApplicationContext());
96+
if (conversionService != null) {
97+
this.typeConverter = new StandardTypeConverter(conversionService);
98+
}
99+
100+
Map<String, SpelFunctionFactoryBean> functionFactoryBeanMap = BeanFactoryUtils
101+
.beansOfTypeIncludingAncestors(this.applicationContext, SpelFunctionFactoryBean.class);
102+
for (SpelFunctionFactoryBean spelFunctionFactoryBean : functionFactoryBeanMap.values()) {
103+
if (!getFunctions().containsKey(spelFunctionFactoryBean.getFunctionName())) {
104+
getFunctions().put(spelFunctionFactoryBean.getFunctionName(), spelFunctionFactoryBean.getObject());
105+
}
106+
}
107+
108+
try {
109+
SpelPropertyAccessorRegistrar propertyAccessorRegistrar =
110+
this.applicationContext.getBean(SpelPropertyAccessorRegistrar.class);
111+
for (Entry<String, PropertyAccessor> entry : propertyAccessorRegistrar.getPropertyAccessors()
112+
.entrySet()) {
113+
if (!getPropertyAccessors().containsKey(entry.getKey())) {
114+
getPropertyAccessors().put(entry.getKey(), entry.getValue());
115+
}
116+
}
117+
}
118+
catch (NoSuchBeanDefinitionException e) {
119+
// There is no 'SpelPropertyAccessorRegistrar' bean in the application context.
120+
}
121+
122+
ApplicationContext parent = this.applicationContext.getParent();
123+
124+
if (parent != null && parent.containsBean(beanName)) {
125+
AbstractEvaluationContextFactoryBean parentFactoryBean = parent.getBean("&" + beanName, getClass());
126+
127+
for (Entry<String, PropertyAccessor> entry : parentFactoryBean.getPropertyAccessors().entrySet()) {
128+
if (!getPropertyAccessors().containsKey(entry.getKey())) {
129+
getPropertyAccessors().put(entry.getKey(), entry.getValue());
130+
}
131+
}
132+
133+
for (Entry<String, Method> entry : parentFactoryBean.getFunctions().entrySet()) {
134+
if (!getFunctions().containsKey(entry.getKey())) {
135+
getFunctions().put(entry.getKey(), entry.getValue());
136+
}
137+
}
138+
}
139+
}
140+
this.initialized = true;
141+
}
142+
143+
}
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.
@@ -17,17 +17,9 @@
1717
package org.springframework.integration.config;
1818

1919
import java.lang.reflect.Method;
20-
import java.util.LinkedHashMap;
21-
import java.util.Map;
2220
import java.util.Map.Entry;
2321

24-
import org.springframework.beans.BeansException;
25-
import org.springframework.beans.factory.BeanFactoryUtils;
2622
import org.springframework.beans.factory.FactoryBean;
27-
import org.springframework.beans.factory.InitializingBean;
28-
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
29-
import org.springframework.context.ApplicationContext;
30-
import org.springframework.context.ApplicationContextAware;
3123
import org.springframework.context.expression.BeanFactoryResolver;
3224
import org.springframework.context.expression.MapAccessor;
3325
import org.springframework.core.convert.ConversionService;
@@ -36,11 +28,8 @@
3628
import org.springframework.expression.TypeConverter;
3729
import org.springframework.expression.TypeLocator;
3830
import org.springframework.expression.spel.support.StandardEvaluationContext;
39-
import org.springframework.expression.spel.support.StandardTypeConverter;
4031
import org.springframework.integration.context.IntegrationContextUtils;
4132
import org.springframework.integration.expression.SpelPropertyAccessorRegistrar;
42-
import org.springframework.integration.support.utils.IntegrationUtils;
43-
import org.springframework.util.Assert;
4433

4534
/**
4635
* <p>
@@ -73,107 +62,28 @@
7362
*
7463
* @since 3.0
7564
*/
76-
public class IntegrationEvaluationContextFactoryBean implements FactoryBean<StandardEvaluationContext>,
77-
ApplicationContextAware, InitializingBean {
78-
79-
private volatile Map<String, PropertyAccessor> propertyAccessors = new LinkedHashMap<String, PropertyAccessor>();
80-
81-
private volatile Map<String, Method> functions = new LinkedHashMap<String, Method>();
82-
83-
private TypeConverter typeConverter = new StandardTypeConverter();
65+
public class IntegrationEvaluationContextFactoryBean extends AbstractEvaluationContextFactoryBean
66+
implements FactoryBean<StandardEvaluationContext> {
8467

8568
private volatile TypeLocator typeLocator;
8669

8770
private BeanResolver beanResolver;
8871

89-
private ApplicationContext applicationContext;
90-
91-
private volatile boolean initialized;
92-
93-
@Override
94-
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
95-
this.applicationContext = applicationContext;
96-
}
97-
98-
public void setPropertyAccessors(Map<String, PropertyAccessor> accessors) {
99-
Assert.isTrue(!this.initialized, "'propertyAccessors' can't be changed after initialization.");
100-
Assert.notNull(accessors, "'accessors' must not be null.");
101-
Assert.noNullElements(accessors.values().toArray(), "'accessors' cannot have null values.");
102-
this.propertyAccessors = new LinkedHashMap<String, PropertyAccessor>(accessors);
103-
}
104-
105-
public Map<String, PropertyAccessor> getPropertyAccessors() {
106-
return this.propertyAccessors;
107-
}
108-
109-
public void setFunctions(Map<String, Method> functionsArg) {
110-
Assert.isTrue(!this.initialized, "'functions' can't be changed after initialization.");
111-
Assert.notNull(functionsArg, "'functions' must not be null.");
112-
Assert.noNullElements(functionsArg.values().toArray(), "'functions' cannot have null values.");
113-
this.functions = new LinkedHashMap<String, Method>(functionsArg);
114-
}
115-
116-
public Map<String, Method> getFunctions() {
117-
return this.functions;
118-
}
119-
12072
public void setTypeLocator(TypeLocator typeLocator) {
12173
this.typeLocator = typeLocator;
12274
}
12375

76+
@Override
77+
public boolean isSingleton() {
78+
return false;
79+
}
12480

12581
@Override
12682
public void afterPropertiesSet() throws Exception {
127-
if (this.applicationContext != null) {
128-
this.beanResolver = new BeanFactoryResolver(this.applicationContext);
129-
ConversionService conversionService = IntegrationUtils.getConversionService(this.applicationContext);
130-
if (conversionService != null) {
131-
this.typeConverter = new StandardTypeConverter(conversionService);
132-
}
133-
134-
Map<String, SpelFunctionFactoryBean> functionFactoryBeanMap =
135-
BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, SpelFunctionFactoryBean.class);
136-
for (SpelFunctionFactoryBean spelFunctionFactoryBean : functionFactoryBeanMap.values()) {
137-
if (!this.functions.containsKey(spelFunctionFactoryBean.getFunctionName())) {
138-
this.functions.put(spelFunctionFactoryBean.getFunctionName(), spelFunctionFactoryBean.getObject());
139-
}
140-
}
141-
142-
try {
143-
SpelPropertyAccessorRegistrar propertyAccessorRegistrar =
144-
this.applicationContext.getBean(SpelPropertyAccessorRegistrar.class);
145-
for (Entry<String, PropertyAccessor> entry : propertyAccessorRegistrar.getPropertyAccessors().entrySet()) {
146-
if (!this.propertyAccessors.containsKey(entry.getKey())) {
147-
this.propertyAccessors.put(entry.getKey(), entry.getValue());
148-
}
149-
}
150-
}
151-
catch (NoSuchBeanDefinitionException e) {
152-
// There is no 'SpelPropertyAccessorRegistrar' bean in the application context.
153-
}
154-
155-
ApplicationContext parent = this.applicationContext.getParent();
156-
157-
if (parent != null && parent.containsBean(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME)) {
158-
IntegrationEvaluationContextFactoryBean parentFactoryBean =
159-
parent.getBean("&" + IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME,
160-
IntegrationEvaluationContextFactoryBean.class);
161-
162-
for (Entry<String, PropertyAccessor> entry : parentFactoryBean.getPropertyAccessors().entrySet()) {
163-
if (!this.propertyAccessors.containsKey(entry.getKey())) {
164-
this.propertyAccessors.put(entry.getKey(), entry.getValue());
165-
}
166-
}
167-
168-
for (Entry<String, Method> entry : parentFactoryBean.getFunctions().entrySet()) {
169-
if (!this.functions.containsKey(entry.getKey())) {
170-
this.functions.put(entry.getKey(), entry.getValue());
171-
}
172-
}
173-
}
83+
if (getApplicationContext() != null) {
84+
this.beanResolver = new BeanFactoryResolver(getApplicationContext());
17485
}
175-
176-
this.initialized = true;
86+
initialize(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME);
17787
}
17888

17989
@Override
@@ -184,15 +94,15 @@ public StandardEvaluationContext getObject() throws Exception {
18494
}
18595

18696
evaluationContext.setBeanResolver(this.beanResolver);
187-
evaluationContext.setTypeConverter(this.typeConverter);
97+
evaluationContext.setTypeConverter(getTypeConverter());
18898

189-
for (PropertyAccessor propertyAccessor : this.propertyAccessors.values()) {
99+
for (PropertyAccessor propertyAccessor : getPropertyAccessors().values()) {
190100
evaluationContext.addPropertyAccessor(propertyAccessor);
191101
}
192102

193103
evaluationContext.addPropertyAccessor(new MapAccessor());
194104

195-
for (Entry<String, Method> functionEntry : this.functions.entrySet()) {
105+
for (Entry<String, Method> functionEntry : getFunctions().entrySet()) {
196106
evaluationContext.registerFunction(functionEntry.getKey(), functionEntry.getValue());
197107
}
198108

@@ -204,9 +114,4 @@ public Class<?> getObjectType() {
204114
return StandardEvaluationContext.class;
205115
}
206116

207-
@Override
208-
public boolean isSingleton() {
209-
return false;
210-
}
211-
212117
}

spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,17 @@ private void registerIntegrationEvaluationContext(BeanDefinitionRegistry registr
194194
".expression.IntegrationEvaluationContextAwareBeanPostProcessor");
195195
BeanDefinitionReaderUtils.registerWithGeneratedName(integrationEvalContextBPP, registry);
196196
}
197+
if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME)) {
198+
BeanDefinitionBuilder integrationEvaluationContextBuilder = BeanDefinitionBuilder
199+
.genericBeanDefinition(IntegrationSimpleEvaluationContextFactoryBean.class);
200+
integrationEvaluationContextBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
201+
202+
BeanDefinitionHolder integrationEvaluationContextHolder =
203+
new BeanDefinitionHolder(integrationEvaluationContextBuilder.getBeanDefinition(),
204+
IntegrationContextUtils.INTEGRATION_SIMPLE_EVALUATION_CONTEXT_BEAN_NAME);
205+
206+
BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder, registry);
207+
}
197208
}
198209

199210
/**

0 commit comments

Comments
 (0)