RESOLVED - BATCH-969: FlatFileItemWriters interference in CompositeItemWriter

configurable transactional buffer name in TransactionAwareBufferedWriter
sample showing correct usage of two file writers simultaneously
This commit is contained in:
robokaso
2008-12-15 10:19:36 +00:00
parent 48517b2b93
commit 85f815b094
7 changed files with 99 additions and 66 deletions

View File

@@ -1,29 +1,36 @@
<?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"
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>
<![CDATA[Sample showing usage of CompositeItemWriter.
Note that when two writers of the same class are used simultaneously
they need to be distinguished using the 'name' property
(see the two FlatFileItemWriters used in this example).]]>
</description>
<bean id="compositeItemWriterJob" parent="simpleJob">
<property name="steps">
<bean id="step1" parent="simpleStep">
<property name="streams">
<list>
<ref bean="fileItemReader" />
<ref bean="fileItemWriter" />
<ref bean="fileItemWriter1" />
<ref bean="fileItemWriter2" />
</list>
</property>
<property name="itemReader" ref="fileItemReader" />
<property name="itemProcessor">
<bean class="org.springframework.batch.item.validator.ValidatingItemProcessor">
<bean
class="org.springframework.batch.item.validator.ValidatingItemProcessor">
<constructor-arg ref="fixedValidator" />
</bean>
</property>
</property>
<property name="itemWriter" ref="compositeWriter" />
</bean>
</property>
@@ -39,13 +46,13 @@
class="org.springframework.batch.sample.domain.trade.internal.TradeWriter">
<property name="dao" ref="tradeDao" />
</bean>
<ref bean="fileItemWriter" />
<ref bean="fileItemWriter1" />
<ref bean="fileItemWriter2" />
</list>
</property>
</bean>
<bean id="fileItemReader"
class="org.springframework.batch.item.file.FlatFileItemReader">
<bean id="fileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource"
value="classpath:data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt" />
<property name="lineMapper">
@@ -65,8 +72,7 @@
<bean id="fixedValidator"
class="org.springframework.batch.item.validator.SpringValidator">
<property name="validator">
<bean id="tradeValidator"
class="org.springmodules.validation.valang.ValangValidator">
<bean id="tradeValidator" class="org.springmodules.validation.valang.ValangValidator">
<property name="valang">
<value>
<![CDATA[
@@ -90,15 +96,24 @@
</bean>
<bean class="org.springframework.batch.item.file.FlatFileItemWriter"
id="fileItemWriter">
<property name="resource"
value="file:target/test-outputs/20070122.testStream.ParallelCustomerReportStep.TEMP.txt" />
id="fileItemWriter1">
<property name="name" value="fw1" />
<property name="resource" value="file:target/test-outputs/CustomerReport1.txt" />
<property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
</bean>
<bean class="org.springframework.batch.item.file.FlatFileItemWriter"
id="fileItemWriter2">
<property name="name" value="fw2" />
<property name="resource" value="file:target/test-outputs/CustomerReport2.txt" />
<property name="lineAggregator">
<bean
class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" />
</property>
</bean>
<bean id="fieldSetMapper"
class="org.springframework.batch.sample.domain.trade.internal.TradeFieldSetMapper" />

View File

@@ -21,81 +21,80 @@ import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration()
public class CompositeItemWriterSampleFunctionalTests extends AbstractValidatingBatchLauncherTests {
private static final String GET_TRADES = "SELECT isin, quantity, price, customer FROM trade order by isin";
private static final String EXPECTED_OUTPUT_FILE =
"Trade: [isin=UK21341EAH41,quantity=211,price=31.11,customer=customer1]" +
"Trade: [isin=UK21341EAH42,quantity=212,price=32.11,customer=customer2]" +
"Trade: [isin=UK21341EAH43,quantity=213,price=33.11,customer=customer3]" +
"Trade: [isin=UK21341EAH44,quantity=214,price=34.11,customer=customer4]" +
"Trade: [isin=UK21341EAH45,quantity=215,price=35.11,customer=customer5]";
private static final String EXPECTED_OUTPUT_FILE = "Trade: [isin=UK21341EAH41,quantity=211,price=31.11,customer=customer1]"
+ "Trade: [isin=UK21341EAH42,quantity=212,price=32.11,customer=customer2]"
+ "Trade: [isin=UK21341EAH43,quantity=213,price=33.11,customer=customer3]"
+ "Trade: [isin=UK21341EAH44,quantity=214,price=34.11,customer=customer4]"
+ "Trade: [isin=UK21341EAH45,quantity=215,price=35.11,customer=customer5]";
private SimpleJdbcTemplate simpleJdbcTemplate;
private int activeRow = 0;
private int before;
@Autowired
public void setDataSource(DataSource dataSource) {
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
/* (non-Javadoc)
* @see org.springframework.batch.sample.AbstractLifecycleSpringContextTests#validatePreConditions()
*/
@Override
protected void validatePreConditions() throws Exception {
simpleJdbcTemplate.update("DELETE from TRADE");
before = simpleJdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE");
}
protected void validatePostConditions() throws Exception {
checkOutputFile();
@Override
protected void validatePostConditions() throws Exception {
checkOutputFile("target/test-outputs/CustomerReport1.txt");
checkOutputFile("target/test-outputs/CustomerReport2.txt");
checkOutputTable();
}
private void checkOutputTable() {
final List<Trade> trades = new ArrayList<Trade>() {{
final List<Trade> trades = new ArrayList<Trade>() {
{
add(new Trade("UK21341EAH41", 211, new BigDecimal("31.11"), "customer1"));
add(new Trade("UK21341EAH42", 212, new BigDecimal("32.11"), "customer2"));
add(new Trade("UK21341EAH43", 213, new BigDecimal("33.11"), "customer3"));
add(new Trade("UK21341EAH44", 214, new BigDecimal("34.11"), "customer4"));
add(new Trade("UK21341EAH45", 215, new BigDecimal("35.11"), "customer5"));
}};
}
};
int after = simpleJdbcTemplate.queryForInt("SELECT COUNT(*) from TRADE");
assertEquals(before+5, after);
assertEquals(before + 5, after);
simpleJdbcTemplate.getJdbcOperations().query(GET_TRADES, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
Trade trade = trades.get(activeRow++);
assertEquals(trade.getIsin(), rs.getString(1));
assertEquals(trade.getQuantity(), rs.getLong(2));
assertEquals(trade.getPrice(), rs.getBigDecimal(3));
assertEquals(trade.getCustomer(), rs.getString(4));
}
});
}
@SuppressWarnings("unchecked")
private void checkOutputFile() throws IOException {
List<String> outputLines = IOUtils.readLines(
new FileInputStream("target/test-outputs/20070122.testStream.ParallelCustomerReportStep.TEMP.txt"));
private void checkOutputFile(String fileName) throws IOException {
@SuppressWarnings("unchecked")
List<String> outputLines = IOUtils.readLines(new FileInputStream(fileName));
String output = "";
for (String line : outputLines) {
output += line;
}
assertEquals(EXPECTED_OUTPUT_FILE, output);
}
}