BATCH-1714: Added ChunkListener#afterFailedChunk(ChunkContext context)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user