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) 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) 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 annotation : requiredAnnotations) { - if(!field.isAnnotationPresent(annotation)) { - return false; - } - } + private boolean isAnnotated(Field field) { + for (Class 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,