From a77e5dac5aaad323ce30ebbfc64838cc00044c51 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 22 Feb 2012 18:36:47 -0500 Subject: [PATCH] Combined commit from Gary and Mark for INT-2451 Added bean resolver to ContentEnricher INT-2451 Polishing - PR Review Comments Disallow bean resolution in the name expression for content enricher properties - the name expressions can only resolve to payload properties. Value expressions can resolve to beans and bean properties. --- .../transformer/ContentEnricher.java | 20 +++- .../xml/EnricherParserTests-context.xml | 5 + .../config/xml/EnricherParserTests.java | 16 ++- .../xml/EnricherParserTests3-context.xml | 24 +++++ .../xml/EnricherParserTests3-fail-context.xml | 24 +++++ .../config/xml/EnricherParserTests3.java | 99 +++++++++++++++++++ src/reference/docbook/content-enrichment.xml | 5 +- 7 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-context.xml create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-fail-context.xml create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3.java diff --git a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java index b1a036ca9e..749212b4d9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java @@ -20,7 +20,9 @@ import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; +import org.springframework.beans.factory.BeanFactory; import org.springframework.context.Lifecycle; +import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.context.expression.MapAccessor; import org.springframework.expression.Expression; import org.springframework.expression.spel.SpelParserConfiguration; @@ -43,6 +45,7 @@ import org.springframework.util.ReflectionUtils; * * @author Mark Fisher * @author Gunnar Hillert + * @author Gary Russell * @since 2.1 */ public class ContentEnricher extends AbstractReplyProducingMessageHandler implements Lifecycle { @@ -51,7 +54,9 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem private final SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true)); - private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + private final StandardEvaluationContext sourceEvaluationContext = new StandardEvaluationContext(); + + private final StandardEvaluationContext targetEvaluationContext = new StandardEvaluationContext(); private volatile boolean shouldClonePayload = false; @@ -192,7 +197,12 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem this.gateway.afterPropertiesSet(); } - this.evaluationContext.addPropertyAccessor(new MapAccessor()); + this.sourceEvaluationContext.addPropertyAccessor(new MapAccessor()); + this.targetEvaluationContext.addPropertyAccessor(new MapAccessor()); + BeanFactory beanFactory = this.getBeanFactory(); + if (beanFactory != null) { + this.sourceEvaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); + } } @Override @@ -216,7 +226,7 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem actualRequestMessage = requestMessage; } else { - final Object requestMessagePayload = this.requestPayloadExpression.getValue(this.evaluationContext, requestMessage); + final Object requestMessagePayload = this.requestPayloadExpression.getValue(this.sourceEvaluationContext, requestMessage); actualRequestMessage = MessageBuilder.withPayload(requestMessagePayload) .copyHeaders(requestMessage.getHeaders()).build(); } @@ -233,8 +243,8 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler implem for (Map.Entry entry : this.propertyExpressions.entrySet()) { Expression propertyExpression = entry.getKey(); Expression valueExpression = entry.getValue(); - Object value = valueExpression.getValue(this.evaluationContext, replyMessage); - propertyExpression.setValue(this.evaluationContext, targetPayload, value); + Object value = valueExpression.getValue(this.sourceEvaluationContext, replyMessage); + propertyExpression.setValue(this.targetEvaluationContext, targetPayload, value); } return targetPayload; } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml index 73cfe39887..20b6dfb392 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests-context.xml @@ -21,6 +21,11 @@ order="99" should-clone-payload="true" output-channel="output"> + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java index 05ac990474..87fa08bb9c 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests.java @@ -77,8 +77,11 @@ public class EnricherParserTests { else if ("age".equals(e.getKey().getExpressionString())) { assertEquals("42", e.getValue().getExpressionString()); } + else if ("gender".equals(e.getKey().getExpressionString())) { + assertEquals("@testBean", e.getValue().getExpressionString()); + } else { - throw new IllegalStateException("expected 'name' and 'age' only, not: " + e.getKey().getExpressionString()); + throw new IllegalStateException("expected 'name', 'age', and 'gender' only, not: " + e.getKey().getExpressionString()); } } } @@ -123,6 +126,7 @@ public class EnricherParserTests { Target enriched = (Target) reply.getPayload(); assertEquals("foo", enriched.getName()); assertEquals(42, enriched.getAge()); + assertEquals("male", enriched.getGender()); assertNotSame(original, enriched); } @@ -146,6 +150,8 @@ public class EnricherParserTests { private volatile int age; + private volatile String gender; + public String getName() { return name; } @@ -162,6 +168,14 @@ public class EnricherParserTests { this.age = age; } + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + public Object clone() { Target copy = new Target(); copy.setName(this.name); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-context.xml new file mode 100644 index 0000000000..f116f2f3b2 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-context.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-fail-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-fail-context.xml new file mode 100644 index 0000000000..83e9002850 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3-fail-context.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3.java new file mode 100644 index 0000000000..7a2964b37a --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests3.java @@ -0,0 +1,99 @@ +/* + * Copyright 2002-2012 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.xml; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.expression.spel.SpelEvaluationException; +import org.springframework.integration.Message; +import org.springframework.integration.MessageChannel; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.core.PollableChannel; +import org.springframework.integration.message.GenericMessage; + +/** + * @author Gary Russell + * + * @since 2.1.1 + */ +public class EnricherParserTests3 { + + @Test + public void testSourceBeanResolver() { + ApplicationContext context = new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-context.xml", this.getClass()); + MessageChannel beanResolveIn = context.getBean("beanResolveIn", MessageChannel.class); + PollableChannel beanResolveOut = context.getBean("beanResolveOut", PollableChannel.class); + SomeBean payload = new SomeBean("foo"); + assertEquals("foo", payload.getNested().getValue()); + beanResolveIn.send(new GenericMessage(payload)); + @SuppressWarnings("unchecked") + Message out = (Message) beanResolveOut.receive(); + assertSame(payload, out.getPayload()); + assertEquals("bar", out.getPayload().getNested().getValue()); + } + + @Test + public void testTargetBeanResolver() { + ApplicationContext context = new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail-context.xml", this.getClass()); + MessageChannel beanResolveIn = context.getBean("beanResolveIn", MessageChannel.class); + SomeBean payload = new SomeBean("foo"); + assertEquals("foo", payload.getNested().getValue()); + try { + beanResolveIn.send(new GenericMessage(payload)); + fail("Expected SpEL Exception"); + } + catch (MessageHandlingException e) { + assertTrue(e.getCause() instanceof SpelEvaluationException); + } + } + + public static class SomeBean { + + private Nested nested = new Nested(); + + public SomeBean(String someProperty) { + this.nested.setValue(someProperty); + } + + public Nested getNested() { + return nested; + } + + public String getSomeOtherProperty() { + return "bar"; + } + + public class Nested { + private String value; + + public void setValue(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + } +} diff --git a/src/reference/docbook/content-enrichment.xml b/src/reference/docbook/content-enrichment.xml index 47655936a5..bc3df8c42e 100644 --- a/src/reference/docbook/content-enrichment.xml +++ b/src/reference/docbook/content-enrichment.xml @@ -349,7 +349,10 @@ as well. The former for a literal value to set, and the latter for a SpEL expression to be evaluated. The root object of the evaluation context is the Message that was - returned from the flow initiated by this enricher. + returned from the flow initiated by this enricher, the + input Message if there is no request channel, or the + application context (using the '@<beanName>.<beanProperty>' + SpEL syntax).