Skip to content

Commit 78427b0

Browse files
committed
GH-3085 Add Number and Boolean Spel converter
Refactor SpelConverter into an abstract class Resolves #3085
1 parent dc164fe commit 78427b0

File tree

2 files changed

+60
-17
lines changed

2 files changed

+60
-17
lines changed

core/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2018 the original author or authors.
2+
* Copyright 2015-2025 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.
@@ -16,8 +16,6 @@
1616

1717
package org.springframework.cloud.stream.config;
1818

19-
import java.beans.Introspector;
20-
2119
import org.springframework.beans.factory.annotation.Autowired;
2220
import org.springframework.beans.factory.annotation.Qualifier;
2321
import org.springframework.beans.factory.config.BeanDefinition;
@@ -44,6 +42,7 @@
4442
*
4543
* @author Eric Bottard
4644
* @author Artem Bilan
45+
* @author Oleg Zhurakousky
4746
*/
4847
@Configuration(proxyBeanMethods = false)
4948
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@@ -61,19 +60,19 @@ public class SpelExpressionConverterConfiguration {
6160
@Bean
6261
public static SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() {
6362
return new SpelPropertyAccessorRegistrar()
64-
.add(Introspector
65-
.decapitalize(JsonPropertyAccessor.class.getSimpleName()),
66-
new JsonPropertyAccessor());
63+
.add(new JsonPropertyAccessor());
6764
}
6865

6966
@Bean
7067
@ConfigurationPropertiesBinding
7168
@IntegrationConverter
72-
public Converter<Object, Expression> spelConverter(ConfigurableApplicationContext context) {
69+
public Converter<String, Expression> spelConverter(ConfigurableApplicationContext context) {
7370
SpelConverter converter = new SpelConverter();
7471
ConfigurableConversionService cs = (ConfigurableConversionService) context.getBeanFactory().getConversionService();
7572
if (cs != null) {
7673
cs.addConverter(converter);
74+
cs.addConverter(new NumberToStringSpelConverter());
75+
cs.addConverter(new BooleanToStringSpelConverter());
7776
}
7877
return converter;
7978
}
@@ -83,7 +82,30 @@ public Converter<Object, Expression> spelConverter(ConfigurableApplicationContex
8382
*
8483
* @author Eric Bottard
8584
*/
86-
public static class SpelConverter implements Converter<Object, Expression> {
85+
public static class SpelConverter extends AbstractSpelConverter<String> {
86+
@Override
87+
public Expression convert(String source) {
88+
return this.doConvert(source);
89+
}
90+
}
91+
92+
public static class NumberToStringSpelConverter extends AbstractSpelConverter<Number> {
93+
@Override
94+
public Expression convert(Number source) {
95+
String value = source.toString();
96+
return this.doConvert(value);
97+
}
98+
}
99+
100+
public static class BooleanToStringSpelConverter extends AbstractSpelConverter<Boolean> {
101+
@Override
102+
public Expression convert(Boolean source) {
103+
String value = source.toString();
104+
return this.doConvert(value);
105+
}
106+
}
107+
108+
public static abstract class AbstractSpelConverter<T> implements Converter<T, Expression> {
87109

88110
private SpelExpressionParser parser = new SpelExpressionParser();
89111

@@ -92,12 +114,8 @@ public static class SpelConverter implements Converter<Object, Expression> {
92114
@Lazy
93115
private EvaluationContext evaluationContext;
94116

95-
@Override
96-
public Expression convert(Object source) {
117+
public Expression doConvert(String source) {
97118
try {
98-
if (!(source instanceof String)) {
99-
source = String.valueOf(source); // see https://github.com/spring-cloud/spring-cloud-stream/issues/2989
100-
}
101119
Expression expression = this.parser.parseExpression((String) source);
102120
if (expression instanceof SpelExpression) {
103121
((SpelExpression) expression)
@@ -110,7 +128,5 @@ public Expression convert(Object source) {
110128
"Could not convert '%s' into a SpEL expression", source), e);
111129
}
112130
}
113-
114131
}
115-
116132
}

core/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfigurationTests.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.boot.test.context.SpringBootTest;
3232
import org.springframework.context.annotation.Bean;
3333
import org.springframework.context.annotation.Configuration;
34+
import org.springframework.context.annotation.PropertySource;
3435
import org.springframework.expression.EvaluationContext;
3536
import org.springframework.expression.Expression;
3637
import org.springframework.expression.PropertyAccessor;
@@ -47,8 +48,7 @@
4748
* @author Artem Bilan
4849
* @author Soby Chacko
4950
*/
50-
@SpringBootTest(classes = SpelExpressionConverterConfigurationTests.Config.class, properties = {
51-
"expression: a.b" })
51+
@SpringBootTest(classes = SpelExpressionConverterConfigurationTests.Config.class)
5252
class SpelExpressionConverterConfigurationTests {
5353

5454
@Autowired
@@ -77,13 +77,23 @@ void converterCorrectlyInstalled() {
7777

7878
assertThat(propertyAccessors)
7979
.hasAtLeastOneElementOfType(JsonPropertyAccessor.class);
80+
81+
Expression numberExpression = this.pojo.getNumberExpression();
82+
assertThat(numberExpression.getValue()).isEqualTo(5);
83+
84+
Expression booleanExpression = this.pojo.getBooleanExpression();
85+
assertThat(booleanExpression.getValue()).isEqualTo(true);
8086
}
8187

8288
@ConfigurationProperties
8389
public static class Pojo {
8490

8591
private Expression expression;
8692

93+
private Expression numberExpression;
94+
95+
private Expression booleanExpression;
96+
8797
public Expression getExpression() {
8898
return this.expression;
8999
}
@@ -92,11 +102,28 @@ public void setExpression(Expression expression) {
92102
this.expression = expression;
93103
}
94104

105+
public Expression getNumberExpression() {
106+
return numberExpression;
107+
}
108+
109+
public void setNumberExpression(Expression numberExpression) {
110+
this.numberExpression = numberExpression;
111+
}
112+
113+
public Expression getBooleanExpression() {
114+
return booleanExpression;
115+
}
116+
117+
public void setBooleanExpression(Expression booleanExpression) {
118+
this.booleanExpression = booleanExpression;
119+
}
120+
95121
}
96122

97123
@Configuration
98124
@EnableAutoConfiguration
99125
@EnableConfigurationProperties(Pojo.class)
126+
@PropertySource("classpath:/application.yml")
100127
public static class Config implements BeanFactoryAware {
101128

102129
private BeanFactory beanFactory;

0 commit comments

Comments
 (0)