More tooling tweaks for namespace

This commit is contained in:
dsyer
2009-02-05 07:50:23 +00:00
parent 9a112e2203
commit ed60703fdf
19 changed files with 204 additions and 107 deletions

View File

@@ -26,7 +26,7 @@ import org.w3c.dom.Element;
/**
* Internal parser for the <decision/> elements inside a job. A decision
* element references a bean definition for a
* {@link org.springframework.batch.core.job.flow.support.state.JobExecutionDecider}
* {@link org.springframework.batch.core.job.flow.JobExecutionDecider}
* and goes on to list a set of transitions to other states with <next
* on="pattern" to="stepName"/>. Used by the {@link JobParser}.
*

View File

@@ -21,6 +21,7 @@ import java.util.List;
import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
@@ -58,17 +59,18 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
/**
* @param element the top level element containing a flow definition
* @param outerContext the {@link ParserContext}
* @param parserContext the {@link ParserContext}
*/
@Override
protected void doParse(Element element, ParserContext outerContext, BeanDefinitionBuilder builder) {
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
List<RuntimeBeanReference> stateTransitions = new ArrayList<RuntimeBeanReference>();
StepParser stepParser = new StepParser();
DecisionParser decisionParser = new DecisionParser();
SplitParser splitParser = new SplitParser();
ParserContext parserContext = new ParserContext(outerContext.getReaderContext(), outerContext.getDelegate(),
builder.getBeanDefinition());
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
@@ -82,7 +84,8 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
stateTransitions.addAll(decisionParser.parse((Element) node, parserContext));
}
else if (nodeName.equals("split")) {
stateTransitions.addAll(splitParser.parse((Element) node, parserContext));
stateTransitions.addAll(splitParser.parse((Element) node, new ParserContext(parserContext
.getReaderContext(), parserContext.getDelegate(), builder.getBeanDefinition())));
}
}
}
@@ -95,6 +98,8 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.popAndRegisterContainingComponent();
}
}

View File

@@ -21,9 +21,7 @@ import static org.springframework.util.StringUtils.hasText;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
@@ -37,26 +35,26 @@ import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
/**
* {@link BeanDefinitionParser} for {@link org.springframework.batch.core.JobExecutionListener}s
* {@link BeanDefinitionParser} for
* {@link org.springframework.batch.core.JobExecutionListener}s
*
* @author Lucas Ward
*
* @author Dave Syer
*
*/
public class JobExecutionListenerParser {
@SuppressWarnings("unchecked")
public ManagedList parse(Element element,
ParserContext parserContext) {
List<BeanReference> listeners = new ArrayList<BeanReference>();
public ManagedList parse(Element element, ParserContext parserContext) {
List<BeanDefinition> listeners = new ArrayList<BeanDefinition>();
List<Element> listenerElements = (List<Element>) DomUtils.getChildElementsByTagName(element, "listener");
for(Element listenerElement : listenerElements){
BeanDefinitionBuilder listenerBuilder =
BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.listener.JobListenerFactoryBean");
for (Element listenerElement : listenerElements) {
BeanDefinitionBuilder listenerBuilder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.batch.core.listener.JobListenerFactoryBean");
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)) {
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++) {
@@ -65,48 +63,43 @@ public class JobExecutionListenerParser {
}
attributes.append(attributeNodes.item(i));
}
parserContext.getReaderContext().error("Both 'ref' and 'class' specified; use 'class' with an optional 'id' or just 'ref' for <" +
listenerElement.getTagName() + "> element with attributes: " + attributes, listenerElement);
parserContext.getReaderContext().error(
"Both 'ref' and 'class' specified; use 'class' with an optional 'id' or just 'ref' for <"
+ listenerElement.getTagName() + "> element with attributes: " + attributes,
listenerElement);
}
if(hasText(listenerRef)){
if (hasText(listenerRef)) {
listenerBuilder.addPropertyReference("delegate", listenerRef);
}
else if(hasText(className)){
else if (hasText(className)) {
RootBeanDefinition beanDef = new RootBeanDefinition(className, null, null);
String delegateId = parserContext.getReaderContext().generateBeanName(beanDef);
beanDef.setSource(parserContext.extractSource(listenerElement));
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDef, delegateId));
listenerBuilder.addPropertyReference("delegate", delegateId);
listenerBuilder.addPropertyValue("delegate", beanDef);
}
else {
parserContext.getReaderContext().error("Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element", listenerElement);
parserContext.getReaderContext().error(
"Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element",
listenerElement);
}
ManagedMap metaDataMap = new ManagedMap();
String beforeMethod = listenerElement.getAttribute("before-method");
if(StringUtils.hasText(beforeMethod)){
if (StringUtils.hasText(beforeMethod)) {
metaDataMap.put("beforeMethod", beforeMethod);
}
String afterMethod = listenerElement.getAttribute("after-method");
if(StringUtils.hasText(beforeMethod)){
if (StringUtils.hasText(beforeMethod)) {
metaDataMap.put("afterMethod", afterMethod);
}
listenerBuilder.addPropertyValue("metaDataMap", metaDataMap);
AbstractBeanDefinition beanDef = listenerBuilder.getBeanDefinition();
if (!StringUtils.hasText(id)) {
id = parserContext.getReaderContext().generateBeanName(beanDef);
}
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDef, id));
beanDef.setSource(parserContext.extractSource(listenerElement));
BeanReference bean = new RuntimeBeanReference(id);
listeners.add(bean);
listeners.add(beanDef);
}
ManagedList managedList = new ManagedList();
managedList.addAll(listeners);
return managedList;
}

