Skip to content

SONARJAVA-6588 - Implement S8983: Stateless session beans should not store mutable state in instance variables#5758

Merged
NoemieBenard merged 5 commits into
masterfrom
nb/sonarjava-6588-implement-S8983
Jul 8, 2026
Merged

SONARJAVA-6588 - Implement S8983: Stateless session beans should not store mutable state in instance variables#5758
NoemieBenard merged 5 commits into
masterfrom
nb/sonarjava-6588-implement-S8983

Conversation

@NoemieBenard

@NoemieBenard NoemieBenard commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary by Gitar

  • New inspection rule:
    • Implemented S8983 to detect mutable instance fields in classes annotated with @Stateless.
    • Flagging occurs unless the field is static, final, or annotated with container-managed injection markers like @Inject, @EJB, or @PersistenceContext.
  • Test infrastructure:
    • Added comprehensive test suites for standard and Jakarta EE contexts using StatelessBeanInstanceFieldCheckSample.java and StatelessBeanInstanceFieldCheckJakartaSample.java.
    • Included stubs for required Jakarta annotations to support semantic analysis during testing.
  • Rule metadata:
    • Created rule specification, documentation, and Sonar_way profile entry for S8983.

This will update automatically on new commits.

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

SONARJAVA-6588

Comment on lines +78 to +84
private static boolean isSafe(VariableTree variable) {
if (ModifiersUtils.hasAnyOf(variable.modifiers(), Modifier.STATIC, Modifier.FINAL)) {
return true;
}
SymbolMetadata varMetadata = variable.symbol().metadata();
return SAFE_FIELD_ANNOTATIONS.stream().anyMatch(varMetadata::isAnnotatedWith);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Edge Case: final/static fields holding mutable objects are treated as safe

In isSafe() (StatelessBeanInstanceFieldCheck.java:78-84), any field marked static or final is considered safe and never reported. However the rule targets mutable state, and final/static only make the reference immutable, not the referenced object. A stateless bean with private final List<String> cache = new ArrayList<>(); or private static Map<...> shared = ...; still stores mutable, request-crossing state and can leak data or cause race conditions — exactly the problems the rule description warns about ("Multiple threads may access the same field concurrently"). These cases produce false negatives.

This appears partly intentional (the sample marks static final int MAX_RETRIES and static int sharedCounter as compliant), so it may match the RSPEC scope. If so, no change is needed; otherwise consider inspecting the field's declared type (e.g. mutable collections / non-final referenced objects) rather than relying solely on the static/final modifiers. At minimum, adding a test sample with a final collection field would document the intended behavior explicitly.

Was this helpful? React with 👍 / 👎

@sonarqube-next

sonarqube-next Bot commented Jul 8, 2026

Copy link
Copy Markdown

@NoemieBenard NoemieBenard marked this pull request as ready for review July 8, 2026 09:40
@NoemieBenard NoemieBenard merged commit 5cf8400 into master Jul 8, 2026
17 checks passed
@NoemieBenard NoemieBenard deleted the nb/sonarjava-6588-implement-S8983 branch July 8, 2026 17:23
@gitar-bot

gitar-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown
Code Review 👍 Approved with suggestions 0 resolved / 1 findings

Implements rule S8983 to detect mutable instance fields in @Stateless beans, ensuring compliance with container-managed state patterns. Note that the current implementation considers final or static fields containing mutable objects as safe; consider tightening this logic to avoid potential concurrency issues.

💡 Edge Case: final/static fields holding mutable objects are treated as safe

📄 java-checks/src/main/java/org/sonar/java/checks/StatelessBeanInstanceFieldCheck.java:78-84

In isSafe() (StatelessBeanInstanceFieldCheck.java:78-84), any field marked static or final is considered safe and never reported. However the rule targets mutable state, and final/static only make the reference immutable, not the referenced object. A stateless bean with private final List<String> cache = new ArrayList<>(); or private static Map<...> shared = ...; still stores mutable, request-crossing state and can leak data or cause race conditions — exactly the problems the rule description warns about ("Multiple threads may access the same field concurrently"). These cases produce false negatives.

This appears partly intentional (the sample marks static final int MAX_RETRIES and static int sharedCounter as compliant), so it may match the RSPEC scope. If so, no change is needed; otherwise consider inspecting the field's declared type (e.g. mutable collections / non-final referenced objects) rather than relying solely on the static/final modifiers. At minimum, adding a test sample with a final collection field would document the intended behavior explicitly.

🤖 Prompt for agents
Code Review: Implements rule S8983 to detect mutable instance fields in @Stateless beans, ensuring compliance with container-managed state patterns. Note that the current implementation considers final or static fields containing mutable objects as safe; consider tightening this logic to avoid potential concurrency issues.

1. 💡 Edge Case: final/static fields holding mutable objects are treated as safe
   Files: java-checks/src/main/java/org/sonar/java/checks/StatelessBeanInstanceFieldCheck.java:78-84

   In `isSafe()` (StatelessBeanInstanceFieldCheck.java:78-84), any field marked `static` or `final` is considered safe and never reported. However the rule targets *mutable state*, and `final`/`static` only make the *reference* immutable, not the referenced object. A stateless bean with `private final List<String> cache = new ArrayList<>();` or `private static Map<...> shared = ...;` still stores mutable, request-crossing state and can leak data or cause race conditions — exactly the problems the rule description warns about ("Multiple threads may access the same field concurrently"). These cases produce false negatives.
   
   This appears partly intentional (the sample marks `static final int MAX_RETRIES` and `static int sharedCounter` as compliant), so it may match the RSPEC scope. If so, no change is needed; otherwise consider inspecting the field's declared type (e.g. mutable collections / non-final referenced objects) rather than relying solely on the `static`/`final` modifiers. At minimum, adding a test sample with a `final` collection field would document the intended behavior explicitly.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants