NamespaceHandler for the batch-execution namespace.
+ * NamespaceHandler for the batch namespace.
*
*
- * Provides a {@link BeanDefinitionParser} for the <batch:job> tag. A job tag can
- * include nested chunked-step and tasklet-step tags.
- *
- *
- * Provides a {@link BeanDefinitionParser} for the <batch:job-repository> tag.
+ * Provides a {@link BeanDefinitionParser} for the <batch:config> tag. A config tag
+ * must include nested job-repository and job tags.
*
* @author Ben Hale
*/
public class BatchNamespaceHandler extends NamespaceHandlerSupport {
- /**
- * Register the {@link BeanDefinitionParser BeanDefinitionParser} for the 'job', tag.
- */
public void init() {
- registerBeanDefinitionParser("job", new JobBeanDefinitionParser());
- registerBeanDefinitionParser("job-repository", new JobRepositoryBeanDefinitionParser());
+ registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
}
}
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/ChunkStepEntry.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/ChunkStepEntry.java
deleted file mode 100644
index 048f9c5eb..000000000
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/ChunkStepEntry.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2002-2007 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.batch.execution.configuration;
-
-import org.springframework.beans.factory.parsing.ParseState;
-
-/**
- * {@link ParseState} entry representing a {@link ChunkStep}.
- *
- * @author Ben Hale
- */
-public class ChunkStepEntry extends AbstractStepEntry {
-
- /**
- * Creates a new instance of the {@link ChunkStepEntry} class.
- *
- * @param name the bean name of the job
- */
- ChunkStepEntry(String name) {
- super(name);
- }
-
- String getType() {
- return "chunk";
- }
-
-}
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/ConfigBeanDefinitionParser.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/ConfigBeanDefinitionParser.java
new file mode 100644
index 000000000..5429eef3e
--- /dev/null
+++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/ConfigBeanDefinitionParser.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2002-2007 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.batch.execution.configuration;
+
+import org.springframework.batch.execution.repository.SimpleJobRepository;
+import org.springframework.batch.execution.repository.dao.JdbcJobExecutionDao;
+import org.springframework.batch.execution.repository.dao.JdbcJobInstanceDao;
+import org.springframework.batch.execution.repository.dao.JdbcStepExecutionDao;
+import org.springframework.batch.execution.step.ItemOrientedStep;
+import org.springframework.batch.execution.step.TaskletStep;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.ConstructorArgumentValues;
+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.RootBeanDefinition;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.incrementer.DB2SequenceMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.DerbyMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer;
+import org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * @author Ben Hale
+ */
+public class ConfigBeanDefinitionParser implements BeanDefinitionParser {
+
+ private static final String JOB_REPOSITORY_ELEMENT = "job-repository";
+
+ private static final String JOB_REPOSITORY_BEAN_NAME = "_jobRepository";
+
+ private static final String DATA_SOURCE_ATT = "data-source";
+
+ private static final String DB_TYPE_ATT = "db-type";
+
+ private static final String DB_TYPE_DB2 = "db2";
+
+ private static final String DB_TYPE_DERBY = "derby";
+
+ private static final String DB_TYPE_HSQL = "hsql";
+
+ private static final String DB_TYPE_MYSQL = "mysql";
+
+ private static final String DB_TYPE_ORACLE = "oracle";
+
+ private static final String DB_TYPE_POSTGRES = "postgres";
+
+ private static final String JOB_ELEMENT = "job";
+
+ private static final String ID_ATT = "id";
+
+ private static final String RERUN_ATT = "rerun";
+
+ private static final String RERUN_ALWAYS = "always";
+
+ private static final String RERUN_NEVER = "never";
+
+ private static final String RERUN_INCOMPLETE = "incomplete";
+
+ private static final String STEP_ELEMENT = "step";
+
+ private static final String SIZE_ATT = "size";
+
+ private static final String TRANSACTION_MANAGER_ATT = "transaction-manager";
+
+ private static final String ITEM_READER_ATT = "item-reader";
+
+ private static final String ITEM_WRITER_ATT = "item-writer";
+
+ private static final String INPUT_SKIP_LIMIT_ATT = "input-skip-limit";
+
+ private static final String OUTPUT_SKIP_LIMIT_ATT = "output-skip-limit";
+
+ private static final String TASKLET_STEP_ELEMENT = "tasklet-step";
+
+ private static final String TASKLET_ATT = "tasklet";
+
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(),
+ parserContext.extractSource(element));
+ parserContext.pushContainingComponent(compositeDef);
+
+ NodeList childNodes = element.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node child = childNodes.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String localName = child.getLocalName();
+ if (JOB_REPOSITORY_ELEMENT.equals(localName)) {
+ parseJobRepository((Element) child, parserContext);
+ } else if (JOB_ELEMENT.equals(localName)) {
+ parseJob((Element) child, parserContext);
+ }
+ }
+ }
+
+ parserContext.popAndRegisterContainingComponent();
+ return null;
+ }
+
+ private void parseJobRepository(Element jobRepoEle, ParserContext parserContext) {
+ RootBeanDefinition jobRepoDef = new RootBeanDefinition(SimpleJobRepository.class);
+ jobRepoDef.setSource(parserContext.extractSource(jobRepoEle));
+
+ String dataSourceId = jobRepoEle.getAttribute(DATA_SOURCE_ATT);
+ if (!StringUtils.hasText(dataSourceId)) {
+ parserContext.getReaderContext().error("'data-source' attribute contains empty value", jobRepoEle);
+ } else {
+ String dbType = jobRepoEle.getAttribute(DB_TYPE_ATT);
+ ConstructorArgumentValues constructorArgumentValues = jobRepoDef.getConstructorArgumentValues();
+ String templateId = createJdbcTemplateDefinition(dataSourceId, parserContext);
+ constructorArgumentValues.addGenericArgumentValue(createJobInstanceDao(templateId, dataSourceId, dbType,
+ parserContext));
+ constructorArgumentValues.addGenericArgumentValue(createJobExecutionDao(templateId, dataSourceId, dbType,
+ parserContext));
+ constructorArgumentValues.addGenericArgumentValue(createStepExecutionDao(templateId, dataSourceId, dbType,
+ parserContext));
+ }
+
+ parserContext.registerBeanComponent(new BeanComponentDefinition(jobRepoDef, JOB_REPOSITORY_BEAN_NAME));
+ }
+
+ private String createJdbcTemplateDefinition(String dataSourceId, ParserContext parserContext) {
+ RootBeanDefinition templateDef = new RootBeanDefinition(JdbcTemplate.class);
+ templateDef.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(dataSourceId));
+ return parserContext.getReaderContext().registerWithGeneratedName(templateDef);
+ }
+
+ private BeanDefinition createJobInstanceDao(String templateId, String dataSourceId, String dbType,
+ ParserContext parserContext) {
+ RootBeanDefinition daoDef = new RootBeanDefinition(JdbcJobInstanceDao.class);
+ MutablePropertyValues propertyValues = daoDef.getPropertyValues();
+ propertyValues.addPropertyValue("jdbcTemplate", new RuntimeBeanReference(templateId));
+ propertyValues.addPropertyValue("jobIncrementer", getIncrementer(dbType, dataSourceId, "BATCH_JOB_SEQ"));
+ return daoDef;
+ }
+
+ private BeanDefinition createJobExecutionDao(String templateId, String dataSourceId, String dbType,
+ ParserContext parserContext) {
+ RootBeanDefinition daoDef = new RootBeanDefinition(JdbcJobExecutionDao.class);
+ MutablePropertyValues propertyValues = daoDef.getPropertyValues();
+ propertyValues.addPropertyValue("jdbcTemplate", new RuntimeBeanReference(templateId));
+ propertyValues.addPropertyValue("jobExecutionIncrementer", getIncrementer(dbType, dataSourceId,
+ "BATCH_JOB_EXECUTION_SEQ"));
+ return daoDef;
+ }
+
+ private BeanDefinition createStepExecutionDao(String templateId, String dataSourceId, String dbType,
+ ParserContext parserContext) {
+ RootBeanDefinition daoDef = new RootBeanDefinition(JdbcStepExecutionDao.class);
+ MutablePropertyValues propertyValues = daoDef.getPropertyValues();
+ propertyValues.addPropertyValue("jdbcTemplate", new RuntimeBeanReference(templateId));
+ propertyValues.addPropertyValue("stepExecutionIncrementer", getIncrementer(dbType, dataSourceId,
+ "BATCH_STEP_EXECUTION_SEQ"));
+ return daoDef;
+ }
+
+ private BeanDefinition getIncrementer(String dbType, String dataSourceId, String incrementerName) {
+ RootBeanDefinition incrementerDef = new RootBeanDefinition();
+
+ if (DB_TYPE_DB2.equals(dbType)) {
+ incrementerDef.setBeanClass(DB2SequenceMaxValueIncrementer.class);
+ addSequenceIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
+ } else if (DB_TYPE_DERBY.equals(dbType)) {
+ incrementerDef.setBeanClass(DerbyMaxValueIncrementer.class);
+ addTableIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
+ } else if (DB_TYPE_HSQL.equals(dbType)) {
+ incrementerDef.setBeanClass(HsqlMaxValueIncrementer.class);
+ addTableIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
+ } else if (DB_TYPE_MYSQL.equals(dbType)) {
+ incrementerDef.setBeanClass(MySQLMaxValueIncrementer.class);
+ addTableIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
+ } else if (DB_TYPE_ORACLE.equals(dbType)) {
+ incrementerDef.setBeanClass(OracleSequenceMaxValueIncrementer.class);
+ addSequenceIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
+ } else if (DB_TYPE_POSTGRES.equals(dbType)) {
+ incrementerDef.setBeanClass(PostgreSQLSequenceMaxValueIncrementer.class);
+ addSequenceIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
+ }
+
+ return incrementerDef;
+ }
+
+ private void addSequenceIncrementer(String dataSourceId, String incrementerName,
+ ConstructorArgumentValues constructorArgumentValues) {
+ constructorArgumentValues.addGenericArgumentValue(new RuntimeBeanReference(dataSourceId));
+ constructorArgumentValues.addGenericArgumentValue(incrementerName);
+ }
+
+ private void addTableIncrementer(String dataSourceId, String incrementerName,
+ ConstructorArgumentValues constructorArgumentValues) {
+ constructorArgumentValues.addGenericArgumentValue(new RuntimeBeanReference(dataSourceId));
+ constructorArgumentValues.addGenericArgumentValue(incrementerName);
+ constructorArgumentValues.addGenericArgumentValue("id");
+ }
+
+ private void parseJob(Element jobEle, ParserContext parserContext) {
+ NodeList childNodes = jobEle.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node child = childNodes.item(i);
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ String localName = child.getLocalName();
+ if (STEP_ELEMENT.equals(localName)) {
+ parseStep((Element) child, parserContext);
+ } else if (TASKLET_STEP_ELEMENT.equals(localName)) {
+ parseTaskletStep((Element) child, parserContext);
+ }
+ }
+ }
+ }
+
+ private void parseStep(Element stepEle, ParserContext parserContext) {
+ AbstractBeanDefinition stepDef = createStepBeanDefinition(stepEle, parserContext);
+ String id = stepEle.getAttribute(ID_ATT);
+
+ if (StringUtils.hasText(id)) {
+ parserContext.getRegistry().registerBeanDefinition(id, stepDef);
+ } else {
+ parserContext.getReaderContext().registerWithGeneratedName(stepDef);
+ }
+ }
+
+ private AbstractBeanDefinition createStepBeanDefinition(Element stepElement, ParserContext parserContext) {
+ RootBeanDefinition stepDef = new RootBeanDefinition(ItemOrientedStep.class);
+ stepDef.setSource(parserContext.extractSource(stepElement));
+ MutablePropertyValues propertyValues = stepDef.getPropertyValues();
+
+ String size = stepElement.getAttribute(SIZE_ATT);
+ propertyValues.addPropertyValue("commitInterval", Integer.valueOf(size));
+ String transactionManager = stepElement.getAttribute(TRANSACTION_MANAGER_ATT);
+ if (!StringUtils.hasText(transactionManager)) {
+ parserContext.getReaderContext().error("'transaction-manager' attribute contains empty value", stepElement);
+ } else {
+ propertyValues.addPropertyValue("transactionManager", new RuntimeBeanReference(transactionManager));
+ }
+
+ String itemReader = stepElement.getAttribute(ITEM_READER_ATT);
+ if (!StringUtils.hasText(itemReader)) {
+ parserContext.getReaderContext().error("'item-reader' attribute contains empty value", stepElement);
+ } else {
+ propertyValues.addPropertyValue("itemReader", new RuntimeBeanReference(itemReader));
+ }
+ String itemWriter = stepElement.getAttribute(ITEM_WRITER_ATT);
+ if (!StringUtils.hasText(itemWriter)) {
+ parserContext.getReaderContext().error("'item-writer' attribute contains empty value", stepElement);
+ } else {
+ propertyValues.addPropertyValue("itemWriter", new RuntimeBeanReference(itemWriter));
+ }
+
+ if (stepElement.hasAttribute(INPUT_SKIP_LIMIT_ATT)) {
+ String inputSkipLimit = stepElement.getAttribute(INPUT_SKIP_LIMIT_ATT);
+ propertyValues.addPropertyValue("skipLimit", Integer.valueOf(inputSkipLimit));
+ }
+
+ // TODO: Create difference between input skip limit and output skip limit
+ // if (stepElement.hasAttribute(ATT_OUTPUT_SKIP_LIMIT)) {
+ // String outputSkipLimit = stepElement.getAttribute(ATT_OUTPUT_SKIP_LIMIT);
+ // propertyValues.addPropertyValue(PROP_OUTPUT_SKIP_LIMIT, Integer.valueOf(outputSkipLimit));
+ // }
+
+ String rerun = stepElement.getAttribute(RERUN_ATT);
+ setPropertiesForRerun(rerun, propertyValues);
+ propertyValues.addPropertyValue("jobRepository", new RuntimeBeanReference(JOB_REPOSITORY_BEAN_NAME));
+ return stepDef;
+ }
+
+ private void parseTaskletStep(Element taskletStepEle, ParserContext parserContext) {
+ AbstractBeanDefinition stepDef = createTaskletStepBeanDefinition(taskletStepEle, parserContext);
+
+ String id = taskletStepEle.getAttribute(ID_ATT);
+
+ if (StringUtils.hasText(id)) {
+ parserContext.getRegistry().registerBeanDefinition(id, stepDef);
+ } else {
+ parserContext.getReaderContext().registerWithGeneratedName(stepDef);
+ }
+ }
+
+ private AbstractBeanDefinition createTaskletStepBeanDefinition(Element taskletElement, ParserContext parserContext) {
+ RootBeanDefinition stepDef = new RootBeanDefinition(TaskletStep.class);
+ stepDef.setSource(parserContext.extractSource(taskletElement));
+ MutablePropertyValues propertyValues = stepDef.getPropertyValues();
+
+ String tasklet = taskletElement.getAttribute(TASKLET_ATT);
+ if (!StringUtils.hasText(tasklet)) {
+ parserContext.getReaderContext().error("'tasklet' attribute contains empty value", taskletElement);
+ } else {
+ propertyValues.addPropertyValue("tasklet", new RuntimeBeanReference(tasklet));
+ }
+
+ String rerun = taskletElement.getAttribute(RERUN_ATT);
+ setPropertiesForRerun(rerun, propertyValues);
+ propertyValues.addPropertyValue("jobRepository", new RuntimeBeanReference(JOB_REPOSITORY_BEAN_NAME));
+
+ return stepDef;
+ }
+
+ private void setPropertiesForRerun(String rerun, MutablePropertyValues propertyValues) {
+ if (RERUN_ALWAYS.equals(rerun)) {
+ propertyValues.addPropertyValue("allowStartIfComplete", Boolean.TRUE);
+ propertyValues.addPropertyValue("startLimit", new Integer(Integer.MAX_VALUE));
+ } else if (RERUN_NEVER.equals(rerun)) {
+ propertyValues.addPropertyValue("allowStartIfComplete", Boolean.FALSE);
+ propertyValues.addPropertyValue("startLimit", Integer.valueOf(1));
+ } else if (RERUN_INCOMPLETE.equals(rerun)) {
+ propertyValues.addPropertyValue("allowStartIfComplete", Boolean.FALSE);
+ propertyValues.addPropertyValue("startLimit", new Integer(Integer.MAX_VALUE));
+ }
+ }
+}
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobBeanDefinitionParser.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobBeanDefinitionParser.java
deleted file mode 100644
index 8cf559382..000000000
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobBeanDefinitionParser.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2002-2007 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.batch.execution.configuration;
-
-import org.springframework.batch.execution.step.ItemOrientedStep;
-import org.springframework.batch.execution.step.TaskletStep;
-import org.springframework.beans.MutablePropertyValues;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.beans.factory.xml.BeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- *
- * @author Ben Hale
- */
-class JobBeanDefinitionParser implements BeanDefinitionParser {
-
- private static final String TAG_JOB = "job";
-
- private static final String TAG_STEP = "step";
-
- private static final String TAG_TASKLET_STEP = "tasklet-step";
-
- private static final String ATT_ID = "id";
-
- private static final String ATT_TASKLET = "tasklet";
-
- private static final String ATT_RERUN = "rerun";
-
- private static final String PROP_TASKLET = "tasklet";
-
- private static final String ENUM_ALWAYS = "always";
-
- private static final String ENUM_NEVER = "never";
-
- private static final String ENUM_INCOMPLETE = "incomplete";
-
- private static final String PROP_ALLOW_START_IF_COMPLETE = "allowStartIfComplete";
-
- private static final String PROP_JOB_REPOSITORY = "jobRepository";
-
- private static final String PROP_START_LIMIT = "startLimit";
-
- private static final String REPOSITORY_BEAN_NAME = "_jobRepository";
-
- private static final String ATT_SIZE = "size";
-
- private static final String PROP_COMMIT_INTERVAL = "commitInterval";
-
- private static final String ATT_TRANSACTION_MANAGER = "transaction-manager";
-
- private static final String PROP_TRANSACTION_MANAGER = "transactionManager";
-
- private static final String ATT_ITEM_READER = "item-reader";
-
- private static final String PROP_ITEM_READER = "itemReader";
-
- private static final String ATT_ITEM_WRITER = "item-writer";
-
- private static final String PROP_ITEM_WRITER = "itemWriter";
-
- private static final String ATT_INPUT_SKIP_LIMIT = "input-skip-limit";
-
- // TODO: Create difference between input skip limit and output skip limit
- private static final String PROP_INPUT_SKIP_LIMIT = "skipLimit";
-
- private static final String ATT_OUTPUT_SKIP_LIMIT = "output-skip-limit";
-
- private static final String PROP_OUTPUT_SKIP_LIMIT = "outputSkipLimit";
-
- public BeanDefinition parse(Element element, ParserContext parserContext) {
- NodeList childNodes = element.getChildNodes();
- for (int i = 0; i < childNodes.getLength(); i++) {
- Node node = childNodes.item(i);
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- String localName = node.getLocalName();
- if (TAG_STEP.equals(localName)) {
- parseStep((Element) node, parserContext);
- } else if (TAG_TASKLET_STEP.equals(localName)) {
- parseTaskletStep((Element) node, parserContext);
- }
- }
- }
- return null;
- }
-
- private void parseStep(Element stepElement, ParserContext parserContext) {
- AbstractBeanDefinition stepDef = createStepBeanDefinition(stepElement, parserContext);
- String id = stepElement.getAttribute(ATT_ID);
-
- if (StringUtils.hasText(id)) {
- parserContext.getRegistry().registerBeanDefinition(id, stepDef);
- } else {
- parserContext.getReaderContext().registerWithGeneratedName(stepDef);
- }
- }
-
- private AbstractBeanDefinition createStepBeanDefinition(Element stepElement, ParserContext parserContext) {
- RootBeanDefinition stepDef = new RootBeanDefinition(ItemOrientedStep.class);
- stepDef.setSource(parserContext.extractSource(stepElement));
- MutablePropertyValues propertyValues = stepDef.getPropertyValues();
-
- String size = stepElement.getAttribute(ATT_SIZE);
- propertyValues.addPropertyValue(PROP_COMMIT_INTERVAL, Integer.valueOf(size));
- String transactionManager = stepElement.getAttribute(ATT_TRANSACTION_MANAGER);
- if (!StringUtils.hasText(transactionManager)) {
- parserContext.getReaderContext().error("'transaction-manager' attribute contains empty value", stepElement);
- } else {
- propertyValues.addPropertyValue(PROP_TRANSACTION_MANAGER, new RuntimeBeanReference(transactionManager));
- }
-
- String itemReader = stepElement.getAttribute(ATT_ITEM_READER);
- if (!StringUtils.hasText(itemReader)) {
- parserContext.getReaderContext().error("'item-reader' attribute contains empty value", stepElement);
- } else {
- propertyValues.addPropertyValue(PROP_ITEM_READER, new RuntimeBeanReference(itemReader));
- }
- String itemWriter = stepElement.getAttribute(ATT_ITEM_WRITER);
- if (!StringUtils.hasText(itemWriter)) {
- parserContext.getReaderContext().error("'item-writer' attribute contains empty value", stepElement);
- } else {
- propertyValues.addPropertyValue(PROP_ITEM_WRITER, new RuntimeBeanReference(itemWriter));
- }
-
- if (stepElement.hasAttribute(ATT_INPUT_SKIP_LIMIT)) {
- String inputSkipLimit = stepElement.getAttribute(ATT_INPUT_SKIP_LIMIT);
- propertyValues.addPropertyValue(PROP_INPUT_SKIP_LIMIT, Integer.valueOf(inputSkipLimit));
- }
-
- // TODO: Create difference between input skip limit and output skip limit
- // if (stepElement.hasAttribute(ATT_OUTPUT_SKIP_LIMIT)) {
- // String outputSkipLimit = stepElement.getAttribute(ATT_OUTPUT_SKIP_LIMIT);
- // propertyValues.addPropertyValue(PROP_OUTPUT_SKIP_LIMIT, Integer.valueOf(outputSkipLimit));
- // }
-
- String rerun = stepElement.getAttribute(ATT_RERUN);
- setPropertiesForRerun(rerun, propertyValues);
- propertyValues.addPropertyValue(PROP_JOB_REPOSITORY, new RuntimeBeanReference(REPOSITORY_BEAN_NAME));
- return stepDef;
- }
-
- private void parseTaskletStep(Element taskletElement, ParserContext parserContext) {
- AbstractBeanDefinition stepDef = createTaskletStepBeanDefinition(taskletElement, parserContext);
- String id = taskletElement.getAttribute(ATT_ID);
-
- if (StringUtils.hasText(id)) {
- parserContext.getRegistry().registerBeanDefinition(id, stepDef);
- } else {
- parserContext.getReaderContext().registerWithGeneratedName(stepDef);
- }
- }
-
- private AbstractBeanDefinition createTaskletStepBeanDefinition(Element taskletElement, ParserContext parserContext) {
- RootBeanDefinition stepDef = new RootBeanDefinition(TaskletStep.class);
- stepDef.setSource(parserContext.extractSource(taskletElement));
- MutablePropertyValues propertyValues = stepDef.getPropertyValues();
-
- String tasklet = taskletElement.getAttribute(ATT_TASKLET);
- if (!StringUtils.hasText(tasklet)) {
- parserContext.getReaderContext().error("'tasklet' attribute contains empty value", taskletElement);
- } else {
- propertyValues.addPropertyValue(PROP_TASKLET, new RuntimeBeanReference(tasklet));
- }
-
- String rerun = taskletElement.getAttribute(ATT_RERUN);
- setPropertiesForRerun(rerun, propertyValues);
- propertyValues.addPropertyValue(PROP_JOB_REPOSITORY, new RuntimeBeanReference(REPOSITORY_BEAN_NAME));
-
- return stepDef;
- }
-
- private void setPropertiesForRerun(String rerun, MutablePropertyValues propertyValues) {
- if (ENUM_ALWAYS.equals(rerun)) {
- propertyValues.addPropertyValue(PROP_ALLOW_START_IF_COMPLETE, Boolean.TRUE);
- propertyValues.addPropertyValue(PROP_START_LIMIT, new Integer(Integer.MAX_VALUE));
- } else if (ENUM_NEVER.equals(rerun)) {
- propertyValues.addPropertyValue(PROP_ALLOW_START_IF_COMPLETE, Boolean.FALSE);
- propertyValues.addPropertyValue(PROP_START_LIMIT, Integer.valueOf(1));
- } else if (ENUM_INCOMPLETE.equals(rerun)) {
- propertyValues.addPropertyValue(PROP_ALLOW_START_IF_COMPLETE, Boolean.FALSE);
- propertyValues.addPropertyValue(PROP_START_LIMIT, new Integer(Integer.MAX_VALUE));
- }
- }
-}
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobEntry.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobEntry.java
deleted file mode 100644
index 4aa503471..000000000
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobEntry.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2002-2007 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.batch.execution.configuration;
-
-import org.springframework.beans.factory.parsing.ParseState;
-
-/**
- * {@link ParseState} entry representing a job.
- *
- * @author Ben Hale
- */
-class JobEntry implements ParseState.Entry {
-
- private final String name;
-
- /**
- * Creates a new instance of the {@link JobEntry} class.
- *
- * @param name the bean name of the job
- */
- JobEntry(String name) {
- this.name = name;
- }
-
- public String toString() {
- return "Job '" + name + "'";
- }
-}
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobRepositoryBeanDefinitionParser.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobRepositoryBeanDefinitionParser.java
deleted file mode 100644
index bafaebef8..000000000
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/JobRepositoryBeanDefinitionParser.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2002-2007 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.batch.execution.configuration;
-
-import org.springframework.batch.execution.repository.SimpleJobRepository;
-import org.springframework.batch.execution.repository.dao.JdbcJobExecutionDao;
-import org.springframework.batch.execution.repository.dao.JdbcJobInstanceDao;
-import org.springframework.batch.execution.repository.dao.JdbcStepExecutionDao;
-import org.springframework.beans.MutablePropertyValues;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.ConstructorArgumentValues;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.beans.factory.xml.BeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.support.incrementer.DB2SequenceMaxValueIncrementer;
-import org.springframework.jdbc.support.incrementer.DerbyMaxValueIncrementer;
-import org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer;
-import org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer;
-import org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer;
-import org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer;
-import org.springframework.util.StringUtils;
-import org.w3c.dom.Element;
-
-/**
- * Creates a {@link BeanDefinitionParser} for the <job-repository> tag.
- *
- * @author Ben Hale
- */
-class JobRepositoryBeanDefinitionParser implements BeanDefinitionParser {
-
- private static final String ATT_DATA_SOURCE = "data-source";
-
- private static final String ATT_DB_TYPE = "db-type";
-
- private static final String ENUM_DB2 = "db2";
-
- private static final String ENUM_DERBY = "derby";
-
- private static final String ENUM_HSQL = "hsql";
-
- private static final String ENUM_MYSQL = "mysql";
-
- private static final String ENUM_ORACLE = "oracle";
-
- private static final String ENUM_POSTGRES = "postgres";
-
- private static final String PROP_JDBC_TEMPLATE = "jdbcTemplate";
-
- private static final String PROP_JOB_INCREMENTER = "jobIncrementer";
-
- private static final String PROP_JOB_EXECUTION_INCREMENTER = "jobExecutionIncrementer";
-
- private static final String PROP_STEP_EXECUTION_INCREMENTER = "stepExecutionIncrementer";
-
- private static final String REPOSITORY_BEAN_NAME = "_jobRepository";
-
- public BeanDefinition parse(Element element, ParserContext parserContext) {
- RootBeanDefinition repositoryDef = new RootBeanDefinition(SimpleJobRepository.class);
-
- String dbType = element.getAttribute(ATT_DB_TYPE);
- String dataSourceId = element.getAttribute(ATT_DATA_SOURCE);
- if (!StringUtils.hasText(dataSourceId)) {
- parserContext.getReaderContext().error("'data-source' attribute contains empty value", element);
- } else {
- ConstructorArgumentValues constructorArgumentValues = repositoryDef.getConstructorArgumentValues();
- String templateId = createJdbcTemplateDefinition(dataSourceId, parserContext);
- constructorArgumentValues.addGenericArgumentValue(createJobInstanceDao(templateId, dataSourceId, dbType,
- parserContext));
- constructorArgumentValues.addGenericArgumentValue(createJobExecutionDao(templateId, dataSourceId, dbType,
- parserContext));
- constructorArgumentValues.addGenericArgumentValue(createStepExecutionDao(templateId, dataSourceId, dbType,
- parserContext));
- }
-
- parserContext.getRegistry().registerBeanDefinition(REPOSITORY_BEAN_NAME, repositoryDef);
- return null;
- }
-
- private String createJdbcTemplateDefinition(String dataSourceId, ParserContext parserContext) {
- RootBeanDefinition templateDef = new RootBeanDefinition(JdbcTemplate.class);
- templateDef.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(dataSourceId));
- return parserContext.getReaderContext().registerWithGeneratedName(templateDef);
- }
-
- private BeanDefinition createJobInstanceDao(String templateId, String dataSourceId, String dbType,
- ParserContext parserContext) {
- RootBeanDefinition daoDef = new RootBeanDefinition(JdbcJobInstanceDao.class);
- MutablePropertyValues propertyValues = daoDef.getPropertyValues();
- propertyValues.addPropertyValue(PROP_JDBC_TEMPLATE, new RuntimeBeanReference(templateId));
- propertyValues.addPropertyValue(PROP_JOB_INCREMENTER, getIncrementer(dbType, dataSourceId, "BATCH_JOB_SEQ"));
- return daoDef;
- }
-
- private BeanDefinition createJobExecutionDao(String templateId, String dataSourceId, String dbType,
- ParserContext parserContext) {
- RootBeanDefinition daoDef = new RootBeanDefinition(JdbcJobExecutionDao.class);
- MutablePropertyValues propertyValues = daoDef.getPropertyValues();
- propertyValues.addPropertyValue(PROP_JDBC_TEMPLATE, new RuntimeBeanReference(templateId));
- propertyValues.addPropertyValue(PROP_JOB_EXECUTION_INCREMENTER, getIncrementer(dbType, dataSourceId,
- "BATCH_JOB_EXECUTION_SEQ"));
- return daoDef;
- }
-
- private BeanDefinition createStepExecutionDao(String templateId, String dataSourceId, String dbType,
- ParserContext parserContext) {
- RootBeanDefinition daoDef = new RootBeanDefinition(JdbcStepExecutionDao.class);
- MutablePropertyValues propertyValues = daoDef.getPropertyValues();
- propertyValues.addPropertyValue(PROP_JDBC_TEMPLATE, new RuntimeBeanReference(templateId));
- propertyValues.addPropertyValue(PROP_STEP_EXECUTION_INCREMENTER, getIncrementer(dbType, dataSourceId,
- "BATCH_STEP_EXECUTION_SEQ"));
- return daoDef;
- }
-
- private BeanDefinition getIncrementer(String dbType, String dataSourceId, String incrementerName) {
- RootBeanDefinition incrementerDef = new RootBeanDefinition();
-
- if (ENUM_DB2.equals(dbType)) {
- incrementerDef.setBeanClass(DB2SequenceMaxValueIncrementer.class);
- addSequenceIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
- } else if (ENUM_DERBY.equals(dbType)) {
- incrementerDef.setBeanClass(DerbyMaxValueIncrementer.class);
- addTableIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
- } else if (ENUM_HSQL.equals(dbType)) {
- incrementerDef.setBeanClass(HsqlMaxValueIncrementer.class);
- addTableIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
- } else if (ENUM_MYSQL.equals(dbType)) {
- incrementerDef.setBeanClass(MySQLMaxValueIncrementer.class);
- addTableIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
- } else if (ENUM_ORACLE.equals(dbType)) {
- incrementerDef.setBeanClass(OracleSequenceMaxValueIncrementer.class);
- addSequenceIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
- } else if (ENUM_POSTGRES.equals(dbType)) {
- incrementerDef.setBeanClass(PostgreSQLSequenceMaxValueIncrementer.class);
- addSequenceIncrementer(dataSourceId, incrementerName, incrementerDef.getConstructorArgumentValues());
- }
-
- return incrementerDef;
- }
-
- private void addSequenceIncrementer(String dataSourceId, String incrementerName,
- ConstructorArgumentValues constructorArgumentValues) {
- constructorArgumentValues.addGenericArgumentValue(new RuntimeBeanReference(dataSourceId));
- constructorArgumentValues.addGenericArgumentValue(incrementerName);
- }
-
- private void addTableIncrementer(String dataSourceId, String incrementerName,
- ConstructorArgumentValues constructorArgumentValues) {
- constructorArgumentValues.addGenericArgumentValue(new RuntimeBeanReference(dataSourceId));
- constructorArgumentValues.addGenericArgumentValue(incrementerName);
- constructorArgumentValues.addGenericArgumentValue("id");
- }
-
-}
diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/TaskletStepEntry.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/TaskletStepEntry.java
deleted file mode 100644
index 245f3b203..000000000
--- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/configuration/TaskletStepEntry.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2002-2007 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.batch.execution.configuration;
-
-import org.springframework.beans.factory.parsing.ParseState;
-
-/**
- * {@link ParseState} entry representing a {@link TaskletStep}.
- *
- * @author Ben Hale
- */
-public class TaskletStepEntry extends AbstractStepEntry {
-
- /**
- * Creates a new instance of the {@link TaskletStepEntry} class.
- *
- * @param name the bean name of the job
- */
- TaskletStepEntry(String name) {
- super(name);
- }
-
- String getType() {
- return "tasklet";
- }
-
-}
diff --git a/spring-batch-execution/src/main/resources/org/springframework/batch/execution/configuration/spring-batch-1.0.xsd b/spring-batch-execution/src/main/resources/org/springframework/batch/execution/configuration/spring-batch-1.0.xsd
index 23bbefbc3..0a4c8d04b 100644
--- a/spring-batch-execution/src/main/resources/org/springframework/batch/execution/configuration/spring-batch-1.0.xsd
+++ b/spring-batch-execution/src/main/resources/org/springframework/batch/execution/configuration/spring-batch-1.0.xsd
@@ -4,60 +4,70 @@
targetNamespace="http://www.springframework.org/schema/batch"
elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
-