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