OPEN - issue BATCH-498: Skip method should get ExecutionContext as an argument

Handle skip internally in ItemHandler.
This commit is contained in:
dsyer
2008-03-25 17:10:26 +00:00
parent f5fcf3a6b6
commit 7a513d4749
2 changed files with 195 additions and 24 deletions

View File

@@ -0,0 +1,189 @@
/*
* Copyright 2006-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.core.step.item;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.job.JobSupport;
import org.springframework.batch.core.step.StepSupport;
import org.springframework.batch.core.step.skip.AlwaysSkipItemSkipPolicy;
import org.springframework.batch.item.ClearFailedException;
import org.springframework.batch.item.FlushFailedException;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.MarkFailedException;
import org.springframework.batch.item.NoWorkFoundException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.ResetFailedException;
import org.springframework.batch.item.UnexpectedInputException;
/**
* @author Dave Syer
*
*/
public class ItemSkipPolicyItemHandlerTests extends TestCase {
private ItemSkipPolicyItemHandler handler = new ItemSkipPolicyItemHandler(new SkipReaderStub(),
new SkipWriterStub());
private StepContribution contribution = new StepContribution(new JobExecution(new JobInstance(new Long(11),
new JobParameters(), new JobSupport())).createStepExecution(new StepSupport("foo")));
public void testReadWithNoSkip() throws Exception {
assertEquals(new Holder("1"), handler.read(contribution));
try {
handler.read(contribution);
fail("Expected SkippableException");
}
catch (SkippableException e) {
// expected
}
assertEquals(0, contribution.getContributionSkipCount());
assertEquals(new Holder("3"), handler.read(contribution));
}
public void testReadWithSkip() throws Exception {
handler.setItemSkipPolicy(new AlwaysSkipItemSkipPolicy());
assertEquals(new Holder("1"), handler.read(contribution));
assertEquals(new Holder("3"), handler.read(contribution));
assertEquals(1, contribution.getContributionSkipCount());
assertEquals(new Holder("4"), handler.read(contribution));
}
public void testWriteWithNoSkip() throws Exception {
handler.write(new Holder("3"), contribution);
try {
handler.write(new Holder("4"), contribution);
fail("Expected SkippableException");
}
catch (SkippableException e) {
// expected
}
assertEquals(0, contribution.getContributionSkipCount());
}
public void testWriteWithSkip() throws Exception {
handler.setItemSkipPolicy(new AlwaysSkipItemSkipPolicy());
handler.write(new Holder("3"), contribution);
try {
handler.write(new Holder("4"), contribution);
fail("Expected SkippableException");
}
catch (SkippableException e) {
// expected
}
assertEquals(1, contribution.getContributionSkipCount());
}
// TODO: test the item key generator, especially with a mutable item that changes on write
/**
* Simple item reader that supports skip functionality.
*/
private static class SkipReaderStub implements ItemReader {
final Holder[] items = { new Holder("1"), new Holder("2"), new Holder("3"), new Holder("4"), new Holder("5"),
null };
Collection processed = new ArrayList();
int counter = -1;
int marked = 0;
public Object read() throws Exception, UnexpectedInputException, NoWorkFoundException, ParseException {
counter++;
if (counter == 1) {
throw new SkippableException("exception in reader");
}
processed.add(items[counter]);
return items[counter];
}
public void mark() throws MarkFailedException {
marked = counter;
}
public void reset() throws ResetFailedException {
counter = marked;
}
}
/**
* Simple item writer that supports skip functionality.
*/
private static class SkipWriterStub implements ItemWriter {
List written = new ArrayList();
int flushIndex = -1;
public void clear() throws ClearFailedException {
for (int i = flushIndex + 1; i < written.size(); i++) {
written.remove(i);
}
}
public void flush() throws FlushFailedException {
flushIndex = written.size() - 1;
}
public void write(Object item) throws Exception {
written.add(item);
if (((Holder) item).value.equals("4")) {
throw new SkippableException("exception in writer");
}
}
}
private static class SkippableException extends Exception {
public SkippableException(String message) {
super(message);
}
}
private static class Holder {
private String value = null;
public Holder(String value) {
super();
this.value = value;
}
public boolean equals(Object obj) {
return obj instanceof Holder && value.equals(((Holder) obj).value);
}
public int hashCode() {
return value.hashCode();
}
public String toString() {
return "[holder:" + value + "]";
}
}
}

View File

@@ -20,7 +20,6 @@ import org.springframework.batch.item.MarkFailedException;
import org.springframework.batch.item.NoWorkFoundException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.ResetFailedException;
import org.springframework.batch.item.Skippable;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
@@ -67,10 +66,9 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
assertEquals(2, stepExecution.getSkipCount());
assertTrue(reader.skipped.contains("2"));
assertTrue(reader.skipped.contains("4"));
// writer did not skip "2" as it never made it to writer, only "4" did
assertTrue(writer.skipped.contains("4"));
assertTrue(reader.processed.contains("4"));
assertFalse(writer.written.contains("4"));
String[] expectedOutput = { "1", "3", "5" };
@@ -109,11 +107,11 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
/**
* Simple item reader that supports skip functionality.
*/
private static class SkipReaderStub implements ItemReader, Skippable {
private static class SkipReaderStub implements ItemReader {
final String[] items = { "1", "2", "3", "4", "5", null };
Collection skipped = new ArrayList();
Collection processed = new ArrayList();
int counter = -1;
@@ -121,12 +119,10 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
public Object read() throws Exception, UnexpectedInputException, NoWorkFoundException, ParseException {
counter++;
while (skipped.contains(items[counter])) {
counter++;
}
if ("2".equals(items[counter])) {
throw new SkippableException("exception in reader");
}
processed.add(items[counter]);
return items[counter];
}
@@ -138,21 +134,15 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
counter = marked;
}
public void skip() {
skipped.add(items[counter]);
}
}
/**
* Simple item writer that supports skip functionality.
*/
private static class SkipWriterStub implements ItemWriter, Skippable {
private static class SkipWriterStub implements ItemWriter {
List written = new ArrayList();
Collection skipped = new ArrayList();
int flushIndex = -1;
public void clear() throws ClearFailedException {
@@ -166,20 +156,12 @@ public class SkipLimitStepFactoryBeanTests extends TestCase {
}
public void write(Object item) throws Exception {
if (skipped.contains(item)) {
return;
}
written.add(item);
if (item.equals("4")) {
throw new SkippableRuntimeException("exception in writer");
}
}
public void skip() {
int lastIndex = written.size() - 1;
skipped.add(written.get(lastIndex));
}
}
private static class SkippableException extends Exception {