BATCH-1714: Added ChunkListener#afterFailedChunk(ChunkContext context)

This commit is contained in:
Michael Minella
2012-12-28 09:06:37 -06:00
parent 4b20665aa5
commit e8bde07a73
16 changed files with 196 additions and 34 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-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.
@@ -15,44 +15,56 @@
*/
package org.springframework.batch.core.listener;
import static org.easymock.EasyMock.*;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.junit.Before;
import org.junit.Test;
import org.springframework.batch.core.ChunkListener;
import org.springframework.batch.core.listener.CompositeChunkListener;
import org.springframework.batch.core.scope.context.ChunkContext;
/**
* @author Lucas Ward
* @author Michael Minella
*
*/
public class CompositeChunkListenerTests {
ChunkListener listener;
CompositeChunkListener compositeListener;
@Before
public void setUp() throws Exception {
listener = createMock(ChunkListener.class);
compositeListener = new CompositeChunkListener();
compositeListener.register(listener);
}
@Test
public void testBeforeChunk(){
listener.beforeChunk();
replay(listener);
compositeListener.beforeChunk();
verify(listener);
}
@Test
public void testAfterChunk(){
listener.afterChunk();
replay(listener);
compositeListener.afterChunk();
verify(listener);
}
@Test
public void testAfterChunkFailed(){
ChunkContext context = new ChunkContext(null);
listener.afterChunkError(context);
replay(listener);
compositeListener.afterChunkError(context);
verify(listener);
}
}

View File

