From 3f381ddb89cd80fde07e8bc280ec7fbf83e7151e Mon Sep 17 00:00:00 2001
From: Michael Minella
Date: Mon, 12 Aug 2013 09:11:02 -0500
Subject: [PATCH] BATCH-2072: Implemented wrapper for JSR-352 Decider
---
.../batch/core/jsr/DecisionAdapter.java | 68 ++++++
.../BatchPropertyBeanPostProcessor.java | 205 ++++++++++--------
.../jsr/configuration/xml/DecisionParser.java | 9 +-
.../xml/DecisionStateFactoryBean.java | 102 +++++++++
.../xml/DecisionStateFactoryBeanTests.java | 100 +++++++++
.../configuration/xml/JobPropertyTests.java | 61 +++---
6 files changed, 419 insertions(+), 126 deletions(-)
create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/jsr/DecisionAdapter.java
create mode 100644 spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBean.java
create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBeanTests.java
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/DecisionAdapter.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/DecisionAdapter.java
new file mode 100644
index 000000000..c125123df
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/DecisionAdapter.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 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.core.jsr;
+
+import javax.batch.api.Decider;
+import javax.batch.operations.BatchRuntimeException;
+
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.StepExecution;
+import org.springframework.batch.core.job.flow.FlowExecutionStatus;
+import org.springframework.batch.core.job.flow.JobExecutionDecider;
+import org.springframework.util.Assert;
+
+/**
+ * Wrapper for {@link Decider} implementation to allow it to be used
+ * by the rest of the framework.
+ *
+ * @author Michael Minella
+ * @since 3.0
+ */
+public class DecisionAdapter implements JobExecutionDecider {
+
+ private Decider decider;
+
+ /**
+ * @param decider a {@link Decider}
+ */
+ public DecisionAdapter(Decider decider) {
+ Assert.notNull(decider, "A Decider implementation is required");
+
+ this.decider = decider;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.batch.core.job.flow.JobExecutionDecider#decide(org.springframework.batch.core.JobExecution, org.springframework.batch.core.StepExecution)
+ */
+ @Override
+ public FlowExecutionStatus decide(JobExecution jobExecution,
+ StepExecution stepExecution) {
+
+ javax.batch.runtime.StepExecution [] executions = null;
+
+ //TODO: Address splits
+ if(stepExecution != null) {
+ executions = new org.springframework.batch.core.jsr.StepExecution[1];
+ executions[0] = new org.springframework.batch.core.jsr.StepExecution(stepExecution);
+ }
+
+ try {
+ return new FlowExecutionStatus(decider.decide(executions));
+ } catch (Exception e) {
+ throw new BatchRuntimeException(e);
+ }
+ }
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java
index 2f0bd383e..a2dc5ef68 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/support/BatchPropertyBeanPostProcessor.java
@@ -21,20 +21,34 @@ import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
+
import javax.batch.api.BatchProperty;
import javax.batch.api.Batchlet;
+import javax.batch.api.Decider;
+import javax.batch.api.chunk.CheckpointAlgorithm;
import javax.batch.api.chunk.ItemProcessor;
import javax.batch.api.chunk.ItemReader;
import javax.batch.api.chunk.ItemWriter;
+import javax.batch.api.chunk.listener.ChunkListener;
import javax.batch.api.chunk.listener.ItemProcessListener;
import javax.batch.api.chunk.listener.ItemReadListener;
import javax.batch.api.chunk.listener.ItemWriteListener;
+import javax.batch.api.chunk.listener.RetryProcessListener;
+import javax.batch.api.chunk.listener.RetryReadListener;
+import javax.batch.api.chunk.listener.RetryWriteListener;
+import javax.batch.api.chunk.listener.SkipProcessListener;
+import javax.batch.api.chunk.listener.SkipReadListener;
+import javax.batch.api.chunk.listener.SkipWriteListener;
+import javax.batch.api.listener.JobListener;
+import javax.batch.api.listener.StepListener;
+import javax.batch.api.partition.PartitionAnalyzer;
+import javax.batch.api.partition.PartitionCollector;
+import javax.batch.api.partition.PartitionMapper;
+import javax.batch.api.partition.PartitionPlan;
+import javax.batch.api.partition.PartitionReducer;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.springframework.batch.core.Job;
-import org.springframework.batch.core.Step;
-import org.springframework.batch.core.job.flow.JobExecutionDecider;
-import org.springframework.batch.repeat.CompletionPolicy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
@@ -47,114 +61,129 @@ import org.springframework.util.ReflectionUtils;
*
*
* @author Chris Schaefer
+ * @author Michael Minella
* @since 3.0
*/
public class BatchPropertyBeanPostProcessor implements BeanPostProcessor {
- @Autowired
- private BatchPropertyContext batchPropertyContext;
- private Log logger = LogFactory.getLog(getClass());
- private Set> requiredAnnotations = new HashSet>();
+ @Autowired
+ private BatchPropertyContext batchPropertyContext;
+ private Log logger = LogFactory.getLog(getClass());
+ private Set> requiredAnnotations = new HashSet>();
- public BatchPropertyBeanPostProcessor() {
- setRequiredAnnotations();
- }
+ public BatchPropertyBeanPostProcessor() {
+ setRequiredAnnotations();
+ }
- @Override
- public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
- if (!isBatchArtifact(bean)) {
- return bean;
- }
+ @Override
+ public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
+ if (!isBatchArtifact(bean)) {
+ return bean;
+ }
- final Properties artifactProperties = batchPropertyContext.getBatchProperties(beanName);
+ final Properties artifactProperties = batchPropertyContext.getBatchProperties(beanName);
- if (artifactProperties.isEmpty()) {
- return bean;
- }
+ if (artifactProperties.isEmpty()) {
+ return bean;
+ }
- injectBatchProperties(bean, artifactProperties);
+ injectBatchProperties(bean, artifactProperties);
- return bean;
- }
+ return bean;
+ }
- private void setRequiredAnnotations() {
- ClassLoader cl = BatchPropertyBeanPostProcessor.class.getClassLoader();
+ @SuppressWarnings("unchecked")
+ private void setRequiredAnnotations() {
+ ClassLoader cl = BatchPropertyBeanPostProcessor.class.getClassLoader();
- try {
- this.requiredAnnotations.add((Class extends Annotation>) cl.loadClass("javax.inject.Inject"));
- } catch (ClassNotFoundException ex) {
- logger.warn("javax.inject.Inject not found - @BatchProperty marked fields will not be processed.");
- }
+ try {
+ this.requiredAnnotations.add((Class extends Annotation>) cl.loadClass("javax.inject.Inject"));
+ } catch (ClassNotFoundException ex) {
+ logger.warn("javax.inject.Inject not found - @BatchProperty marked fields will not be processed.");
+ }
- this.requiredAnnotations.add(BatchProperty.class);
- }
+ this.requiredAnnotations.add(BatchProperty.class);
+ }
- private boolean isBatchArtifact(Object bean) {
- return (bean instanceof ItemReader) ||
- (bean instanceof ItemProcessor) ||
- (bean instanceof ItemWriter) ||
- (bean instanceof CompletionPolicy) ||
- (bean instanceof Batchlet) ||
- (bean instanceof ItemReadListener) ||
- (bean instanceof ItemProcessListener) ||
- (bean instanceof ItemWriteListener) ||
- (bean instanceof JobExecutionDecider) ||
- (bean instanceof Step) ||
- (bean instanceof Job);
- }
+ private boolean isBatchArtifact(Object bean) {
+ return (bean instanceof ItemReader) ||
+ (bean instanceof ItemProcessor) ||
+ (bean instanceof ItemWriter) ||
+ (bean instanceof CheckpointAlgorithm) ||
+ (bean instanceof Batchlet) ||
+ (bean instanceof ItemReadListener) ||
+ (bean instanceof ItemProcessListener) ||
+ (bean instanceof ItemWriteListener) ||
+ (bean instanceof JobListener) ||
+ (bean instanceof StepListener) ||
+ (bean instanceof ChunkListener) ||
+ (bean instanceof SkipReadListener) ||
+ (bean instanceof SkipProcessListener) ||
+ (bean instanceof SkipWriteListener) ||
+ (bean instanceof RetryReadListener) ||
+ (bean instanceof RetryProcessListener) ||
+ (bean instanceof RetryWriteListener) ||
+ (bean instanceof PartitionMapper) ||
+ (bean instanceof PartitionReducer) ||
+ (bean instanceof PartitionCollector) ||
+ (bean instanceof PartitionAnalyzer) ||
+ (bean instanceof PartitionPlan) ||
+ (bean instanceof Decider);
+ }
- private void injectBatchProperties(final Object bean, final Properties artifactProperties) {
- ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
- public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
- if (isValidFieldModifier(field) && isAnnotated(field)) {
- boolean isAccessible = field.isAccessible();
- field.setAccessible(true);
+ private void injectBatchProperties(final Object bean, final Properties artifactProperties) {
+ ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
+ @Override
+ public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
+ if (isValidFieldModifier(field) && isAnnotated(field)) {
+ boolean isAccessible = field.isAccessible();
+ field.setAccessible(true);
- String batchProperty = getBatchPropertyFieldValue(field, artifactProperties);
+ String batchProperty = getBatchPropertyFieldValue(field, artifactProperties);
- if (batchProperty != null) {
- field.set(bean, batchProperty);
- }
+ if (batchProperty != null) {
+ field.set(bean, batchProperty);
+ }
- field.setAccessible(isAccessible);
- }
- }
- });
- }
+ field.setAccessible(isAccessible);
+ }
+ }
+ });
+ }
- private String getBatchPropertyFieldValue(Field field, Properties batchArtifactProperties) {
- BatchProperty batchProperty = field.getAnnotation(BatchProperty.class);
+ private String getBatchPropertyFieldValue(Field field, Properties batchArtifactProperties) {
+ BatchProperty batchProperty = field.getAnnotation(BatchProperty.class);
- if (!"".equals(batchProperty.name())) {
- return getBatchProperty(batchProperty.name(), batchArtifactProperties);
- }
+ if (!"".equals(batchProperty.name())) {
+ return getBatchProperty(batchProperty.name(), batchArtifactProperties);
+ }
- return getBatchProperty(field.getName(), batchArtifactProperties);
- }
+ return getBatchProperty(field.getName(), batchArtifactProperties);
+ }
- private String getBatchProperty(String propertyKey, Properties batchArtifactProperties) {
- if (batchArtifactProperties.containsKey(propertyKey)) {
- return (String) batchArtifactProperties.get(propertyKey);
- }
+ private String getBatchProperty(String propertyKey, Properties batchArtifactProperties) {
+ if (batchArtifactProperties.containsKey(propertyKey)) {
+ return (String) batchArtifactProperties.get(propertyKey);
+ }
- return null;
- }
+ return null;
+ }
- private boolean isAnnotated(Field field) {
- for (Class extends Annotation> annotation : requiredAnnotations) {
- if(!field.isAnnotationPresent(annotation)) {
- return false;
- }
- }
+ private boolean isAnnotated(Field field) {
+ for (Class extends Annotation> annotation : requiredAnnotations) {
+ if(!field.isAnnotationPresent(annotation)) {
+ return false;
+ }
+ }
- return true;
- }
+ return true;
+ }
- private boolean isValidFieldModifier(Field field) {
- return !Modifier.isStatic(field.getModifiers()) && !Modifier.isFinal(field.getModifiers());
- }
+ private boolean isValidFieldModifier(Field field) {
+ return !Modifier.isStatic(field.getModifiers()) && !Modifier.isFinal(field.getModifiers());
+ }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- return bean;
- }
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionParser.java
index bdee142e0..81e584b63 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionParser.java
@@ -19,7 +19,6 @@ import java.util.Collection;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
@@ -27,7 +26,7 @@ import org.w3c.dom.Element;
/**
* Parser for the <decision /> element as specified in JSR-352. The current state
* parses a decision element and assumes that it refers to a {@link JobExecutionDecider}
- *
+ *
* @author Michael Minella
* @author Chris Schaefer
* @since 3.0
@@ -42,9 +41,9 @@ public class DecisionParser {
String idAttribute = element.getAttribute(ID_ATTRIBUTE);
BeanDefinitionBuilder stateBuilder =
- BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.DecisionState");
- stateBuilder.addConstructorArgValue(new RuntimeBeanReference(refAttribute));
- stateBuilder.addConstructorArgValue(idAttribute);
+ BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.jsr.configuration.xml.DecisionStateFactoryBean");
+ stateBuilder.addPropertyReference("decider", refAttribute);
+ stateBuilder.addPropertyValue("name", idAttribute);
new PropertyParser(refAttribute, parserContext).parseProperties(element);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBean.java
new file mode 100644
index 000000000..ec2036ee6
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBean.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2013 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.core.jsr.configuration.xml;
+
+import javax.batch.api.Decider;
+
+import org.springframework.batch.core.job.flow.JobExecutionDecider;
+import org.springframework.batch.core.job.flow.State;
+import org.springframework.batch.core.job.flow.support.state.DecisionState;
+import org.springframework.batch.core.jsr.DecisionAdapter;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.Assert;
+
+/**
+ * {@link FactoryBean} for creating a {@link DecisionState}. If the underlying
+ * decider is a {@link Decider}, it will be wrapped in a {@link DecisionAdapter}.
+ *
+ * @author Michael Minella
+ * @since 3.0
+ */
+public class DecisionStateFactoryBean implements FactoryBean, InitializingBean {
+
+ private Decider jsrDecider;
+ private JobExecutionDecider decider;
+ private String name;
+
+ /**
+ * @param decider either a {@link Decider} or a {@link JobExecutionDecider}
+ * @throws IllegalArgumentException if the type passed in is not a valid type
+ */
+ public void setDecider(Object decider) {
+ if(decider instanceof JobExecutionDecider) {
+ this.decider = (JobExecutionDecider) decider;
+ } else if(decider instanceof Decider) {
+ this.jsrDecider = (Decider) decider;
+ } else {
+ throw new IllegalArgumentException("Invalid type for a decider");
+ }
+ }
+
+ /**
+ * The name of the state
+ *
+ * @param name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#getObject()
+ */
+ @Override
+ public State getObject() throws Exception {
+ JobExecutionDecider wrappedDecider = null;
+
+ if(decider != null) {
+ wrappedDecider = decider;
+ } else if(jsrDecider != null) {
+ wrappedDecider = new DecisionAdapter(jsrDecider);
+ }
+ State state = new DecisionState(wrappedDecider, name);
+
+ return state;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#getObjectType()
+ */
+ @Override
+ public Class> getObjectType() {
+ return JobExecutionDecider.class;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#isSingleton()
+ */
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ Assert.isTrue(!(decider == null && jsrDecider == null), "A decider implementation is required");
+ Assert.notNull(name, "A name is required for a decision state");
+ }
+}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBeanTests.java
new file mode 100644
index 000000000..763ebbda8
--- /dev/null
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/DecisionStateFactoryBeanTests.java
@@ -0,0 +1,100 @@
+package org.springframework.batch.core.jsr.configuration.xml;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import javax.batch.api.Decider;
+import javax.batch.runtime.StepExecution;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.job.flow.FlowExecutionStatus;
+import org.springframework.batch.core.job.flow.JobExecutionDecider;
+import org.springframework.batch.core.job.flow.State;
+import org.springframework.batch.core.job.flow.support.state.DecisionState;
+
+public class DecisionStateFactoryBeanTests {
+
+ private DecisionStateFactoryBean factoryBean;
+
+ @Before
+ public void setUp() throws Exception {
+ factoryBean = new DecisionStateFactoryBean();
+ }
+
+ @Test
+ public void testGetObjectType() {
+ assertEquals(JobExecutionDecider.class, factoryBean.getObjectType());
+ }
+
+ @Test
+ public void testIsSingleton() {
+ assertTrue(factoryBean.isSingleton());
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testNullDeciderAndName() throws Exception {
+ factoryBean.afterPropertiesSet();
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testNullDecider() throws Exception{
+ factoryBean.setName("state1");
+ factoryBean.afterPropertiesSet();
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testNullName() throws Exception {
+ factoryBean.setDecider(new DeciderSupport());
+ factoryBean.afterPropertiesSet();
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void setWrongDeciderType() {
+ factoryBean.setDecider("Some decider");
+ }
+
+ @Test
+ public void testJobExecutionDeciderState() throws Exception {
+ factoryBean.setDecider(new JobExecutionDeciderSupport());
+ factoryBean.setName("IL");
+
+ factoryBean.afterPropertiesSet();
+
+ State state = factoryBean.getObject();
+
+ assertEquals("IL", state.getName());
+ assertEquals(DecisionState.class, state.getClass());
+ }
+
+ @Test
+ public void testDeciderDeciderState() throws Exception {
+ factoryBean.setDecider(new DeciderSupport());
+ factoryBean.setName("IL");
+
+ factoryBean.afterPropertiesSet();
+
+ State state = factoryBean.getObject();
+
+ assertEquals("IL", state.getName());
+ assertEquals(DecisionState.class, state.getClass());
+ }
+
+ public static class DeciderSupport implements Decider {
+
+ @Override
+ public String decide(StepExecution[] executions) throws Exception {
+ return null;
+ }
+ }
+
+ public static class JobExecutionDeciderSupport implements JobExecutionDecider {
+
+ @Override
+ public FlowExecutionStatus decide(JobExecution jobExecution,
+ org.springframework.batch.core.StepExecution stepExecution) {
+ return null;
+ }
+ }
+}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/JobPropertyTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/JobPropertyTests.java
index c7e177b07..cd358b226 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/JobPropertyTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/jsr/configuration/xml/JobPropertyTests.java
@@ -24,6 +24,8 @@ import java.util.List;
import javax.batch.api.BatchProperty;
import javax.batch.api.Batchlet;
+import javax.batch.api.Decider;
+import javax.batch.api.chunk.CheckpointAlgorithm;
import javax.batch.api.chunk.ItemProcessor;
import javax.batch.api.chunk.ItemReader;
import javax.batch.api.chunk.ItemWriter;
@@ -37,13 +39,7 @@ import org.springframework.batch.core.ExitStatus;
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.FlowExecutionStatus;
-import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.launch.JobLauncher;
-import org.springframework.batch.repeat.CompletionPolicy;
-import org.springframework.batch.repeat.RepeatContext;
-import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
@@ -335,32 +331,13 @@ public class JobPropertyTests {
}
}
- public static final class TestCheckpointAlgorithm implements CompletionPolicy {
+ public static final class TestCheckpointAlgorithm implements CheckpointAlgorithm {
@Inject @BatchProperty String algorithmPropertyName1;
@Inject @BatchProperty String algorithmPropertyName2;
@Inject @BatchProperty(name = "annotationNamedAlgorithmPropertyName") String annotationNamedProperty;
@Inject @BatchProperty String notDefinedProperty;
@Inject @BatchProperty(name = "notDefinedAnnotationNamedProperty") String notDefinedAnnotationNamedProperty;
- @Override
- public boolean isComplete(RepeatContext context, RepeatStatus result) {
- return true;
- }
-
- @Override
- public boolean isComplete(RepeatContext context) {
- return true;
- }
-
- @Override
- public RepeatContext start(RepeatContext parent) {
- return parent;
- }
-
- @Override
- public void update(RepeatContext context) {
- }
-
String getAlgorithmPropertyName1() {
return algorithmPropertyName1;
}
@@ -380,21 +357,33 @@ public class JobPropertyTests {
String getNotDefinedAnnotationNamedProperty() {
return notDefinedAnnotationNamedProperty;
}
+
+ @Override
+ public int checkpointTimeout() throws Exception {
+ return 0;
+ }
+
+ @Override
+ public void beginCheckpoint() throws Exception {
+ }
+
+ @Override
+ public boolean isReadyToCheckpoint() throws Exception {
+ return true;
+ }
+
+ @Override
+ public void endCheckpoint() throws Exception {
+ }
}
- public static class TestDecider implements JobExecutionDecider {
+ public static class TestDecider implements Decider {
@Inject @BatchProperty String deciderPropertyName1;
@Inject @BatchProperty String deciderPropertyName2;
@Inject @BatchProperty(name = "annotationNamedDeciderPropertyName") String annotationNamedProperty;
@Inject @BatchProperty String notDefinedProperty;
@Inject @BatchProperty(name = "notDefinedAnnotationNamedProperty") String notDefinedAnnotationNamedProperty;
- @Override
- public FlowExecutionStatus decide(JobExecution jobExecution,
- StepExecution stepExecution) {
- return new FlowExecutionStatus("step2");
- }
-
String getDeciderPropertyName1() {
return deciderPropertyName1;
}
@@ -414,6 +403,12 @@ public class JobPropertyTests {
String getNotDefinedAnnotationNamedProperty() {
return notDefinedAnnotationNamedProperty;
}
+
+ @Override
+ public String decide(javax.batch.runtime.StepExecution[] executions)
+ throws Exception {
+ return "step2";
+ }
}
public static class TestStepListener implements javax.batch.api.chunk.listener.ItemReadListener,