diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java index d74b7da7b..3636a1b9f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java @@ -247,8 +247,8 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement if (outputState.lastMarkedByteOffsetPosition == 0) { if (headerCallback != null) { try { - headerCallback.write(state.outputBufferedWriter); - state.write("\n"); + headerCallback.write(outputState.outputBufferedWriter); + outputState.write("\n"); } catch (IOException e) { throw new FlushFailedException("Could not write headers. The file may be corrupt.", e); @@ -422,6 +422,7 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement outputBufferedWriter = getBufferedWriter(fileChannel, encoding); + Assert.state(outputBufferedWriter != null); // in case of restarting reset position to last committed point if (restarted) { checkFileSize(); diff --git a/spring-batch-samples/.settings/org.springframework.ide.eclipse.core.prefs b/spring-batch-samples/.settings/org.springframework.ide.eclipse.core.prefs index 1058cc07e..dfc176ba0 100644 --- a/spring-batch-samples/.settings/org.springframework.ide.eclipse.core.prefs +++ b/spring-batch-samples/.settings/org.springframework.ide.eclipse.core.prefs @@ -1,14 +1,14 @@ -#Mon Aug 11 02:58:58 EDT 2008 +#Thu Sep 11 14:26:57 CEST 2008 eclipse.preferences.version=1 org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true -org.springframework.ide.eclipse.core.builders.enable.beanmetadatabuilder=true +org.springframework.ide.eclipse.core.builders.enable.beanmetadatabuilder=false org.springframework.ide.eclipse.core.builders.enable.osgibundleupdater=true org.springframework.ide.eclipse.core.enable.project.preferences=false org.springframework.ide.eclipse.core.validator.enable.com.springsource.platform.ide.manifest.core.manifestvalidator=true org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.ap.quickfix.manifestvalidator=true org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.bestpractices.beansvalidator=true org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=true +org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=false org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=true org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.applicationSymbolicNameRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.platform.ide.manifest.core.applicationVersionRule-com.springsource.platform.ide.manifest.core.manifestvalidator=true @@ -45,8 +45,8 @@ org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.i org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=true org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.methodOverride-org.springframework.ide.eclipse.beans.core.beansvalidator=true org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.parsingProblems-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=true -org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=true +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false +org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=false org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=true org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=true org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=true diff --git a/spring-batch-samples/.springBeans b/spring-batch-samples/.springBeans index c57300f79..7c73069e8 100644 --- a/spring-batch-samples/.springBeans +++ b/spring-batch-samples/.springBeans @@ -1,7 +1,7 @@ 1 - + @@ -41,6 +41,7 @@ src/main/resources/staging-test-context.xml src/main/resources/org/springframework/batch/sample/config/common-context.xml src/main/resources/jobs/taskletJob.xml + src/main/resources/jobs/headerFooterSample.xml @@ -215,17 +216,6 @@ src/main/resources/org/springframework/batch/sample/config/common-context.xml - - - true - false - - src/main/resources/adhoc-job-launcher-context.xml - src/main/resources/data-source-context.xml - src/main/resources/simple-job-launcher-context.xml - src/main/resources/org/springframework/batch/sample/config/common-context.xml - - true @@ -345,5 +335,27 @@ src/main/resources/jobs/taskletJob.xml + + + true + false + + src/main/resources/adhoc-job-launcher-context.xml + src/main/resources/data-source-context.xml + src/main/resources/simple-job-launcher-context.xml + src/main/resources/org/springframework/batch/sample/config/common-context.xml + + + + + true + false + + src/main/resources/data-source-context.xml + src/main/resources/jobs/headerFooterSample.xml + src/main/resources/org/springframework/batch/sample/config/common-context.xml + src/main/resources/simple-job-launcher-context.xml + + diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/HeaderCopyCallback.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/HeaderCopyCallback.java new file mode 100644 index 000000000..23340ac68 --- /dev/null +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/HeaderCopyCallback.java @@ -0,0 +1,32 @@ +package org.springframework.batch.sample.support; + +import java.io.IOException; +import java.io.Writer; + + +import org.springframework.batch.item.file.FileWriterCallback; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.FlatFileItemWriter; +import org.springframework.batch.item.file.LineCallbackHandler; +import org.springframework.util.Assert; + +/** + * Designed to be registered with both {@link FlatFileItemReader} and + * {@link FlatFileItemWriter} and copy header line from input file to output + * file. + */ +public class HeaderCopyCallback implements LineCallbackHandler, FileWriterCallback { + + private String header = ""; + + public void handleLine(String line) { + Assert.notNull(line); + this.header = line; + } + + public void write(Writer writer) throws IOException { + writer.write("header from input: " + header); + + } + +} diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/SummaryFooterCallback.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/SummaryFooterCallback.java new file mode 100644 index 000000000..cc0f89596 --- /dev/null +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/support/SummaryFooterCallback.java @@ -0,0 +1,27 @@ +package org.springframework.batch.sample.support; + +import java.io.IOException; +import java.io.Writer; + +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.listener.StepExecutionListenerSupport; +import org.springframework.batch.item.file.FileWriterCallback; + +/** + * Writes summary info in the footer of a file. + */ +public class SummaryFooterCallback extends StepExecutionListenerSupport implements FileWriterCallback{ + + private StepExecution stepExecution; + + public void write(Writer writer) throws IOException { + writer.write("footer - number of items written: " + stepExecution.getWriteCount()); + } + + @Override + public void beforeStep(StepExecution stepExecution) { + this.stepExecution = stepExecution; + } + + +} diff --git a/spring-batch-samples/src/main/resources/data/headerFooterSample/input.txt b/spring-batch-samples/src/main/resources/data/headerFooterSample/input.txt new file mode 100644 index 000000000..da7709d50 --- /dev/null +++ b/spring-batch-samples/src/main/resources/data/headerFooterSample/input.txt @@ -0,0 +1,5 @@ +# next line is a header and should be copied to to output file +names +john +joe +jane \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/jobs/headerFooterSample.xml b/spring-batch-samples/src/main/resources/jobs/headerFooterSample.xml new file mode 100644 index 000000000..fff0cf5ef --- /dev/null +++ b/spring-batch-samples/src/main/resources/jobs/headerFooterSample.xml @@ -0,0 +1,66 @@ + + + + Showcases reading and writing of headers and footers. Copies header from input to output and adds a footer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests.java new file mode 100644 index 000000000..abd9ad7f5 --- /dev/null +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests.java @@ -0,0 +1,40 @@ +package org.springframework.batch.sample; + +import java.io.BufferedReader; +import java.io.FileReader; + +import static org.junit.Assert.*; +import org.junit.runner.RunWith; +import org.springframework.core.io.Resource; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class HeaderFooterSampleFunctionalTests extends AbstractValidatingBatchLauncherTests { + + @Override + protected void validatePostConditions() throws Exception { + Resource input = (Resource) applicationContext.getBean("inputResource", Resource.class); + Resource output = (Resource) applicationContext.getBean("outputResource", Resource.class); + + BufferedReader inputReader = new BufferedReader(new FileReader(input.getFile())); + BufferedReader outputReader = new BufferedReader(new FileReader(output.getFile())); + + // skip initial comment from input file + inputReader.readLine(); + + String line; + + int lineCount = 0; + while ((line = inputReader.readLine()) != null) { + lineCount++; + assertTrue("input line should correspond to output line", outputReader.readLine().contains(line)); + } + + // footer contains the item count + int itemCount = lineCount - 1; // minus 1 due to header line + assertTrue(outputReader.readLine().contains(String.valueOf(itemCount))); + } + +} diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests-context.xml new file mode 100644 index 000000000..5ac797e16 --- /dev/null +++ b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/HeaderFooterSampleFunctionalTests-context.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file