INT-1002: add support for fixed-rate, fixed-interval and cron attributes

This commit is contained in:
Marius Bogoevici
2010-07-22 06:21:33 +00:00
parent bdc85ff303
commit e75f4b616f
7 changed files with 173 additions and 25 deletions

View File

@@ -16,6 +16,8 @@
package org.springframework.integration.config.xml;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.w3c.dom.Element;
@@ -46,7 +48,12 @@ import org.springframework.util.xml.DomUtils;
*/
public class PollerParser extends AbstractBeanDefinitionParser {
@Override
public static final String MULTIPLE_TRIGGER_DEFINITIONS = "A <poller> cannot specify more than one trigger configuration.";
public static final String NO_TRIGGER_DEFINITIONS = "A <poller> must have a one and only one trigger configuration.";
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
if (element.getAttribute("default").equals("true")) {
@@ -91,34 +98,59 @@ public class PollerParser extends AbstractBeanDefinitionParser {
}
private void configureTrigger(Element pollerElement, BeanDefinitionBuilder targetBuilder, ParserContext parserContext) {
String triggerBeanName = null;
if (pollerElement.hasAttribute("trigger")) {
triggerBeanName = pollerElement.getAttribute("trigger");
// Polling frequency can be configured either through attributes or by using sub-elements
// Since Spring Integration 2.0 trigger sub-elements are deprecated
String triggerAttribute = pollerElement.getAttribute("trigger");
String fixedRateAttribute = pollerElement.getAttribute("fixed-rate");
String fixedDelayAttribute = pollerElement.getAttribute("fixed-delay");
String cronAttribute = pollerElement.getAttribute("cron");
List<String> triggerBeanNames = new ArrayList<String>();
if (StringUtils.hasText(triggerAttribute)) {
triggerBeanNames.add(triggerAttribute);
} else if (StringUtils.hasText(fixedRateAttribute)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
"org.springframework.scheduling.support.PeriodicTrigger");
builder.addConstructorArgValue(fixedRateAttribute);
builder.addPropertyValue("fixedRate", Boolean.TRUE);
String triggerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
triggerBeanNames.add(triggerBeanName);
} else if (StringUtils.hasText(fixedDelayAttribute)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
"org.springframework.scheduling.support.PeriodicTrigger");
builder.addConstructorArgValue(fixedDelayAttribute);
builder.addPropertyValue("fixedRate", Boolean.FALSE);
String triggerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
triggerBeanNames.add(triggerBeanName);
} else if (StringUtils.hasText(cronAttribute)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
"org.springframework.scheduling.support.CronTrigger");
builder.addConstructorArgValue(cronAttribute);
String triggerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry());
triggerBeanNames.add(triggerBeanName);
}
Element intervalElement = DomUtils.getChildElementByTagName(pollerElement, "interval-trigger");
if (intervalElement != null) {
if (triggerBeanName != null) {
parserContext.getReaderContext().error(
"A <poller> element with the 'trigger' attribute cannot have <interval-trigger/> or <cron-trigger/> child elements. ", pollerElement);
}
triggerBeanName = parseIntervalTrigger(intervalElement, parserContext);
parserContext.getReaderContext().warning("Poller configuration via 'interval-trigger' subelements is deprecated, use attributes instead", pollerElement);
triggerBeanNames.add(parseIntervalTrigger(intervalElement, parserContext));
}
else {
Element cronElement = DomUtils.getChildElementByTagName(pollerElement, "cron-trigger");
parserContext.getReaderContext().warning("Poller configuration via 'cron-trigger' subelements is deprecated, use attributes instead", pollerElement);
if (cronElement != null) {
if (triggerBeanName != null) {
parserContext.getReaderContext().error(
"A <poller> element with the 'trigger' attribute cannot have <interval-trigger/> or <cron-trigger/> child elements. ", pollerElement);
}
triggerBeanName = parseCronTrigger(cronElement, parserContext);
triggerBeanNames.add(parseCronTrigger(cronElement, parserContext));
}
}
if (triggerBeanName == null) {
if (triggerBeanNames.isEmpty()) {
parserContext.getReaderContext().error(
"A <poller> element must include a trigger definition, either as a 'trigger' attribute, or as an <interval-trigger/> or <cron-trigger/> child element.", pollerElement);
NO_TRIGGER_DEFINITIONS, pollerElement);
}
targetBuilder.addPropertyReference("trigger", triggerBeanName);
}
if (triggerBeanNames.size() > 1) {
parserContext.getReaderContext().error(
MULTIPLE_TRIGGER_DEFINITIONS, pollerElement);
}
targetBuilder.addPropertyReference("trigger", triggerBeanNames.get(0));
}
/**
* Parse an "interval-trigger" element

View File

@@ -1018,10 +1018,12 @@
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<!-- Poller sub-elements are deprecated since Spring Integration 2.0 -->
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="interval-trigger" type="intervalTriggerType" />
<xsd:element name="cron-trigger" type="cronTriggerType" />
</xsd:choice>
<!-- Poller sub-elements are deprecated since Spring Integration 2.0 -->
<xsd:element name="transactional" type="transactionalType" minOccurs="0" maxOccurs="1" />
<xsd:element name="advice-chain" minOccurs="0" maxOccurs="1">
<xsd:complexType>
@@ -1046,7 +1048,21 @@
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<!-- <xsd:attribute name="ref" type="xsd:string" />-->
<xsd:attribute name="fixed-delay" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Fixed delay trigger (in milliseconds).</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="fixed-rate" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Fixed rate trigger (in milliseconds).</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cron" type="xsd:string">
<xsd:annotation>
<xsd:documentation>Cron trigger.</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="trigger" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>

View File

@@ -1,14 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
http://www.springframework.org/schema/integration/spring-integration.xsd">
<poller id="poller" receive-timeout="1234">
<poller id="pollerWithSubElement" receive-timeout="1234">
<cron-trigger expression="*/10 * 9-17 * * MON-FRI"/>
</poller>
<poller id="pollerWithAttribute" cron="*/10 * 9-17 * * MON-FRI" receive-timeout="1234"/>
</beans:beans>