@@ -18,7 +18,6 @@ package org.springframework.batch.core.listener;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.springframework.batch.core.listener.StepListenerMetaData.AFTER_CHUNK;
import static org.springframework.batch.core.listener.StepListenerMetaData.AFTER_STEP;
import static org.springframework.batch.core.listener.StepListenerMetaData.AFTER_WRITE;
@@ -44,6 +43,8 @@ import org.springframework.batch.core.SkipListener;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.StepListener;
import org.springframework.batch.core.annotation.AfterChunk;
import org.springframework.batch.core.annotation.AfterChunkError;
import org.springframework.batch.core.annotation.AfterProcess;
import org.springframework.batch.core.annotation.AfterRead;
import org.springframework.batch.core.annotation.AfterStep;
@@ -57,6 +58,7 @@ import org.springframework.batch.core.annotation.OnProcessError;
import org.springframework.batch.core.annotation.OnReadError;
import org.springframework.batch.core.annotation.OnWriteError;
import org.springframework.batch.core.configuration.xml.AbstractTestComponent;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
@@ -83,10 +85,10 @@ public class StepListenerFactoryBeanTests {
public void testStepAndChunk() throws Exception {
TestListener testListener = new TestListener();
factoryBean.setDelegate(testListener);
Map<String, String> metaDataMap = new HashMap<String, String>();
metaDataMap.put(AFTER_STEP.getPropertyName(), "destroy");
metaDataMap.put(AFTER_CHUNK.getPropertyName(), "afterChunk");
factoryBean.setMetaDataMap(metaDataMap);
// Map<String, String> metaDataMap = new HashMap<String, String>();
// metaDataMap.put(AFTER_STEP.getPropertyName(), "destroy");
// metaDataMap.put(AFTER_CHUNK.getPropertyName(), "afterChunk");
// factoryBean.setMetaDataMap(metaDataMap);
String readItem = "item";
Integer writeItem = 2;
List<Integer> writeItems = Arrays.asList(writeItem);
@@ -95,6 +97,7 @@ public class StepListenerFactoryBeanTests {
((StepExecutionListener) listener).afterStep(stepExecution);
((ChunkListener) listener).beforeChunk();
((ChunkListener) listener).afterChunk();
((ChunkListener) listener).afterChunkError(new ChunkContext(null));
((ItemReadListener<String>) listener).beforeRead();
((ItemReadListener<String>) listener).afterRead(readItem);
((ItemReadListener<String>) listener).onReadError(new Exception());
@@ -110,6 +113,7 @@ public class StepListenerFactoryBeanTests {
assertTrue(testListener.beforeStepCalled);
assertTrue(testListener.beforeChunkCalled);
assertTrue(testListener.afterChunkCalled);
assertTrue(testListener.afterChunkErrorCalled);
assertTrue(testListener.beforeReadCalled);
assertTrue(testListener.afterReadCalled);
assertTrue(testListener.onReadErrorCalled);
@@ -132,7 +136,6 @@ public class StepListenerFactoryBeanTests {
ThreeStepExecutionListener delegate = new ThreeStepExecutionListener();
factoryBean.setDelegate(delegate);
Map<String, String> metaDataMap = new HashMap<String, String>();
;
metaDataMap.put(AFTER_STEP.getPropertyName(), "destroy");
factoryBean.setMetaDataMap(metaDataMap);
StepListener listener = (StepListener) factoryBean.getObject();
@@ -428,6 +431,8 @@ public class StepListenerFactoryBeanTests {
boolean afterChunkCalled = false;
boolean afterChunkErrorCalled = false;
boolean beforeReadCalled = false;
boolean afterReadCalled = false;
@@ -457,6 +462,7 @@ public class StepListenerFactoryBeanTests {
beforeStepCalled = true;
}
@AfterStep
public void destroy() {
afterStepCalled = true;
}
@@ -466,10 +472,16 @@ public class StepListenerFactoryBeanTests {
beforeChunkCalled = true;
}
@AfterChunk
public void afterChunk() {
afterChunkCalled = true;
}
@AfterChunkError
public void afterChunkError(ChunkContext context) {
afterChunkErrorCalled = true;
}
@BeforeRead
public void beforeReadMethod() {
beforeReadCalled = true;

View File

@@ -29,6 +29,7 @@ import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.StepListener;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.FatalStepExecutionException;
import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean;
import org.springframework.batch.item.ItemReader;
@@ -110,7 +111,7 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
@Test
public void testBeforeChunkListenerException() throws Exception{
factory.setListeners(new StepListener []{new ExceptionThrowingChunkListener(true)});
factory.setListeners(new StepListener []{new ExceptionThrowingChunkListener(1)});
Step step = (Step) factory.getObject();
step.execute(stepExecution);
assertEquals(FAILED, stepExecution.getStatus());
@@ -123,7 +124,7 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
@Test
public void testAfterChunkListenerException() throws Exception{
factory.setListeners(new StepListener []{new ExceptionThrowingChunkListener(false)});
factory.setListeners(new StepListener []{new ExceptionThrowingChunkListener(2)});
Step step = (Step) factory.getObject();
step.execute(stepExecution);
assertEquals(FAILED, stepExecution.getStatus());
@@ -590,24 +591,31 @@ public class FaultTolerantStepFactoryBeanRollbackTests {
class ExceptionThrowingChunkListener implements ChunkListener{
private boolean throwBefore = true;
private int phase = -1;
public ExceptionThrowingChunkListener(boolean throwBefore) {
this.throwBefore = throwBefore;
public ExceptionThrowingChunkListener(int throwPhase) {
this.phase = throwPhase;
}
@Override
public void beforeChunk() {
if(throwBefore){
if(phase == 1){
throw new IllegalArgumentException("Planned exception");
}
}
@Override
public void afterChunk() {
throw new IllegalArgumentException("Planned exception");
if(phase == 2) {
throw new IllegalArgumentException("Planned exception");
}
}
@Override
public void afterChunkError(ChunkContext context) {
if(phase == 3) {
throw new IllegalArgumentException("Planned exception");
}
}
}
}

View File

@@ -33,6 +33,7 @@ import org.springframework.batch.core.StepListener;
import org.springframework.batch.core.listener.SkipListenerSupport;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.factory.FaultTolerantStepFactoryBean;
import org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy;
import org.springframework.batch.core.step.skip.SkipLimitExceededException;
@@ -806,6 +807,9 @@ public class FaultTolerantStepFactoryBeanTests {
listenerCalls.add(5);
}
@Override
public void afterChunkError(ChunkContext context) {
}
}
factory.setItemWriter(new TestItemListenerWriter());
@@ -1109,7 +1113,6 @@ public class FaultTolerantStepFactoryBeanTests {
@SuppressWarnings("serial")
public static class NonExistentException extends Exception {
}
}

View File

@@ -46,6 +46,7 @@ import org.springframework.batch.core.repository.dao.MapJobExecutionDao;
import org.springframework.batch.core.repository.dao.MapJobInstanceDao;
import org.springframework.batch.core.repository.dao.MapStepExecutionDao;
import org.springframework.batch.core.repository.support.SimpleJobRepository;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.AbstractStep;
import org.springframework.batch.core.step.factory.SimpleStepFactoryBean;
import org.springframework.batch.item.ItemProcessor;
@@ -217,7 +218,7 @@ public class SimpleStepFactoryBeanTests {
@Test
public void testChunkListeners() throws Exception {
String[] items = new String[] { "1", "2", "3", "4", "5", "6", "7" };
String[] items = new String[] { "1", "2", "3", "4", "5", "6", "7", "error" };
int commitInterval = 3;
SimpleStepFactoryBean<String, String> factory = getStepFactory(items);
@@ -227,6 +228,10 @@ public class SimpleStepFactoryBeanTests {
@Override
public void beforeWrite(List<? extends Object> items) {
if(items.contains("error")) {
throw new RuntimeException("rollback the last chunk");
}
trail = trail + "2";
}
@@ -241,6 +246,8 @@ public class SimpleStepFactoryBeanTests {
int afterCount = 0;
int failedCount = 0;
private AssertingWriteListener writeListener;
public CountingChunkListener(AssertingWriteListener writeListener) {
@@ -259,6 +266,12 @@ public class SimpleStepFactoryBeanTests {
writeListener.trail = writeListener.trail + "1";
beforeCount++;
}
@Override
public void afterChunkError(ChunkContext context) {
writeListener.trail = writeListener.trail + "5";
failedCount++;
}
}
AssertingWriteListener writeListener = new AssertingWriteListener();
CountingChunkListener chunkListener = new CountingChunkListener(writeListener);
@@ -272,13 +285,15 @@ public class SimpleStepFactoryBeanTests {
JobExecution jobExecution = repository.createJobExecution(job.getName(), new JobParameters());
job.execute(jobExecution);
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
assertNull(reader.read());
assertEquals(items.length, written.size());
assertEquals(6, written.size());
int expectedListenerCallCount = (items.length / commitInterval) + 1;
assertEquals(expectedListenerCallCount, chunkListener.afterCount);
assertEquals(expectedListenerCallCount - 1, chunkListener.afterCount);
assertEquals(expectedListenerCallCount, chunkListener.beforeCount);
assertEquals(1, chunkListener.failedCount);
assertEquals("1234123415", writeListener.trail);
assertTrue("Listener order not as expected: " + writeListener.trail, writeListener.trail.startsWith("1234"));
}
@@ -392,6 +407,10 @@ public class SimpleStepFactoryBeanTests {
public void beforeChunk() {
}
@Override
public void afterChunkError(ChunkContext context) {
}
}
TestItemListenerWriter itemWriter = new TestItemListenerWriter();