From 10704c94c571a68dc2cdff561051de14cfd65211 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 17 Aug 2010 17:32:18 +0000 Subject: [PATCH] INT-1270 added support for
sub-elements on the --- .../config/xml/ScheduledProducerParser.java | 35 +++++++++++- .../endpoint/ScheduledMessageProducer.java | 21 +++---- .../config/xml/spring-integration-2.0.xsd | 56 ++++++++++++------- .../ScheduledProducerParserTests-context.xml | 7 +++ .../xml/ScheduledProducerParserTests.java | 16 ++++++ .../ScheduledMessageProducerTests.java | 9 ++- 6 files changed, 107 insertions(+), 37 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ScheduledProducerParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ScheduledProducerParser.java index 0a7584f187..09e22d0f18 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ScheduledProducerParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ScheduledProducerParser.java @@ -16,13 +16,18 @@ package org.springframework.integration.config.xml; +import java.util.List; + import org.w3c.dom.Element; import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; /** * Parser for the <scheduled-producer> element. @@ -83,7 +88,35 @@ public class ScheduledProducerParser extends AbstractSingleBeanDefinitionParser builder.addPropertyReference("outputChannel", element.getAttribute("channel")); builder.addConstructorArgValue(element.getAttribute("payload-expression")); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); - // TODO: add support for header expression sub-elements + List headerElements = DomUtils.getChildElementsByTagName(element, "header"); + if (!CollectionUtils.isEmpty(headerElements)) { + ManagedMap headerExpressions = new ManagedMap(); + for (Element headerElement : headerElements) { + String headerName = headerElement.getAttribute("name"); + String headerValue = headerElement.getAttribute("value"); + String headerExpression = headerElement.getAttribute("expression"); + boolean hasValue = StringUtils.hasText(headerValue); + boolean hasExpression = StringUtils.hasText(headerExpression); + if (!(hasValue ^ hasExpression)) { + parserContext.getReaderContext().error("exactly one of 'value' or 'expression' is required on a header sub-element", + parserContext.extractSource(headerElement)); + continue; + } + RootBeanDefinition expressionDef = null; + if (hasValue) { + expressionDef = new RootBeanDefinition("org.springframework.expression.common.LiteralExpression"); + expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerValue); + } + else if (hasExpression) { + expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); + expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerExpression); + } + if (expressionDef != null) { + headerExpressions.put(headerName, expressionDef); + } + } + builder.addPropertyValue("headerExpressions", headerExpressions); + } } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/ScheduledMessageProducer.java b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/ScheduledMessageProducer.java index b8d0c2c2d7..5ecb4f5dda 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/ScheduledMessageProducer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/ScheduledMessageProducer.java @@ -46,7 +46,7 @@ public class ScheduledMessageProducer extends MessageProducerSupport { private volatile ScheduledFuture future; - private volatile Map headerExpressionMap; + private final Map headerExpressions = new HashMap(); private final StandardEvaluationContext context = new StandardEvaluationContext(); @@ -59,22 +59,19 @@ public class ScheduledMessageProducer extends MessageProducerSupport { } - public void setHeaderExpressions(Map headerExpressions) { - if (headerExpressions != null) { - Map parsedExpressions = new HashMap(); - for (Map.Entry entry : headerExpressions.entrySet()) { - parsedExpressions.put(entry.getKey(), PARSER.parseExpression(entry.getValue())); + public void setHeaderExpressions(Map headerExpressions) { + synchronized (this.headerExpressions) { + this.headerExpressions.clear(); + if (headerExpressions != null) { + this.headerExpressions.putAll(headerExpressions); } - this.headerExpressionMap = parsedExpressions; } } private Map evaluateHeaders() { Map headers = new HashMap(); - if (this.headerExpressionMap != null) { - for (Map.Entry entry : this.headerExpressionMap.entrySet()) { - headers.put(entry.getKey(), entry.getValue().getValue(context)); - } + for (Map.Entry entry : this.headerExpressions.entrySet()) { + headers.put(entry.getKey(), entry.getValue().getValue(context)); } return headers; } @@ -106,7 +103,7 @@ public class ScheduledMessageProducer extends MessageProducerSupport { private final Expression payloadExpression; - private MessageProducingTask(Expression payloadExpression) { + private MessageProducingTask(Expression payloadExpression) {//, Map headerExpressions) { this.payloadExpression = payloadExpression; } diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd index 8611200a7e..273a04ad1f 100644 --- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd +++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd @@ -428,7 +428,7 @@ - + - - - - - - - - - - - - - - - - @@ -607,6 +587,37 @@ + + + + + + + + + + + + + + + + + + + + + @@ -2227,6 +2238,9 @@ Name of the header whose value to use. + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests-context.xml index 257818d260..71c0187ea6 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests-context.xml @@ -13,6 +13,8 @@ + + @@ -23,6 +25,11 @@ + +
+
+ + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests.java index 2da375ce13..048b7dbb58 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.util.Map; + import org.junit.Test; import org.junit.runner.RunWith; @@ -106,4 +108,18 @@ public class ScheduledProducerParserTests { assertEquals("'triggerRefTest'", payloadExpression.getExpressionString()); } + @Test + @SuppressWarnings("unchecked") + public void headerExpressions() { + ScheduledMessageProducer producer = context.getBean("headerExpressionsProducer", ScheduledMessageProducer.class); + assertFalse(producer.isAutoStartup()); + DirectFieldAccessor producerAccessor = new DirectFieldAccessor(producer); + Map headerExpressions = (Map) producerAccessor.getPropertyValue("headerExpressions"); + assertEquals(2, headerExpressions.size()); + assertEquals("6 * 7", headerExpressions.get("foo").getExpressionString()); + assertEquals("x", headerExpressions.get("bar").getExpressionString()); + assertEquals(42, headerExpressions.get("foo").getValue()); + assertEquals("x", headerExpressions.get("bar").getValue()); + } + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/endpoint/ScheduledMessageProducerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/endpoint/ScheduledMessageProducerTests.java index ba8f02c94c..0113a00fb9 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/endpoint/ScheduledMessageProducerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/endpoint/ScheduledMessageProducerTests.java @@ -26,6 +26,9 @@ import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; +import org.springframework.expression.Expression; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.integration.Message; import org.springframework.integration.channel.QueueChannel; import org.springframework.scheduling.Trigger; @@ -48,9 +51,9 @@ public class ScheduledMessageProducerTests { String payloadExpression = "'test-' + T(org.springframework.integration.endpoint.ScheduledMessageProducerTests).next()"; ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.afterPropertiesSet(); - Map headerExpressions = new HashMap(); - headerExpressions.put("foo", "'x'"); - headerExpressions.put("bar", "7 * 6"); + Map headerExpressions = new HashMap(); + headerExpressions.put("foo", new LiteralExpression("x")); + headerExpressions.put("bar", new SpelExpressionParser().parseExpression("7 * 6")); ScheduledMessageProducer producer = new ScheduledMessageProducer(trigger, payloadExpression); producer.setHeaderExpressions(headerExpressions); producer.setTaskScheduler(scheduler);