SONARJAVA-4926 Implement new rule S8989#5770
Conversation
Code Review 👍 Approved with suggestions 2 resolved / 7 findingsImplements rule S8989 to detect unchecked checked exceptions in 💡 Bug: Rule S8989 is "ready" but not added to Sonar_way profile📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8989.json:3 S8989.json declares 💡 Quality: Impact/type may misclassify a data-integrity rule as maintainability📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8989.json:12-18 The rule description centers on silent data corruption, inconsistent database state, and business-logic violations (a reliability/correctness concern), yet the metadata sets 💡 Edge Case: Quick fix uses simple type name; may not compile if not imported
💡 Bug: Meta-annotated (composed)
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
799967a to
12235f2
Compare
Code Review 👍 Approved with suggestions 4 resolved / 7 findingsImplements rule S8989 to detect missing rollback configurations in 💡 Edge Case: Quick fix uses simple type name; may not compile if not imported
💡 Bug: Meta-annotated (composed)
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
NoemieBenard
left a comment
There was a problem hiding this comment.
The implementation looks good, some questions/suggestions on the documentation and agent-generated files
| "ruleSpecification": "RSPEC-8989", | ||
| "sqKey": "S8989", | ||
| "scope": "Main", | ||
| "quickfix": "unknown", |
There was a problem hiding this comment.
quickfix shoud be "covered" (or "partial" since it doesn't suggest using "noRollbackFor") based on the implementation
| <li>Spring Framework Documentation - Transaction Management - <a | ||
| href="https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html">Official Spring documentation | ||
| explaining the @Transactional annotation and its rollback behavior</a></li> | ||
| <li>Baeldung - Spring @Transactional Rollback - <a href="https://www.baeldung.com/spring-transactional-rollback">Practical guide to configuring |
There was a problem hiding this comment.
I get a 404 on this link
There was a problem hiding this comment.
I'm replacing it in the rspec PR.
| <li>Spring Framework Documentation - Transaction Management - <a | ||
| href="https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html">Official Spring documentation | ||
| explaining the @Transactional annotation and its rollback behavior</a></li> |
There was a problem hiding this comment.
Following the guidelines, it probably should be:
| <li>Spring Framework Documentation - Transaction Management - <a | |
| href="https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html">Official Spring documentation | |
| explaining the @Transactional annotation and its rollback behavior</a></li> | |
| <li>Spring Framework Documentation - <a | |
| href="https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html">Using @Transactional </a></li> |
There was a problem hiding this comment.
I am not sure I understand the purpose of this file
There was a problem hiding this comment.
Sorry it looks like it was comited by mistake by nigel
There was a problem hiding this comment.
I think this should not be part of the PR (and it is probably the same for TESTING-RULING-DIFF-ACTION.md, or at least we need to move it to an agent directory if we want to keep it as a skill)
This rule detects methods annotated with @transactional from Spring Framework that declare checked exceptions but do not explicitly configure rollback behavior using rollbackFor or noRollbackFor attributes. By default, Spring only rolls back transactions for unchecked exceptions, which can lead to silent data corruption when checked exceptions are thrown but the transaction commits anyway. The rule helps prevent this by requiring explicit rollback configuration for all transactional methods that throw checked exceptions.
…ckSample Added caret markers under method names to specify exact issue locations for all Noncompliant cases in the sample file. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Changed issue location from method name to @transactional annotation - Added two quick fixes: 1. Add rollbackFor with specific checked exceptions 2. Add rollbackFor = Exception.class (covers all) - Updated sample file with correct location markers on annotations Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Removed unused imports (Symbol, SymbolMetadata) - Made isCheckedException static - Made hasRollbackConfiguration static - Removed unused hasRollbackConfiguration(SymbolMetadata) method Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added parentheses around ternary operator and string concatenation to make the operator precedence explicit. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added test case for @transactional(value = "txManager") to ensure hasRollbackConfiguration returns false when the annotation has arguments but none of them are rollback-related attributes. This covers the edge case where annotation arguments exist but are not rollback configuration attributes. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added test cases to ensure complete coverage of getTransactionalAnnotation: - Line 92: Exit loop when no method-level @transactional found - Line 97: Parent traversal through nested class structures - Line 105: Exit loop when no class-level @transactional found Test cases added: - Nested class structure (InnerClassWithAnnotation) to test parent traversal - Nested class without annotation to test return null path - Interface with @transactional to test INTERFACE tree kind handling Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…k fixes
1. Use fully qualified names in quick fixes
- Changed Type::name to Type::fullyQualifiedName to avoid compilation
errors when exception types are not imported
- Ensures quick fixes always produce compilable code
2. Restore support for meta-annotated @transactional
- Added isTransactionalAnnotation() helper that checks both direct
and meta-annotations using SymbolMetadata.isAnnotatedWith()
- Supports composed annotations like custom @MyTransactional that
is itself annotated with Spring's @transactional
- Prevents false-negatives with composed annotations
3. Deduplicate identical quick fixes
- When the only checked exception is Exception, only show one quick
fix instead of two identical ones
- Improved UX by avoiding confusing duplicate quick fixes
4. Added test for meta-annotated annotation
- Created @MyTransactional composed annotation
- Verified detection works with meta-annotations
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Line 168 - isCheckedException returns false for unknown types: - Added unknownException() test with UnresolvedCheckedException - When type.isUnknown() is true, should not raise issue as we cannot determine if it's truly a checked exception Line 187 - hasRollbackConfiguration returns false for non-ASSIGNMENT: - Added valueShorthand() test with @transactional("txManager") - Covers case where annotation has arguments but none are rollback-related configuration - Correctly raises Noncompliant as expected Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created TransactionalMethodCheckedExceptionCheckSampleNonCompiling.java to test behavior with unresolved exception types that cannot be compiled. This properly tests line 168 (type.isUnknown() returns false) by having an UnresolvedCheckedException that is not defined, ensuring the check doesn't raise false positives on unknown types. Moved unknownException test from main sample to non-compiling sample to satisfy sanity checks that expect all main samples to compile. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
75a6732 to
3dd065b
Compare
|
Code Review ✅ Approved 7 resolved / 7 findingsImplements rule S8989 to detect unchecked exceptions in ✅ 7 resolved✅ Bug: Class-level @transactional reports duplicate issues at same location
✅ Quality: Dead code: unused hasRollbackConfiguration(SymbolMetadata) and Symbol import
✅ Bug: Rule S8989 is "ready" but not added to Sonar_way profile
✅ Quality: Impact/type may misclassify a data-integrity rule as maintainability
✅ Edge Case: Quick fix uses simple type name; may not compile if not imported
...and 2 more resolved from earlier reviews OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |




This rule detects methods annotated with @transactional from Spring Framework that declare checked exceptions but do not explicitly configure rollback behavior using rollbackFor or noRollbackFor attributes. By default, Spring only rolls back transactions for unchecked exceptions, which can lead to silent data corruption when checked exceptions are thrown but the transaction commits anyway. The rule helps prevent this by requiring explicit rollback configuration for all transactional methods that throw checked exceptions.
RSPEC PR