IN PROGRESS - BATCH-827: Create Sample job for reading and writing headers and footers

This commit is contained in:
robokaso
2008-09-11 14:21:43 +00:00
parent df870a5df6
commit 2973139959
9 changed files with 212 additions and 19 deletions

View File

@@ -247,8 +247,8 @@ public class FlatFileItemWriter<T> 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<T> extends ExecutionContextUserSupport implement
outputBufferedWriter = getBufferedWriter(fileChannel, encoding);
Assert.state(outputBufferedWriter != null);
// in case of restarting reset position to last committed point
if (restarted) {
checkFileSize();

View File

@@ -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

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.1.0.v200806081427]]></pluginVersion>
<pluginVersion><![CDATA[2.0.6.v200806241357]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
@@ -41,6 +41,7 @@
<config>src/main/resources/staging-test-context.xml</config>
<config>src/main/resources/org/springframework/batch/sample/config/common-context.xml</config>
<config>src/main/resources/jobs/taskletJob.xml</config>
<config>src/main/resources/jobs/headerFooterSample.xml</config>
</configs>
<configSets>
<configSet>
@@ -215,17 +216,6 @@
<config>src/main/resources/org/springframework/batch/sample/config/common-context.xml</config>
</configs>
</configSet>
<configSet>
<name><![CDATA[jmxLauncher]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/resources/adhoc-job-launcher-context.xml</config>
<config>src/main/resources/data-source-context.xml</config>
<config>src/main/resources/simple-job-launcher-context.xml</config>
<config>src/main/resources/org/springframework/batch/sample/config/common-context.xml</config>
</configs>
</configSet>
<configSet>
<name><![CDATA[skipSample]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
@@ -345,5 +335,27 @@
<config>src/main/resources/jobs/taskletJob.xml</config>
</configs>
</configSet>
<configSet>
<name><![CDATA[jmxLauncher]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/resources/adhoc-job-launcher-context.xml</config>
<config>src/main/resources/data-source-context.xml</config>
<config>src/main/resources/simple-job-launcher-context.xml</config>
<config>src/main/resources/org/springframework/batch/sample/config/common-context.xml</config>
</configs>
</configSet>
<configSet>
<name><![CDATA[headerFooter]]></name>
<allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
<incomplete>false</incomplete>
<configs>
<config>src/main/resources/data-source-context.xml</config>
<config>src/main/resources/jobs/headerFooterSample.xml</config>
<config>src/main/resources/org/springframework/batch/sample/config/common-context.xml</config>
<config>src/main/resources/simple-job-launcher-context.xml</config>
</configs>
</configSet>
</configSets>
</beansProjectDescription>

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,5 @@
# next line is a header and should be copied to to output file
names
john
joe
jane

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<description>
Showcases reading and writing of headers and footers. Copies header from input to output and adds a footer.
</description>
<bean id="headerFooterSample" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep" p:commitInterval="3">
<property name="streams">
<list>
<!--
explicit registration to enforce ordering (header needs to be
read before it can be written)
-->
<ref bean="reader" />
<ref bean="writer" />
</list>
</property>
<property name="listeners" ref="footerCallback" />
<property name="itemReader" ref="reader" />
<property name="itemWriter" ref="writer" />
</bean>
</property>
</bean>
<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" ref="inputResource" />
<property name="lineTokenizer">
<bean
class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value="," />
</bean>
</property>
<property name="fieldSetMapper">
<bean
class="org.springframework.batch.item.file.mapping.PassThroughFieldSetMapper" />
</property>
<property name="headerCallback" ref="headerCopier" />
<property name="firstLineIsHeader" value="true" />
</bean>
<bean id="writer" class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" ref="outputResource" />
<property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
<property name="headerCallback" ref="headerCopier" />
<property name="footerCallback" ref="footerCallback" />
</bean>
<bean id="footerCallback" class="org.springframework.batch.sample.support.SummaryFooterCallback" />
<bean id="headerCopier"
class="org.springframework.batch.sample.support.HeaderCopyCallback" />
<bean id="inputResource" class="org.springframework.core.io.ClassPathResource">
<constructor-arg type="java.lang.String"
value="data/headerFooterSample/input.txt" />
</bean>
<bean id="outputResource" class="org.springframework.core.io.FileSystemResource">
<constructor-arg type="java.lang.String"
value="target/test-outputs/headerFooterOutput.txt" />
</bean>
</beans>

View File

@@ -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)));
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<import resource="classpath:/simple-job-launcher-context.xml" />
<import resource="classpath:/jobs/headerFooterSample.xml" />
</beans>