From 73264ff40de2b7c75c1b5feabd2029d0e1048b2d Mon Sep 17 00:00:00 2001 From: dhgarrette Date: Sat, 6 Jun 2009 17:50:23 +0000 Subject: [PATCH] BATCH-1276: Change Common Pattern "Writing a Summary Footer" to use AfterWrite for updating total. --- .../docbook/reference/common-patterns.xml | 72 +++++++++++-------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/src/site/docbook/reference/common-patterns.xml b/src/site/docbook/reference/common-patterns.xml index 9e3f132ed..754f7862a 100644 --- a/src/site/docbook/reference/common-patterns.xml +++ b/src/site/docbook/reference/common-patterns.xml @@ -195,22 +195,32 @@ the end of the file. This footer serves as a summarization of the file or provides a checksum. - For example, if a batch job is writing Trade records to a flat - file, and there is a requirement that the total amount from all the - Trades is placed in a footer, then the following ItemWriter - implementation can be used: + For example, if a batch job is writing + Trade records to a flat file, and there is a + requirement that the total amount from all the + Trades is placed in a footer, then the following + ItemWriter implementation can be used: public class TradeItemWriter implements ItemWriter<Trade>, FlatFileFooterCallback { private ItemWriter<Trade> delegate; - private double totalAmount = 0.0; + private BigDecimal totalAmount = BigDecimal.ZERO; public void write(List<? extends Trade> items) { + for (Trade trade : items) { + // There must be an amount to total + Assert.notNull(trade.getAmount()); + } + delegate.write(items); - for(Trade trade : items) { - totalAmount += trade.getAmount(); + } + + @AfterWrite + public void updateTotalPrice(List<Trade> trades) { + for (Trade trade : trades) { + totalAmount = totalAmount.add(trade.getAmount()); } } @@ -226,9 +236,21 @@ amount from each Trade item written. After the last Trade is processed, the framework will call writeFooter, which will put that - totalAmount into the file. In order for the method to be - called, the TradeItemWriter must be wired into - the FlatFileItemWriter as the + totalAmount into the file. Note that the + totalAmount is not updated in + the write method; it is updated in the + AfterWrite method. This is done to ensure that if + a skip occurs in the write method, that the + totalAmount will be left unchanged. The + write method also validates that the + amount on each Trade is not + null; this guarantees that no exceptions will be thrown by the + AfterWrite method. + + In order for the writeFooter method to be + called, the TradeItemWriter (which implements + FlatFileFooterCallback) must be wired into the + FlatFileItemWriter as the footerCallback: <bean id="tradeItemWriter" class="..TradeItemWriter"> @@ -236,9 +258,9 @@ </bean> <bean id="flatFileItemWriter" class="org.spr...FlatFileItemWriter"> - <property name="resource" ref="outputResource" /> - <property name="lineAggregator" ref="lineAggregator"/> - <property name="footerCallback" ref="tradeItemWriter" /> + <property name="resource" ref="outputResource" /> + <property name="lineAggregator" ref="lineAggregator"/> + <property name="footerCallback" ref="tradeItemWriter" /> </bean> The way that the TradeItemWriter has been @@ -251,17 +273,17 @@ with the methods open and update: - private static final String TOTAL_AMOUNT_KEY = "total.amount"; + private static final String TOTAL_AMOUNT_KEY = "total.amount"; - public void open(ExecutionContext executionContext) { - if (executionContext.containsKey(TOTAL_AMOUNT_KEY) { - totalAmount = executionContext.getDouble(TOTAL_AMOUNT_KEY); - } - } +public void open(ExecutionContext executionContext) { + if (executionContext.containsKey(TOTAL_AMOUNT_KEY) { + totalAmount = (BigDecimal) executionContext.get(TOTAL_AMOUNT_KEY); + } +} - public void update(ExecutionContext executionContext) { - executionContext.setDouble(TOTAL_AMOUNT_KEY, totalAmount); - } +public void update(ExecutionContext executionContext) { + executionContext.put(TOTAL_AMOUNT_KEY, totalAmount); +} The update method will store the most current version of totalAmount to the @@ -272,12 +294,6 @@ for processing, allowing the TradeItemWriter to pick up on restart where it left off the previous time the Step was executed. - - It should be noted that it is not always necessary to implement - ItemStream. For example, if the - ItemWriter is re-runnable, meaning that it - maintains its own state in a transactional resource like a database, - there is no need to maintain state within the writer itself.