EMMA Coverage Report (generated Fri Jan 30 13:20:29 EST 2009)
[all classes][org.springframework.batch.item.database]

COVERAGE SUMMARY FOR SOURCE FILE [AbstractTransactionalResourceItemWriter.java]

nameclass, %method, %block, %line, %
AbstractTransactionalResourceItemWriter.java100% (1/1)100% (8/8)88%  (111/126)97%  (38/39)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AbstractTransactionalResourceItemWriter100% (1/1)100% (8/8)88%  (111/126)97%  (38/39)
clear (): void 100% (1/1)55%  (6/11)88%  (3.5/4)
flushIfNecessary (Object): void 100% (1/1)79%  (19/24)96%  (6.7/7)
flush (): void 100% (1/1)86%  (30/35)98%  (9.8/10)
AbstractTransactionalResourceItemWriter (): void 100% (1/1)100% (8/8)100% (2/2)
bindTransactionResources (): void 100% (1/1)100% (12/12)100% (4/4)
getProcessed (): Set 100% (1/1)100% (12/12)100% (3/3)
unbindTransactionResources (): void 100% (1/1)100% (10/10)100% (4/4)
write (Object): void 100% (1/1)100% (14/14)100% (5/5)

1/*
2 * Copyright 2006-2007 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.springframework.batch.item.database;
17 
18import java.util.HashSet;
19import java.util.Set;
20 
21import org.springframework.batch.item.ClearFailedException;
22import org.springframework.batch.item.FlushFailedException;
23import org.springframework.batch.item.ItemWriter;
24import org.springframework.batch.repeat.RepeatContext;
25import org.springframework.batch.repeat.support.RepeatSynchronizationManager;
26import org.springframework.transaction.support.TransactionSynchronizationManager;
27import org.springframework.util.Assert;
28 
29/**
30 * Stores items in transactional resource and flushes aggressively in case of
31 * failure. This is useful for batch update writers which need to identify the
32 * failed item after failed flush.
33 * 
34 * @see BatchSqlUpdateItemWriter
35 * @see HibernateAwareItemWriter
36 * 
37 * @author Dave Syer
38 * @author Robert Kasanicky
39 */
40public abstract class AbstractTransactionalResourceItemWriter implements ItemWriter {
41 
42        private Set failed = new HashSet();
43 
44        /**
45         * Flushing delegated to subclass surrounded by binding and unbinding of
46         * transactional resources.
47         * 
48         * @see org.springframework.batch.item.ItemWriter#flush()
49         */
50        public void flush() throws FlushFailedException {
51                bindTransactionResources();
52                try {
53                        doFlush();
54                }
55                catch (RuntimeException e) {
56                        synchronized (failed) {
57                                failed.addAll(getProcessed());
58                        }
59                        // This used to contain a call to onError, however, I think this
60                        // should be handled within the step.
61                        throw e;
62                }
63                finally {
64                        unbindTransactionResources();
65                }
66        }
67 
68        /**
69         * Delegate to subclass to actually do the writing, but flushes aggressively
70         * if the item was previously part of a failed chunk.
71         * 
72         * @throws Exception
73         * 
74         * @see org.springframework.batch.item.ItemWriter#write(Object)
75         */
76        public void write(Object output) throws Exception {
77                bindTransactionResources();
78                getProcessed().add(output);
79                doWrite(output);
80                flushIfNecessary(output);
81        }
82 
83        private void flushIfNecessary(Object output) {
84                boolean flush;
85                synchronized (failed) {
86                        flush = failed.contains(output);
87                }
88                if (flush) {
89                        // Force early completion to commit aggressively if we encounter a
90                        // failed item (from a failed chunk but we don't know which one was
91                        // the problem).
92                        RepeatSynchronizationManager.setCompleteOnly();
93                        // Flush now, so that if there is a failure this record can be
94                        // skipped.
95                        flush();
96                }
97 
98        }
99 
100        /**
101         * Delegate to subclass and unbind transactional resources, effectively
102         * clearing the item buffer.
103         */
104        public void clear() throws ClearFailedException {
105                try {
106                        doClear();
107                }
108                finally {
109                        unbindTransactionResources();
110                }
111        }
112 
113        /**
114         * Callback method of {@link #flush()}.
115         */
116        protected abstract void doFlush() throws FlushFailedException;
117 
118        /**
119         * Callback method of {@link #clear()}.
120         */
121        protected abstract void doClear() throws ClearFailedException;
122 
123        /**
124         * Callback method of {@link #write(Object)}.
125         */
126        protected abstract void doWrite(Object output) throws Exception;
127 
128        /**
129         * @return Key for items processed in the current transaction
130         * {@link RepeatContext}.
131         */
132        protected abstract String getResourceKey();
133 
134        /**
135         * Set up the {@link RepeatContext} as a transaction resource.
136         * 
137         * @param context the context to set
138         */
139        private void bindTransactionResources() {
140                if (TransactionSynchronizationManager.hasResource(getResourceKey())) {
141                        return;
142                }
143                TransactionSynchronizationManager.bindResource(getResourceKey(), new HashSet());
144        }
145 
146        /**
147         * Remove the transaction resource associated with this context.
148         */
149        private void unbindTransactionResources() {
150                if (!TransactionSynchronizationManager.hasResource(getResourceKey())) {
151                        return;
152                }
153                TransactionSynchronizationManager.unbindResource(getResourceKey());
154        }
155 
156        /**
157         * Accessor for the list of processed items in this transaction.
158         * 
159         * @return the processed
160         */
161        protected Set getProcessed() {
162                Assert.state(TransactionSynchronizationManager.hasResource(getResourceKey()),
163                                "Processed items not bound to transaction.");
164                Set processed = (Set) TransactionSynchronizationManager.getResource(getResourceKey());
165                return processed;
166        }
167}

[all classes][org.springframework.batch.item.database]
EMMA 2.0.5312 (C) Vladimir Roubtsov