View File

@@ -17,6 +17,7 @@ package org.springframework.batch.core.configuration.xml;
import org.springframework.batch.core.job.flow.FlowJob;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
@@ -76,8 +77,12 @@ public class JobParser extends AbstractSingleBeanDefinitionParser {
JobExecutionListenerParser listenerParser = new JobExecutionListenerParser();
Element listenersElement = (Element)DomUtils.getChildElementByTagName(element, "listeners");
if(listenersElement != null){
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(listenersElement.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
ManagedList managedList = listenerParser.parse(listenersElement, parserContext);
builder.addPropertyValue("jobExecutionListeners", managedList);
parserContext.popAndRegisterContainingComponent();
}
}

View File

@@ -31,7 +31,7 @@ import org.w3c.dom.Element;
/**
* Internal parser for the &lt;split/&gt; elements inside a job. A split element
* references a bean definition for a
* {@link org.springframework.batch.core.job.flow.support.state.JobExecutionDecider} and goes on to
* {@link org.springframework.batch.core.job.flow.JobExecutionDecider} and goes on to
* list a set of transitions to other states with &lt;next on="pattern"
* to="stepName"/&gt;. Used by the {@link JobParser}.
*

View File

@@ -23,6 +23,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
@@ -405,32 +406,40 @@ public class StepParser {
Element listenersElement =
DomUtils.getChildElementByTagName(element, "listeners");
if (listenersElement != null) {
List<BeanReference> listenerBeans = new ArrayList<BeanReference>();
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(listenersElement.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
List<Object> listenerBeans = new ArrayList<Object>();
handleStepListenerElements(parserContext, listenersElement,
listenerBeans);
ManagedList arguments = new ManagedList();
arguments.addAll(listenerBeans);
bd.getPropertyValues().addPropertyValue(property, arguments);
parserContext.popAndRegisterContainingComponent();
}
}
@SuppressWarnings("unchecked")
private void handleRetryListenersElement(Element element, BeanDefinition bd, ParserContext parserContext) {
Element retryListenersElement =
Element listenersElement =
DomUtils.getChildElementByTagName(element, "retry-listeners");
if (retryListenersElement != null) {
List<BeanReference> retryListenerBeans = new ArrayList<BeanReference>();
handleListenerElements(parserContext, retryListenersElement,
if (listenersElement != null) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(listenersElement.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
List<Object> retryListenerBeans = new ArrayList<Object>();
handleRetryListenerElements(parserContext, listenersElement,
retryListenerBeans);
ManagedList arguments = new ManagedList();
arguments.addAll(retryListenerBeans);
bd.getPropertyValues().addPropertyValue("retryListeners", arguments);
parserContext.popAndRegisterContainingComponent();
}
}
@SuppressWarnings("unchecked")
private void handleListenerElements(ParserContext parserContext,
Element element, List<BeanReference> beans) {
private void handleRetryListenerElements(ParserContext parserContext,
Element element, List<Object> beans) {
List<Element> listenerElements =
DomUtils.getChildElementsByTagName(element, "listener");
if (listenerElements != null) {
@@ -449,10 +458,7 @@ public class StepParser {
if (!StringUtils.hasText(id)) {
id = parserContext.getReaderContext().generateBeanName(beanDef);
}
beanDef.setSource(parserContext.extractSource(listenerElement));
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDef, id));
BeanReference bean = new RuntimeBeanReference(id);
beans.add(bean);
beans.add(beanDef);
}
else {
parserContext.getReaderContext().error("Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element", element);
@@ -463,7 +469,7 @@ public class StepParser {
@SuppressWarnings("unchecked")
private void handleStepListenerElements(ParserContext parserContext,
Element element, List<BeanReference> beans) {
Element element, List<Object> beans) {
List<Element> listenerElements =
DomUtils.getChildElementsByTagName(element, "listener");
if (listenerElements != null) {
@@ -480,10 +486,7 @@ public class StepParser {
}
else if (StringUtils.hasText(className)) {
RootBeanDefinition beanDef = new RootBeanDefinition(className, null, null);
String delegateId = parserContext.getReaderContext().generateBeanName(beanDef);
beanDef.setSource(parserContext.extractSource(listenerElement));
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDef, delegateId));
listenerBuilder.addPropertyReference("delegate", delegateId);
listenerBuilder.addPropertyValue("delegate", beanDef);
}
else {
parserContext.getReaderContext().error("Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element", element);
@@ -520,10 +523,7 @@ public class StepParser {
if (!StringUtils.hasText(id)) {
id = parserContext.getReaderContext().generateBeanName(beanDef);
}
parserContext.registerBeanComponent(new BeanComponentDefinition(beanDef, id));
beanDef.setSource(parserContext.extractSource(listenerElement));
BeanReference bean = new RuntimeBeanReference(id);
beans.add(bean);
beans.add(beanDef);
}
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.job.flow.support.state;
package org.springframework.batch.core.job.flow;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepExecution;

View File

@@ -17,6 +17,7 @@
package org.springframework.batch.core.job.flow.support.state;
import org.springframework.batch.core.job.flow.FlowExecutor;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
/**

View File

@@ -30,7 +30,7 @@
<xsd:complexContent>
<xsd:extension base="flowType">
<xsd:attribute name="id" type="xsd:ID" use="required" />
<xsd:attributeGroup ref="jobRepository"/>
<xsd:attributeGroup ref="jobRepository" />
<xsd:attribute name="incrementer" type="xsd:string"
use="optional">
<xsd:annotation>
@@ -109,10 +109,13 @@
<xsd:annotation>
<xsd:documentation>
Defines a stage in job processing backed by a
Step.
Step.
The name attribute must be specified and
can match the id of a bean definition
for a Step. If it does not, then you must provide a
can match the id of
a bean
definition
for a Step. If it does not, then you must provide
a
tasklet definition.
The next attribute is a synonym for &lt;next on="*" .../&gt;
</xsd:documentation>
@@ -133,6 +136,11 @@
<xsd:documentation>
The tasklet is a reference to another bean definition that defines implements the Tasklet interface.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.batch.core.step.tasklet.Tasklet"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
@@ -176,6 +184,11 @@
The decider is a reference to a JobExecutionDecider that can produce a status to base
the next transition on.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.batch.core.job.flow.JobExecutionDecider"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
@@ -196,7 +209,16 @@
maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID" />
<xsd:attribute name="ref" type="xsd:string" />
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
A reference to a JobExecutionListener or a POJO (with before-method / after-method).
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="class" type="xsd:string" />
<xsd:attribute name="before-method" type="xsd:string" />
<xsd:attribute name="after-method" type="xsd:string" />
@@ -451,9 +473,9 @@
</xsd:complexType>
<xsd:complexType name="jobExecutionListenerType">
<xsd:attribute name="before-method" type="xsd:string"></xsd:attribute>
<xsd:attribute name="after-method" type="xsd:string"></xsd:attribute>
<xsd:attribute name="ref" type="xsd:string" use="required"></xsd:attribute>
<xsd:attribute name="before-method" type="xsd:string"/>
<xsd:attribute name="after-method" type="xsd:string"/>
<xsd:attribute name="ref" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:group name="transitions">
@@ -526,9 +548,9 @@
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="COMPLETED"></xsd:enumeration>
<xsd:enumeration value="FAILED"></xsd:enumeration>
<xsd:enumeration value="STOPPED"></xsd:enumeration>
<xsd:enumeration value="COMPLETED"/>
<xsd:enumeration value="FAILED"/>
<xsd:enumeration value="STOPPED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>

View File

@@ -26,7 +26,7 @@ import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.support.state.JobExecutionDecider;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -111,7 +111,7 @@ public class StepWithFaultTolerantProcessTaskJobParserTests {
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);
assertEquals("wrong number of retry-listeners:", 2, ((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());

View File

@@ -26,7 +26,7 @@ import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.flow.support.state.JobExecutionDecider;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -38,7 +38,6 @@ import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.batch.core.job.flow.support.StateTransition;
import org.springframework.batch.core.job.flow.support.state.DecisionState;
import org.springframework.batch.core.job.flow.support.state.EndState;
import org.springframework.batch.core.job.flow.support.state.JobExecutionDecider;
import org.springframework.batch.core.job.flow.support.state.StepState;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;

View File

@@ -15,6 +15,7 @@
is-reader-transactional-queue="true"
task-executor="taskExecutor">
<retry-listeners>
<listener ref="retryListener"/>
<listener class="org.springframework.batch.core.configuration.xml.TestRetryListener"/>
</retry-listeners>
<streams>
@@ -39,6 +40,8 @@
<beans:bean id="listener" class="org.springframework.batch.core.configuration.xml.TestListener"/>
<beans:bean id="retryListener" class="org.springframework.batch.core.configuration.xml.TestRetryListener"/>
<beans:bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ConcurrentTaskExecutor"/>
</beans:beans>