View File

@@ -41,8 +41,8 @@ public class CronTriggerParserTests {
private ApplicationContext context;
@Test
public void checkConfig() {
Object poller = context.getBean("poller");
public void checkConfigWithSubElement() {
Object poller = context.getBean("pollerWithSubElement");
assertEquals(PollerMetadata.class, poller.getClass());
PollerMetadata metadata = (PollerMetadata) poller;
Trigger trigger = metadata.getTrigger();
@@ -54,4 +54,19 @@ public class CronTriggerParserTests {
assertEquals("*/10 * 9-17 * * MON-FRI", expression);
}
@Test
public void checkConfigWithAttribute() {
Object poller = context.getBean("pollerWithAttribute");
assertEquals(PollerMetadata.class, poller.getClass());
PollerMetadata metadata = (PollerMetadata) poller;
Trigger trigger = metadata.getTrigger();
assertEquals(CronTrigger.class, trigger.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(trigger);
String expression = (String) new DirectFieldAccessor(
accessor.getPropertyValue("sequenceGenerator"))
.getPropertyValue("expression");
assertEquals("*/10 * 9-17 * * MON-FRI", expression);
}
}

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
<poller id="pollerWithFixedRateAttribute" fixed-rate="36" receive-timeout="1234"/>
<poller id="pollerWithFixedDelayAttribute" fixed-delay="37" receive-timeout="1234"/>
</beans:beans>

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2010 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 org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.integration.scheduling.PollerMetadata;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Marius Bogoevici
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class IntervalTriggerParserTests {
@Autowired
ApplicationContext context;
@Test
public void testFixedRateTrigger() {
Object poller = context.getBean("pollerWithFixedRateAttribute");
assertEquals(PollerMetadata.class, poller.getClass());
PollerMetadata metadata = (PollerMetadata) poller;
Trigger trigger = metadata.getTrigger();
assertEquals(PeriodicTrigger.class, trigger.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(trigger);
Boolean fixedRate = (Boolean) accessor.getPropertyValue("fixedRate");
Long period = (Long) accessor.getPropertyValue("period");
assertEquals(fixedRate, true);
assertEquals(36l, period.longValue());
}
@Test
public void testFixedDelayTrigger() {
Object poller = context.getBean("pollerWithFixedDelayAttribute");
assertEquals(PollerMetadata.class, poller.getClass());
PollerMetadata metadata = (PollerMetadata) poller;
Trigger trigger = metadata.getTrigger();
assertEquals(PeriodicTrigger.class, trigger.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(trigger);
Boolean fixedRate = (Boolean) accessor.getPropertyValue("fixedRate");
Long period = (Long) accessor.getPropertyValue("period");
assertEquals(fixedRate, false);
assertEquals(37l, period.longValue());
}
}

View File

@@ -28,6 +28,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.config.TestTrigger;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.scheduling.PollerMetadata;
import org.springframework.scheduling.support.PeriodicTrigger;
/**
* @author Mark Fisher