View Javadoc
1 /* ====================================================================
2 * License:
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. The end-user documentation included with the redistribution,
17 * if any, must include the following acknowledgment:
18 * "This product includes software developed by
19 * Robert Half International (http://www.rhi.com/)."
20 * Alternately, this acknowledgment may appear in the software itself,
21 * if and wherever such third-party acknowledgments normally appear.
22 *
23 * 4. The names "Parc", "RHI", and "Robert Half International" must
24 * not be used to endorse or promote products derived from this
25 * software without prior written permission. For written
26 * permission, please contact pete.mckinstry@rhi.com.
27 *
28 * 5. Products derived from this software may not be called "PARC",
29 * nor may "PARC" appear in their name, without prior written
30 * permission of Robert Half International.
31 *
32 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
33 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
34 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
36 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 * ====================================================================
45 *
46 */
47 package com.rhi.architecture.parc.adapter;
48
49 import com.rhi.architecture.batch.AuditException;
50 import com.rhi.architecture.config.ConfigurationException;
51 import com.rhi.architecture.logging.LogUtil;
52 import com.rhi.architecture.logging.Logger;
53 import com.rhi.architecture.parc.ExceptionHandler;
54 import com.rhi.architecture.parc.ProcessingException;
55 import com.rhi.architecture.xa.Transaction;
56 import com.rhi.architecture.xa.TransactionException;
57
58 import java.util.Collection;
59
60 /***
61 * The OutputRecordsTask encapsulates generic processing required for
62 * processing OutputAdapter records. Derived classes override processRecords
63 * method to perform processing specific to type of output records.
64 *
65 * @author Chandra Ilindra
66 * @copyright 2002, Robert Half Int'l., Inc. All rights reserved.
67 *
68 * @since 1.0
69 */
70 public abstract class OutputRecordsTask implements Runnable, Cloneable {
71
72 private static Logger log = null;
73 protected AbstractOutputAdapter parent;
74 private Collection records;
75 private ExceptionHandler handler;
76 private int maxRetries;
77 /***
78 * Constructor
79 *
80 * @param aoa - reference to OutputAdapter
81 * @param mr - maximum number of retries for deadlocks
82 * @param eh - the exception handler to use when reporting asynch errors.
83 * @since 1.0
84 */
85 public OutputRecordsTask(
86 AbstractOutputAdapter aoa,
87 int mr,
88 ExceptionHandler eh) {
89
90 parent = aoa;
91 maxRetries = mr;
92 handler = eh;
93
94 // initialize logger object
95 try {
96 log = LogUtil.getLogger();
97 }
98 catch (ConfigurationException e) {
99 // ignore throw new InitializationException(e.toString(), e);
100 }
101 }
102
103 /***
104 * sets the records to be processed by this task.
105 *
106 * @param recs - the records to process.
107 *
108 * @since 1.0
109 */
110 public void setRecords(Collection recs) {
111 records = recs;
112 }
113
114 /***
115 * This is core processing logic method run by this task.
116 * It creates a transaction and processes the records. If
117 * a deadlock occurs then it rollsback and retries one more time.
118 * Only maxRetries number of times retry occurs, otherwise
119 * a ProcessingException is thrown.
120 *
121 * @since 1.0
122 */
123 public void run() {
124 Transaction transaction = null;
125 Throwable excp = null;
126 boolean completedSuccessfully = false;
127 int retryCount = 0;
128
129 // create a transaction
130 try {
131 transaction = parent.createTransaction();
132 }
133 catch (ProcessingException e) {
134 handler.reportException(e);
135 return;
136 }
137
138 /***
139 * process recoords in a loop until
140 * - non deadlock exception occurs or
141 * - successfully able to commit to database.
142 */
143 while (!completedSuccessfully) {
144 try {
145 transaction.begin();
146 processRecords(records, transaction);
147 transaction.commit();
148 completedSuccessfully = true;
149 }
150 catch (AuditException e) {
151 log.error("AuditException", e);
152 try {
153 if (transaction != null)
154 transaction.rollback();
155 }
156 catch (TransactionException te) {
157 // ignore
158 }
159 log.info(e.toString());
160 excp = e;
161 }
162 catch (ProcessingException e) {
163 log.error("ProcessingException", e);
164 try {
165 if (transaction != null)
166 transaction.rollback();
167 }
168 catch (TransactionException te) {
169 // ignore
170 }
171 log.info(e.toString());
172 excp = e;
173 }
174 catch (TransactionException e) {
175 log.error("TransactionException", e);
176 try {
177 if (transaction != null)
178 transaction.rollback();
179 }
180 catch (TransactionException te) {
181 // ignore
182 }
183 log.info(e.toString());
184 excp = e;
185 }
186 catch (Throwable t) {
187 log.fatal("Unknown Exception caught: " + t, t);
188 try {
189 if (transaction != null)
190 transaction.rollback();
191 }
192 catch (TransactionException te) {
193 // ignore
194 }
195 excp = t;
196 }
197
198 if (!completedSuccessfully) {
199 if (isDeadlockTimeoutError(excp)) {
200 // Deadlock occured and let us retry one more time,
201 // if maxRetries has not reached
202 retryCount++;
203 if (retryCount == maxRetries) {
204 // maxRetries reached, create an exception
205 // and add it to exception handler
206 handler.reportException(
207 new ProcessingException("Max number of retries exceeded for deadlock errors."));
208 break; // exit from while loop
209 }
210 }
211 else {
212 // non deadlock error occured, so
213 // add it to exception handler
214 handler.reportException(
215 new ProcessingException(excp.toString(), excp));
216 break; // exit from while loop
217 }
218 }
219 } // while
220 }
221
222 /***
223 * checks for deadlock/timeout errors
224 *
225 * @param e - Exception object
226 *
227 * @return true - if SQL return code corresponds to deadlock/timeout error; false - otherwise.
228 *
229 * @since 1.0
230 */
231 private boolean isDeadlockTimeoutError(Throwable e) {
232 if (e.toString().indexOf("SQLSTATE=40001") > 0) {
233 log.info("Deadlock Exception occured");
234 return true;
235 }
236 else {
237 log.info("Non Deadlock Exception occured");
238 return false;
239 }
240 }
241
242 /***
243 *
244 * Abstract method overriden by the concreate classes to perform
245 * processing specific to each subclass.
246 * @param records
247 * @param transacttion
248 * @throws TransactionException
249 * @throws ProcessingException
250 * @throws AuditException
251 */
252 protected abstract void processRecords(
253 Collection records,
254 Transaction transacttion)
255 throws TransactionException, ProcessingException, AuditException;
256
257 /***
258 * Simple <code>Object</code> based clone() method.
259 *
260 * @return OutputRecordsTask object
261 *
262 * @since 1.0
263 */
264 public Object clone() {
265 OutputRecordsTask ort = null;
266 try {
267 ort = (OutputRecordsTask) super.clone();
268 ort.maxRetries = maxRetries;
269 ort.handler = handler;
270 ort.parent = parent;
271 }
272 catch (CloneNotSupportedException cnse) {
273 // impossible.
274 }
275 return ort;
276 }
277
278 }
This page was automatically generated by Maven