diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1110.json b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1110.json index 2b607b5003f..87cbe8691bb 100644 --- a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1110.json +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1110.json @@ -1,23 +1,25 @@ { - "title": "Redundant pairs of parentheses should be removed", + "title": "Unnecessary parentheses should be removed", "type": "CODE_SMELL", - "code": { - "impacts": { - "MAINTAINABILITY": "MEDIUM" - }, - "attribute": "CLEAR" - }, "status": "ready", "remediation": { "func": "Constant\/Issue", - "constantCost": "1min" + "constantCost": "2 min" }, "tags": [ - "confusing" + "clippy", + "redundant", + "readability" ], - "defaultSeverity": "Major", + "defaultSeverity": "Minor", "ruleSpecification": "RSPEC-1110", "sqKey": "S1110", "scope": "All", - "quickfix": "unknown" + "quickfix": "unknown", + "code": { + "impacts": { + "MAINTAINABILITY": "LOW" + }, + "attribute": "CLEAR" + } } diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2206.json b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2206.json index 3e6c2d30eb9..a7c838a29c4 100644 --- a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2206.json +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2206.json @@ -1,5 +1,5 @@ { - "title": "Either fields or getters should be annotated for persistence but not both", + "title": "Do not mix field and getter persistence annotations", "type": "BUG", "status": "ready", "remediation": { diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2654.html b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2654.html index 7f2832d9391..5b6762cbe6c 100644 --- a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2654.html +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2654.html @@ -1,18 +1,106 @@
Proper synchronization and thread management can be tricky under the best of circumstances, but it’s particularly difficult in JEE application, and -is even forbidden under some circumstances by the JEE standard.
-This rule raises an issue for each Runnable, and use of the synchronized keyword.
-public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // ...
-
- Runnable r = new Runnable() { // Noncompliant
- public void run() {
+Proper synchronization and thread management can be tricky under the best of circumstances, but it’s particularly difficult in Jakarta EE
+application, and is even forbidden under some circumstances by the Jakarta EE standard.
+This rule raises an issue for each Runnable, and use of the synchronized keyword in Jakarta EE applications.
+How to fix it
+Instead of creating unmanaged threads, use the Concurrency Utilities for Jakarta EE. Injecting a ManagedExecutorService lets the
+container manage the thread pool and preserves the container context (CDI, security, transactions). If you are using EJBs, annotate a method with
+@Asynchronous to run it in a container-managed background thread, with no need to manage threads or submit tasks explicitly.
+For shared mutable state that would otherwise require synchronized, use container-managed concurrency instead. In EJBs, the container
+serializes access to @Singleton beans by default (via @Lock(WRITE)), eliminating the need for explicit synchronization.
+Outside EJBs, use the concurrency utilities from java.util.concurrent such as AtomicInteger or
+ConcurrentHashMap, which are safe to use in Jakarta EE.
+Code examples
+Noncompliant code example
+
+@RequestScoped
+public class DataProcessor {
+
+ public void processData() {
+ Runnable task = () -> { // Noncompliant
+ // ...
+ };
+ new Thread(task).start();
+ }
+}
+
+Compliant solution
+Using ManagedExecutorService
+
+@RequestScoped
+public class DataProcessor {
+
+ @Resource
+ private ManagedExecutorService executor;
+
+ public void processData() {
+ executor.submit(() -> { // Compliant
// ...
- }
- };
- new Thread(r).start();
+ });
+ }
+}
+
+Noncompliant code example
+
+@Stateless
+public class OrderService {
+
+ public void dispatchOrder(Long orderId) {
+ Runnable r = new Runnable() { // Noncompliant
+ public void run() {
+ // ...
+ }
+ };
+ new Thread(r).start();
+ }
+}
+
+Compliant solution
+Using @Asynchronous
+
+@Stateless
+public class OrderService {
+
+ @Asynchronous // Compliant
+ public void dispatchOrder(Long orderId) {
+ // ...
+ }
+}
+
+Noncompliant code example
+
+@Singleton
+public class CounterService {
+
+ private int count = 0;
+
+ public synchronized void increment() { // Noncompliant
+ count++;
+ }
+
+ public synchronized int getCount() { // Noncompliant
+ return count;
+ }
+}
+
+Compliant solution
+Using @Singleton with @Lock(…)
+
+@Singleton
+public class CounterService {
+
+ private int count = 0;
+
+ @Lock(LockType.WRITE) // Compliant - container manages concurrency
+ public void increment() {
+ count++;
+ }
+
+ @Lock(LockType.READ) // Compliant
+ public int getCount() {
+ return count;
+ }
+}
Resources
For AES, the weakest mode is ECB (Electronic Codebook). Repeated blocks of data are encrypted to the same value, making them easy to identify and reducing the difficulty of recovering the original cleartext.
-Unauthenticated modes such as CBC (Cipher Block Chaining) may be used but are prone to attacks that manipulate the ciphertext. They must be used -with caution.
For RSA, the weakest algorithms are either using it without padding or using the PKCS1v1.5 padding scheme.
The cleartext of an encrypted message might be recoverable. Additionally, it might be possible to modify the cleartext of an encrypted message.
@@ -103,16 +101,12 @@Integer Authenticated Parallelizable ModeOffset Codebook ModeIt is also possible to use AES-CBC with HMAC for integrity checks. However, it is considered more straightforward to use AES-GCM directly -instead.
The Optimal Asymmetric Encryption Padding scheme (OAEP) adds randomness and a secure hash function that strengthens the regular inner workings of RSA.
This rule raises an issue when at least 3 test methods could be refactored into a single parameterized test with less than 4 parameters.
When multiple tests differ only by a few hardcoded values they should be refactored as a single "parameterized" test. This reduces the chances of -adding a bug and makes them more readable. Parameterized tests exist in most test frameworks (JUnit, TestNG, etc…).
-The right balance needs of course to be found. There is no point in factorizing test methods when the parameterized version is a lot more complex -than initial tests.
-This rule raises an issue when at least 3 tests could be refactored as one parameterized test with less than 4 parameters. Only test methods which -have at least one duplicated statement are considered.
+When multiple tests differ only by a few hardcoded values, they should be refactored into a single parameterized test. This reduces duplication, +makes the tests easier to read, and lowers the risk of introducing bugs when the test logic needs to change.
+Parameterized tests are supported by most testing frameworks.
+The right balance still needs to be found. There is little value in parameterizing tests when the resulting test becomes significantly more complex +than the original versions.
with JUnit 5
diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6206.html b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6206.html index 9b2a70025cd..e8ade5a5fd4 100644 --- a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6206.html +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6206.html @@ -80,3 +80,4 @@+ diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8911.html b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8911.html index 755756ece61..11c6cf1701d 100644 --- a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8911.html +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8911.html @@ -8,23 +8,23 @@Resources
When you mark a method for startup execution, the dependency injection framework generates initialization hooks that trigger the method when the application starts. For this mechanism to work correctly, the method must meet three requirements:
When methods designated for startup execution don’t follow the required signature, the initialization logic will not execute at application startup. This can lead to:
Remove the static modifier from the method to make it an instance method. Ensure the method has no parameters and is not annotated
@@ -53,8 +53,9 @@
This rule raises an issue when Mockito core methods are called with the Mockito. prefix instead of being statically imported.
This applies to commonly used Mockito methods such as:
+This applies to the following Mockito methods:
mock()when()doThrow()times()never()any()eq()Mockito was designed with static imports in mind to create a more readable, fluent testing DSL (Domain-Specific Language). When you use the
Mockito. prefix for method calls, the test code becomes more verbose and harder to read.
Compare these two examples:
-Mockito.when(Mockito.mock(MyService.class).getValue()).thenReturn(42); +var myMock = Mockito.mock(MyService.class); +Mockito.when(myMock.getValue()).thenReturn(42);
versus:
-when(mock(MyService.class).getValue()).thenReturn(42); +var myMock = mock(MyService.class); +when(myMock.getValue()).thenReturn(42);
The second version reads more naturally, almost like plain English, which is the intent of Mockito’s API design. This readability improvement becomes even more significant in larger test files with many mock interactions.
@@ -51,7 +51,8 @@
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
public class MyServiceTest {
private MyService myService = mock(MyService.class);
@@ -73,3 +74,13 @@ Documentation
(visible only on this page)
+Use a static import for "{method name}".
+