1
0

Optimierung: Catch-all-Exception-Behandlung an technischen Grenzen

gezielt geschärft
This commit is contained in:
2026-04-06 07:45:01 +02:00
parent 00daa9cb74
commit 6437ef38af
3 changed files with 60 additions and 53 deletions

View File

@@ -78,25 +78,20 @@ public class Sha256FingerprintAdapter implements FingerprintPort {
return new FingerprintSuccess(fingerprint);
} catch (IOException e) {
String errorMsg = String.format("Failed to read file for '%s': %s",
String errorMsg = String.format("Failed to read file for '%s': %s",
candidate.uniqueIdentifier(), e.getMessage());
logger.warn(errorMsg, e);
return new FingerprintTechnicalError(errorMsg, e);
} catch (InvalidPathException e) {
String errorMsg = String.format("Invalid file path for '%s': %s",
String errorMsg = String.format("Invalid file path for '%s': %s",
candidate.uniqueIdentifier(), e.getMessage());
logger.warn(errorMsg, e);
return new FingerprintTechnicalError(errorMsg, e);
} catch (NoSuchAlgorithmException e) {
String errorMsg = String.format("SHA-256 algorithm not available for '%s'",
String errorMsg = String.format("SHA-256 algorithm not available for '%s'",
candidate.uniqueIdentifier());
logger.error(errorMsg, e);
return new FingerprintTechnicalError(errorMsg, e);
} catch (Exception e) {
String errorMsg = String.format("Unexpected error computing fingerprint for '%s': %s",
candidate.uniqueIdentifier(), e.getMessage());
logger.error(errorMsg, e);
return new FingerprintTechnicalError(errorMsg, e);
}
}

View File

@@ -49,8 +49,19 @@ public class SqliteUnitOfWorkAdapter implements UnitOfWorkPort {
connection.commit();
logger.debug("Transaction committed successfully");
} catch (Exception e) {
// Rollback for ANY exception, not just SQLException
} catch (DocumentPersistenceException e) {
// Re-throw document-level persistence errors as-is, but still rollback
if (connection != null) {
try {
connection.rollback();
logger.debug("Transaction rolled back due to document error: {}", e.getMessage());
} catch (SQLException rollbackEx) {
logger.error("Failed to rollback transaction: {}", rollbackEx.getMessage(), rollbackEx);
}
}
throw e;
} catch (RuntimeException e) {
// Rollback on any RuntimeException and wrap in DocumentPersistenceException
if (connection != null) {
try {
connection.rollback();
@@ -59,9 +70,16 @@ public class SqliteUnitOfWorkAdapter implements UnitOfWorkPort {
logger.error("Failed to rollback transaction: {}", rollbackEx.getMessage(), rollbackEx);
}
}
// Re-throw as DocumentPersistenceException if not already
if (e instanceof DocumentPersistenceException) {
throw (DocumentPersistenceException) e;
throw new DocumentPersistenceException("Transaction failed: " + e.getMessage(), e);
} catch (SQLException e) {
// Rollback for any SQL error
if (connection != null) {
try {
connection.rollback();
logger.debug("Transaction rolled back due to error: {}", e.getMessage());
} catch (SQLException rollbackEx) {
logger.error("Failed to rollback transaction: {}", rollbackEx.getMessage(), rollbackEx);
}
}
throw new DocumentPersistenceException("Transaction failed: " + e.getMessage(), e);
} finally {
@@ -84,53 +102,47 @@ public class SqliteUnitOfWorkAdapter implements UnitOfWorkPort {
@Override
public void saveProcessingAttempt(ProcessingAttempt attempt) {
try {
// Reuse the existing repository logic but with shared connection
SqliteProcessingAttemptRepositoryAdapter repo =
new SqliteProcessingAttemptRepositoryAdapter(jdbcUrl) {
@Override
protected Connection getConnection() throws SQLException {
return connection;
}
};
repo.save(attempt);
} catch (Exception e) {
throw new DocumentPersistenceException("Failed to save processing attempt: " + e.getMessage(), e);
}
// Repository methods declare DocumentPersistenceException as the only thrown exception.
// Any other exception (NullPointerException, etc.) will propagate to the outer try-catch
// and be caught there.
SqliteProcessingAttemptRepositoryAdapter repo =
new SqliteProcessingAttemptRepositoryAdapter(jdbcUrl) {
@Override
protected Connection getConnection() throws SQLException {
return connection;
}
};
repo.save(attempt);
}
@Override
public void createDocumentRecord(DocumentRecord record) {
try {
// Reuse the existing repository logic but with shared connection
SqliteDocumentRecordRepositoryAdapter repo =
new SqliteDocumentRecordRepositoryAdapter(jdbcUrl) {
@Override
protected Connection getConnection() throws SQLException {
return connection;
}
};
repo.create(record);
} catch (Exception e) {
throw new DocumentPersistenceException("Failed to create document record: " + e.getMessage(), e);
}
// Repository methods declare DocumentPersistenceException as the only thrown exception.
// Any other exception (NullPointerException, etc.) will propagate to the outer try-catch
// and be caught there.
SqliteDocumentRecordRepositoryAdapter repo =
new SqliteDocumentRecordRepositoryAdapter(jdbcUrl) {
@Override
protected Connection getConnection() throws SQLException {
return connection;
}
};
repo.create(record);
}
@Override
public void updateDocumentRecord(DocumentRecord record) {
try {
// Reuse the existing repository logic but with shared connection
SqliteDocumentRecordRepositoryAdapter repo =
new SqliteDocumentRecordRepositoryAdapter(jdbcUrl) {
@Override
protected Connection getConnection() throws SQLException {
return connection;
}
};
repo.update(record);
} catch (Exception e) {
throw new DocumentPersistenceException("Failed to update document record: " + e.getMessage(), e);
}
// Repository methods declare DocumentPersistenceException as the only thrown exception.
// Any other exception (NullPointerException, etc.) will propagate to the outer try-catch
// and be caught there.
SqliteDocumentRecordRepositoryAdapter repo =
new SqliteDocumentRecordRepositoryAdapter(jdbcUrl) {
@Override
protected Connection getConnection() throws SQLException {
return connection;
}
};
repo.update(record);
}
}
}