@Override protected DataAccessException doTranslate(String task, String sql, SQLException ex) { if (ex instanceof SQLTransientException) { if (ex instanceof SQLTransientConnectionException) { return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLTransactionRollbackException) { return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLTimeoutException) { return new QueryTimeoutException(buildMessage(task, sql, ex), ex); } } else if (ex instanceof SQLNonTransientException) { if (ex instanceof SQLNonTransientConnectionException) { return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLDataException) { return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLIntegrityConstraintViolationException) { return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLInvalidAuthorizationSpecException) { return new PermissionDeniedDataAccessException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLSyntaxErrorException) { return new BadSqlGrammarException(task, sql, ex); } else if (ex instanceof SQLFeatureNotSupportedException) { return new InvalidDataAccessApiUsageException(buildMessage(task, sql, ex), ex); } } else if (ex instanceof SQLRecoverableException) { return new RecoverableDataAccessException(buildMessage(task, sql, ex), ex); } // Fallback to Spring's own SQL state translation... return null; }
@DataProvider public Object[][] statuses() { TitanMigrationManager happyMigrationManager = new TitanMigrationManager(); TitanMigrationManager sadMigrationManager = new TitanMigrationManager(); Whitebox.setInternalState(happyMigrationManager, IS_MIGRATION_COMPLETE_FIELD_NAME, true); Whitebox.setInternalState(sadMigrationManager, IS_MIGRATION_COMPLETE_FIELD_NAME, false); return new Object[][] { new Object[] { mockDbWithUp(), Status.UP, AcsMonitoringUtilities.HealthCode.AVAILABLE, happyMigrationManager }, { mockDbWithException(new TransientDataAccessResourceException("")), Status.DOWN, AcsMonitoringUtilities.HealthCode.UNAVAILABLE, happyMigrationManager }, { mockDbWithException(new QueryTimeoutException("")), Status.DOWN, AcsMonitoringUtilities.HealthCode.UNAVAILABLE, happyMigrationManager }, { mockDbWithException(new DataSourceLookupFailureException("")), Status.DOWN, AcsMonitoringUtilities.HealthCode.UNREACHABLE, happyMigrationManager }, { mockDbWithException(new PermissionDeniedDataAccessException("", null)), Status.DOWN, AcsMonitoringUtilities.HealthCode.MISCONFIGURATION, happyMigrationManager }, { mockDbWithException(new ConcurrencyFailureException("")), Status.DOWN, AcsMonitoringUtilities.HealthCode.ERROR, happyMigrationManager }, { mockDbWithUp(), Status.DOWN, AcsMonitoringUtilities.HealthCode.MIGRATION_INCOMPLETE, sadMigrationManager }, }; }
@Override protected DataAccessException doTranslate(String task, String sql, SQLException ex) { // First, the getSQLState check... String sqlState = getSqlState(ex); if (sqlState != null && sqlState.length() >= 2) { String classCode = sqlState.substring(0, 2); if (logger.isDebugEnabled()) { logger.debug("Extracted SQL state class '" + classCode + "' from value '" + sqlState + "'"); } if (BAD_SQL_GRAMMAR_CODES.contains(classCode)) { return new BadSqlGrammarException(task, sql, ex); } else if (DATA_INTEGRITY_VIOLATION_CODES.contains(classCode)) { return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); } else if (DATA_ACCESS_RESOURCE_FAILURE_CODES.contains(classCode)) { return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex); } else if (TRANSIENT_DATA_ACCESS_RESOURCE_CODES.contains(classCode)) { return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); } else if (CONCURRENCY_FAILURE_CODES.contains(classCode)) { return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex); } } // For MySQL: exception class name indicating a timeout? // (since MySQL doesn't throw the JDBC 4 SQLTimeoutException) if (ex.getClass().getName().contains("Timeout")) { return new QueryTimeoutException(buildMessage(task, sql, ex), ex); } // Couldn't resolve anything proper - resort to UncategorizedSQLException. return null; }
@ExceptionHandler({ QueryTimeoutException.class }) @ResponseBody public ResponseEntity<E> handleQueryTimeoutException(final QueryTimeoutException ex, final WebRequest request) { final HttpStatus status = HttpStatus.REQUEST_TIMEOUT; final E errorResponse = createErrorResponse(status, i18n(request, "rest-error.QueryTimeoutException")); logException(ex, errorResponse, request); return new ResponseEntity<>(errorResponse, status); }
@Override protected DataAccessException doTranslate(String task, String sql, SQLException ex) { if (ex instanceof SQLTransientException) { if (ex instanceof SQLTransactionRollbackException) { return new ConcurrencyFailureException(buildMessage(task, sql, ex), ex); } if (ex instanceof SQLTransientConnectionException) { return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex); } if (ex instanceof SQLTimeoutException) { return new QueryTimeoutException(buildMessage(task, sql, ex), ex); } } else if (ex instanceof SQLNonTransientException) { if (ex instanceof SQLDataException) { return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLFeatureNotSupportedException) { return new InvalidDataAccessApiUsageException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLIntegrityConstraintViolationException) { return new DataIntegrityViolationException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLInvalidAuthorizationSpecException) { return new PermissionDeniedDataAccessException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLNonTransientConnectionException) { return new DataAccessResourceFailureException(buildMessage(task, sql, ex), ex); } else if (ex instanceof SQLSyntaxErrorException) { return new BadSqlGrammarException(task, sql, ex); } } else if (ex instanceof SQLRecoverableException) { return new RecoverableDataAccessException(buildMessage(task, sql, ex), ex); } // Fallback to Spring's own SQL state translation... return null; }
@Test public void errorCodeTranslation() { SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES); SQLException dataIntegrityViolationEx = SQLExceptionSubclassFactory.newSQLDataException("", "", 0); DataIntegrityViolationException divex = (DataIntegrityViolationException) sext.translate("task", "SQL", dataIntegrityViolationEx); assertEquals(dataIntegrityViolationEx, divex.getCause()); SQLException featureNotSupEx = SQLExceptionSubclassFactory.newSQLFeatureNotSupportedException("", "", 0); InvalidDataAccessApiUsageException idaex = (InvalidDataAccessApiUsageException) sext.translate("task", "SQL", featureNotSupEx); assertEquals(featureNotSupEx, idaex.getCause()); SQLException dataIntegrityViolationEx2 = SQLExceptionSubclassFactory.newSQLIntegrityConstraintViolationException("", "", 0); DataIntegrityViolationException divex2 = (DataIntegrityViolationException) sext.translate("task", "SQL", dataIntegrityViolationEx2); assertEquals(dataIntegrityViolationEx2, divex2.getCause()); SQLException permissionDeniedEx = SQLExceptionSubclassFactory.newSQLInvalidAuthorizationSpecException("", "", 0); PermissionDeniedDataAccessException pdaex = (PermissionDeniedDataAccessException) sext.translate("task", "SQL", permissionDeniedEx); assertEquals(permissionDeniedEx, pdaex.getCause()); SQLException dataAccessResourceEx = SQLExceptionSubclassFactory.newSQLNonTransientConnectionException("", "", 0); DataAccessResourceFailureException darex = (DataAccessResourceFailureException) sext.translate("task", "SQL", dataAccessResourceEx); assertEquals(dataAccessResourceEx, darex.getCause()); SQLException badSqlEx2 = SQLExceptionSubclassFactory.newSQLSyntaxErrorException("", "", 0); BadSqlGrammarException bsgex2 = (BadSqlGrammarException) sext.translate("task", "SQL2", badSqlEx2); assertEquals("SQL2", bsgex2.getSql()); assertEquals(badSqlEx2, bsgex2.getSQLException()); SQLException tranRollbackEx = SQLExceptionSubclassFactory.newSQLTransactionRollbackException("", "", 0); ConcurrencyFailureException cfex = (ConcurrencyFailureException) sext.translate("task", "SQL", tranRollbackEx); assertEquals(tranRollbackEx, cfex.getCause()); SQLException transientConnEx = SQLExceptionSubclassFactory.newSQLTransientConnectionException("", "", 0); TransientDataAccessResourceException tdarex = (TransientDataAccessResourceException) sext.translate("task", "SQL", transientConnEx); assertEquals(transientConnEx, tdarex.getCause()); SQLException transientConnEx2 = SQLExceptionSubclassFactory.newSQLTimeoutException("", "", 0); QueryTimeoutException tdarex2 = (QueryTimeoutException) sext.translate("task", "SQL", transientConnEx2); assertEquals(transientConnEx2, tdarex2.getCause()); SQLException recoverableEx = SQLExceptionSubclassFactory.newSQLRecoverableException("", "", 0); RecoverableDataAccessException rdaex2 = (RecoverableDataAccessException) sext.translate("task", "SQL", recoverableEx); assertEquals(recoverableEx, rdaex2.getCause()); // Test classic error code translation. We should move there next if the exception we pass in is not one // of the new sub-classes. SQLException sexEct = new SQLException("", "", 1); BadSqlGrammarException bsgEct = (BadSqlGrammarException) sext.translate("task", "SQL-ECT", sexEct); assertEquals("SQL-ECT", bsgEct.getSql()); assertEquals(sexEct, bsgEct.getSQLException()); // Test fallback. We assume that no database will ever return this error code, // but 07xxx will be bad grammar picked up by the fallback SQLState translator SQLException sexFbt = new SQLException("", "07xxx", 666666666); BadSqlGrammarException bsgFbt = (BadSqlGrammarException) sext.translate("task", "SQL-FBT", sexFbt); assertEquals("SQL-FBT", bsgFbt.getSql()); assertEquals(sexFbt, bsgFbt.getSQLException()); // and 08xxx will be data resource failure (non-transient) picked up by the fallback SQLState translator SQLException sexFbt2 = new SQLException("", "08xxx", 666666666); DataAccessResourceFailureException darfFbt = (DataAccessResourceFailureException) sext.translate("task", "SQL-FBT2", sexFbt2); assertEquals(sexFbt2, darfFbt.getCause()); }
public void testErrorCodeTranslation() { if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_16) { return; } SQLExceptionTranslator sext = new SQLErrorCodeSQLExceptionTranslator(ERROR_CODES); SQLException dataIntegrityViolationEx = SQLExceptionSubclassFactory.newSQLDataException("", "", 0); DataIntegrityViolationException divex = (DataIntegrityViolationException) sext.translate("task", "SQL", dataIntegrityViolationEx); assertEquals(dataIntegrityViolationEx, divex.getCause()); SQLException featureNotSupEx = SQLExceptionSubclassFactory.newSQLFeatureNotSupportedException("", "", 0); InvalidDataAccessApiUsageException idaex = (InvalidDataAccessApiUsageException) sext.translate("task", "SQL", featureNotSupEx); assertEquals(featureNotSupEx, idaex.getCause()); SQLException dataIntegrityViolationEx2 = SQLExceptionSubclassFactory.newSQLIntegrityConstraintViolationException("", "", 0); DataIntegrityViolationException divex2 = (DataIntegrityViolationException) sext.translate("task", "SQL", dataIntegrityViolationEx2); assertEquals(dataIntegrityViolationEx2, divex2.getCause()); SQLException permissionDeniedEx = SQLExceptionSubclassFactory.newSQLInvalidAuthorizationSpecException("", "", 0); PermissionDeniedDataAccessException pdaex = (PermissionDeniedDataAccessException) sext.translate("task", "SQL", permissionDeniedEx); assertEquals(permissionDeniedEx, pdaex.getCause()); SQLException dataAccessResourceEx = SQLExceptionSubclassFactory.newSQLNonTransientConnectionException("", "", 0); DataAccessResourceFailureException darex = (DataAccessResourceFailureException) sext.translate("task", "SQL", dataAccessResourceEx); assertEquals(dataAccessResourceEx, darex.getCause()); SQLException badSqlEx2 = SQLExceptionSubclassFactory.newSQLSyntaxErrorException("", "", 0); BadSqlGrammarException bsgex2 = (BadSqlGrammarException) sext.translate("task", "SQL2", badSqlEx2); assertEquals("SQL2", bsgex2.getSql()); assertEquals(badSqlEx2, bsgex2.getSQLException()); SQLException tranRollbackEx = SQLExceptionSubclassFactory.newSQLTransactionRollbackException("", "", 0); ConcurrencyFailureException cfex = (ConcurrencyFailureException) sext.translate("task", "SQL", tranRollbackEx); assertEquals(tranRollbackEx, cfex.getCause()); SQLException transientConnEx = SQLExceptionSubclassFactory.newSQLTransientConnectionException("", "", 0); TransientDataAccessResourceException tdarex = (TransientDataAccessResourceException) sext.translate("task", "SQL", transientConnEx); assertEquals(transientConnEx, tdarex.getCause()); SQLException transientConnEx2 = SQLExceptionSubclassFactory.newSQLTimeoutException("", "", 0); QueryTimeoutException tdarex2 = (QueryTimeoutException) sext.translate("task", "SQL", transientConnEx2); assertEquals(transientConnEx2, tdarex2.getCause()); SQLException recoverableEx = SQLExceptionSubclassFactory.newSQLRecoverableException("", "", 0); RecoverableDataAccessException rdaex2 = (RecoverableDataAccessException) sext.translate("task", "SQL", recoverableEx); assertEquals(recoverableEx, rdaex2.getCause()); // Test classic error code translation. We should move there next if the exception we pass in is not one // of the new sub-classes. SQLException sexEct = new SQLException("", "", 1); BadSqlGrammarException bsgEct = (BadSqlGrammarException) sext.translate("task", "SQL-ECT", sexEct); assertEquals("SQL-ECT", bsgEct.getSql()); assertEquals(sexEct, bsgEct.getSQLException()); // Test fallback. We assume that no database will ever return this error code, // but 07xxx will be bad grammar picked up by the fallback SQLState translator SQLException sexFbt = new SQLException("", "07xxx", 666666666); BadSqlGrammarException bsgFbt = (BadSqlGrammarException) sext.translate("task", "SQL-FBT", sexFbt); assertEquals("SQL-FBT", bsgFbt.getSql()); assertEquals(sexFbt, bsgFbt.getSQLException()); // and 08xxx will be data resource failure (non-transient) picked up by the fallback SQLState translator SQLException sexFbt2 = new SQLException("", "08xxx", 666666666); DataAccessResourceFailureException darfFbt = (DataAccessResourceFailureException) sext.translate("task", "SQL-FBT2", sexFbt2); assertEquals(sexFbt2, darfFbt.getCause()); }