package org.atomhopper.jdbc.adapter; import org.aspectj.lang.ProceedingJoinPoint; import org.postgresql.util.PSQLException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessResourceFailureException; /** * This class is an Around Advice meant to surround a call to the JdbcTemplate accessing * a Postgres database. * * User: shin4590 * Date: 7/23/13 * Time: 4:21 PM */ public class JdbcRetryOnFailureAdvice { private static final Logger LOG = LoggerFactory.getLogger(JdbcRetryOnFailureAdvice.class); private String sqlStatesToRetry = ""; private int maxRetriesOnConnDrop = 0; private long retryWaitInMillis = 1000; public Object retryOnFailure(ProceedingJoinPoint jp) throws Throwable { Object result = null; int retryCount = 0; do { try { Object[] args = jp.getArgs(); if ( args != null && args.length > 0 ) result = jp.proceed(jp.getArgs()); else result = jp.proceed(); break; } catch (DataAccessResourceFailureException ex) { if ( ex.getCause() instanceof PSQLException ) { PSQLException psqlEx = (PSQLException) ex.getCause(); String sqlState = psqlEx.getSQLState(); LOG.warn("Got exception with sqlState=" + sqlState + ": " + ex); if ( sqlStatesToRetry.contains(sqlState) && retryCount < maxRetriesOnConnDrop ) { LOG.warn("Retrying...(retryCount=" + retryCount + ")"); sleep(retryWaitInMillis); } else { throw ex; } } } retryCount++; } while ( retryCount <= maxRetriesOnConnDrop ); return result; } public String getSqlStatesToRetry() { return sqlStatesToRetry; } public void setSqlStatesToRetry(String sqlStatesToRetry) { this.sqlStatesToRetry = sqlStatesToRetry; } public int getMaxRetriesOnConnDrop() { return maxRetriesOnConnDrop; } public void setMaxRetriesOnConnDrop(int maxRetriesOnConnDrop) { this.maxRetriesOnConnDrop = maxRetriesOnConnDrop; } public long getRetryWaitInMillis() { return retryWaitInMillis; } public void setRetryWaitInMillis(long retryWaitInMillis) { this.retryWaitInMillis = retryWaitInMillis; } private void sleep(long sleepTime) { try { Thread.sleep(sleepTime); } catch(Exception ex) { // ignore } } }