BATCH-63: added <retry-listeners>

This commit is contained in:
trisberg
2008-11-13 22:11:01 +00:00
parent 2c0f0ca8a0
commit 5274b55883
5 changed files with 95 additions and 39 deletions

View File

@@ -266,6 +266,8 @@ public class StepParser {
handleListenersElement(element, bd, parserContext);
handleRetryListenersElement(element, bd, parserContext);
handleStreamsElement(element, bd, parserContext);
bd.setRole(BeanDefinition.ROLE_SUPPORT);
@@ -299,50 +301,71 @@ public class StepParser {
DomUtils.getChildElementByTagName(element, "listeners");
if (listenersElement != null) {
List<BeanReference> listenerBeans = new ArrayList<BeanReference>();
List<Element> listenerElements =
DomUtils.getChildElementsByTagName(listenersElement, "listener");
if (listenerElements != null) {
for (Element listenerElement : listenerElements) {
String id = listenerElement.getAttribute("id");
String listenerRef = listenerElement.getAttribute("ref");
String className = listenerElement.getAttribute("class");
if ((StringUtils.hasText(id) || StringUtils.hasText(className))
&& StringUtils.hasText(listenerRef)) {
NamedNodeMap attributeNodes = listenerElement.getAttributes();
StringBuilder attributes = new StringBuilder();
for (int i = 0; i < attributeNodes.getLength(); i++) {
if (i > 0) {
attributes.append(" ");
}
attributes.append(attributeNodes.item(i));
}
throw new BeanCreationException("Both 'id' or 'ref' plus 'class' specified; use 'class' with an optional 'id' or just 'ref' for <" +
listenerElement.getTagName() + "> element with attributes: " + attributes);
}
if (StringUtils.hasText(listenerRef)) {
BeanReference bean = new RuntimeBeanReference(listenerRef);
listenerBeans.add(bean);
}
else if (StringUtils.hasText(className)) {
RootBeanDefinition beanDef = new RootBeanDefinition(className, null, null);
if (!StringUtils.hasText(id)) {
id = parserContext.getReaderContext().generateBeanName(beanDef);
}
parserContext.getRegistry().registerBeanDefinition(id, beanDef);
BeanReference bean = new RuntimeBeanReference(id);
listenerBeans.add(bean);
}
else {
throw new BeanCreationException("Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element");
}
}
}
handleListenerElements(parserContext, listenersElement,
listenerBeans);
ManagedList arguments = new ManagedList();
arguments.addAll(listenerBeans);
bd.getPropertyValues().addPropertyValue("listeners", arguments);
}
}
@SuppressWarnings("unchecked")
private void handleRetryListenersElement(Element element, RootBeanDefinition bd, ParserContext parserContext) {
Element retryListenersElement =
DomUtils.getChildElementByTagName(element, "retry-listeners");
if (retryListenersElement != null) {
List<BeanReference> retryListenerBeans = new ArrayList<BeanReference>();
handleListenerElements(parserContext, retryListenersElement,
retryListenerBeans);
ManagedList arguments = new ManagedList();
arguments.addAll(retryListenerBeans);
bd.getPropertyValues().addPropertyValue("retryListeners", arguments);
}
}
@SuppressWarnings("unchecked")
private void handleListenerElements(ParserContext parserContext,
Element element, List<BeanReference> beans) {
List<Element> listenerElements =
DomUtils.getChildElementsByTagName(element, "listener");
if (listenerElements != null) {
for (Element listenerElement : listenerElements) {
String id = listenerElement.getAttribute("id");
String listenerRef = listenerElement.getAttribute("ref");
String className = listenerElement.getAttribute("class");
if ((StringUtils.hasText(id) || StringUtils.hasText(className))
&& StringUtils.hasText(listenerRef)) {
NamedNodeMap attributeNodes = listenerElement.getAttributes();
StringBuilder attributes = new StringBuilder();
for (int i = 0; i < attributeNodes.getLength(); i++) {
if (i > 0) {
attributes.append(" ");
}
attributes.append(attributeNodes.item(i));
}
throw new BeanCreationException("Both 'id' or 'ref' plus 'class' specified; use 'class' with an optional 'id' or just 'ref' for <" +
listenerElement.getTagName() + "> element with attributes: " + attributes);
}
if (StringUtils.hasText(listenerRef)) {
BeanReference bean = new RuntimeBeanReference(listenerRef);
beans.add(bean);
}
else if (StringUtils.hasText(className)) {
RootBeanDefinition beanDef = new RootBeanDefinition(className, null, null);
if (!StringUtils.hasText(id)) {
id = parserContext.getReaderContext().generateBeanName(beanDef);
}
parserContext.getRegistry().registerBeanDefinition(id, beanDef);
BeanReference bean = new RuntimeBeanReference(id);
beans.add(bean);
}
else {
throw new BeanCreationException("Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element");
}
}
}
}
@SuppressWarnings("unchecked")
private void handleStreamsElement(Element element, RootBeanDefinition bd, ParserContext parserContext) {
Element streamsElement =

View File

@@ -251,7 +251,7 @@
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="retryListeners" minOccurs="0" maxOccurs="1">
<xsd:element name="retry-listeners" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
List of all listeners for the step definition

View File

@@ -31,6 +31,7 @@ import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.retry.RetryListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
@@ -59,6 +60,9 @@ public class StepWithFaultTolerantProcessTaskJobParserTests {
@Qualifier("listener")
private TestListener listener;
@Autowired
private TestRetryListener retryListener;
@Autowired
private TestProcessor processor;
@@ -85,6 +89,8 @@ public class StepWithFaultTolerantProcessTaskJobParserTests {
assertEquals("wrong retry-limit:", 3, rl);
Object listeners = ReflectionTestUtils.getField(factory, "listeners");
assertEquals("wrong number of listeners:", 2, ((StepListener[])listeners).length);
Object retryListeners = ReflectionTestUtils.getField(factory, "retryListeners");
assertEquals("wrong number of retry-listeners:", 1, ((RetryListener[])retryListeners).length);
Object streams = ReflectionTestUtils.getField(factory, "streams");
assertEquals("wrong number of streams:", 1, ((ItemStream[])streams).length);
JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters());
@@ -96,5 +102,6 @@ public class StepWithFaultTolerantProcessTaskJobParserTests {
assertTrue(processor.isExecuted());
assertTrue(writer.isExecuted());
assertTrue(listener.isExecuted());
assertTrue(retryListener.isExecuted());
}
}

View File

@@ -0,0 +1,23 @@
package org.springframework.batch.core.configuration.xml;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
import org.springframework.batch.retry.RetryListener;
public class TestRetryListener extends AbstractTestComponent implements RetryListener {
public <T> void close(RetryContext context, RetryCallback<T> callback,
Throwable throwable) {
}
public <T> void onError(RetryContext context, RetryCallback<T> callback,
Throwable throwable) {
}
public <T> boolean open(RetryContext context, RetryCallback<T> callback) {
System.out.println("RETRY RETRY RETRY RETRY");
executed = true;
return true;
}
}

View File

@@ -14,6 +14,9 @@
<listener class="org.springframework.batch.core.configuration.xml.TestListener"/>
<listener ref="listener"/>
</listeners>
<retry-listeners>
<listener class="org.springframework.batch.core.configuration.xml.TestRetryListener"/>
</retry-listeners>
<streams>
<stream ref="reader"/>
</streams>