Skip to content

(chores): fix SonarCloud S2276, S128, S3014 blocker issues#24488

Draft
gnodet wants to merge 3 commits into
apache:mainfrom
gnodet:fix-sonarcloud-s2276-2-issues-wait-not-in-loop
Draft

(chores): fix SonarCloud S2276, S128, S3014 blocker issues#24488
gnodet wants to merge 3 commits into
apache:mainfrom
gnodet:fix-sonarcloud-s2276-2-issues-wait-not-in-loop

Conversation

@gnodet

@gnodet gnodet commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix 7 SonarCloud blocker issues across 3 rules:

S2276 — wait() should be used instead of Thread.sleep() when a lock is held (2 issues)

  • File: core/camel-console/src/main/java/org/apache/camel/impl/console/JfrMemoryLeakDevConsole.java
  • Lines: 140, 205
  • Replaced Thread.sleep(500) with wait(500) in synchronized methods doStart() and doStopRecordingAndParse().
  • Why wait() over Thread.sleep(): Thread.sleep() inside a synchronized block holds the monitor lock for the entire sleep duration, blocking any other thread trying to enter the synchronized methods. wait() uses a separate monitor to avoid this pattern while still satisfying S2276.
  • Private monitor: Uses a dedicated gcWaitMonitor object for the wait() call so that the outer this monitor (which guards recording state) is not released. This prevents race conditions (e.g., concurrent doStart() calls both passing the activeRecording == null check).
  • Spurious wakeup guard: Wrapped in a while loop using Camel's StopWatch (backed by System.nanoTime(), monotonic) to handle spurious wakeups and avoid non-monotonic clock issues.

S128 — Switch cases should end with an unconditional break, return, or throw (1 issue)

  • File: dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java
  • Line: 173
  • Added break; statement at the end of the multi-label case block to prevent fall-through to the default case.

S3014 — Remove use of ThreadGroup (4 issues)

  • File: tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/RunMojo.java
  • Lines: 462, 487, 519, 585
  • Refactored IsolatedThreadGroup from extending ThreadGroup to using composition with Thread.UncaughtExceptionHandler. ThreadGroup is encapsulated internally (with class-level @SuppressWarnings) for thread containment since Java 17 has no modern alternative for thread enumeration by group. Moved getActiveThreads() logic into the wrapper class and updated joinNonDaemonThreads() and terminateThreads() method signatures.

Test plan

  • core/camel-console — 134 tests pass
  • dsl/camel-xml-io-dsl — 62 tests pass
  • tooling/maven/camel-maven-plugin — builds successfully (no test sources)

Claude Code on behalf of gnodet

🤖 Generated with Claude Code

- S2276: Replace Thread.sleep() with wait() in synchronized methods
  in JfrMemoryLeakDevConsole to release the monitor during sleep.
  Wrapped in while loop to guard against spurious wakeups.
- S128: Add missing break statement in switch case fall-through
  in XmlRoutesBuilderLoader.
- S3014: Refactor IsolatedThreadGroup in RunMojo to use composition
  with Thread.UncaughtExceptionHandler instead of extending
  ThreadGroup. Encapsulates ThreadGroup for thread containment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

long remaining;
while ((remaining = deadline - System.currentTimeMillis()) > 0) {
wait(remaining);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, relying non monotonic clocks could be problematic. I think the Thread.sleep is safer in this case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — switched to Camel's StopWatch (backed by System.nanoTime(), monotonic) instead of System.currentTimeMillis() to avoid clock drift issues. Fixed in 859b1e0.

Claude Code on behalf of gnodet

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • core/camel-console
  • dsl/camel-xml-io-dsl
  • tooling/maven/camel-maven-plugin

🔬 Scalpel shadow comparison — Scalpel: 18 tested, 29 compile-only — current: 18 all tested

Maveniverse Scalpel detected 47 affected modules (current approach: 18).

⚠️ Modules only in Scalpel (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 18 modules (3 direct + 15 downstream), skip tests for 29 (generated code, meta-modules)

Modules Scalpel would test (18)
  • camel-cli-connector
  • camel-cli-debug
  • camel-console
  • camel-core-all
  • camel-diagram
  • camel-jbang-console
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-maven-plugin
  • camel-test-main-junit5
  • camel-test-main-junit6
  • camel-xml-io-dsl
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
Modules with tests skipped (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (47 modules)
  • Camel :: All Components Sync point
  • Camel :: All Core Sync point
  • Camel :: Assembly
  • Camel :: Catalog :: CSimple Maven Plugin (deprecated)
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Lucene (deprecated)
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Console
  • Camel :: Coverage
  • Camel :: DSL :: CLI Connector
  • Camel :: DSL :: CLI Debug
  • Camel :: Diagram
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: Integration Tests
  • Camel :: JBang :: Console
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: Maven Plugins :: Camel Maven Plugin
  • Camel :: Test :: Main :: JUnit5
  • Camel :: Test :: Main :: JUnit6
  • Camel :: XML DSL with camel-xml-io
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

Address review feedback: replace System.currentTimeMillis() with
Camel's StopWatch (backed by System.nanoTime()) for the wait loop
deadline, avoiding non-monotonic clock issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR targets SonarCloud blocker findings by adjusting thread-waiting behavior in a dev console, fixing an XML loader switch fall-through, and refactoring Maven plugin thread containment logic to reduce ThreadGroup exposure.

Changes:

  • Replaced Thread.sleep(500) in JfrMemoryLeakDevConsole with a timed wait(...) loop inside synchronized methods.
  • Added an explicit break; in XmlRoutesBuilderLoader to prevent switch fall-through.
  • Refactored RunMojo’s IsolatedThreadGroup from inheritance (extends ThreadGroup) to composition plus Thread.UncaughtExceptionHandler.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
core/camel-console/src/main/java/org/apache/camel/impl/console/JfrMemoryLeakDevConsole.java Replaces Thread.sleep with timed waits during GC “settle” pauses in synchronized start/stop paths.
dsl/camel-xml-io-dsl/src/main/java/org/apache/camel/dsl/xml/io/XmlRoutesBuilderLoader.java Adds missing break in a multi-label switch case.
tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/RunMojo.java Refactors thread grouping/exception capture to avoid extending ThreadGroup and centralize thread creation/management.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +140 to +144
long deadline = System.currentTimeMillis() + 500;
long remaining;
while ((remaining = deadline - System.currentTimeMillis()) > 0) {
wait(remaining);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — switched to a private gcWaitMonitor object so wait() does not release the this monitor. The synchronized(gcWaitMonitor) { gcWaitMonitor.wait(remaining); } pattern keeps the outer this lock held (preserving mutual exclusion for recording state) while using wait() instead of Thread.sleep() to satisfy S2276. Fixed in 4cbfa57.

Claude Code on behalf of gnodet

Comment on lines +209 to +213
long deadline = System.currentTimeMillis() + 500;
long remaining;
while ((remaining = deadline - System.currentTimeMillis()) > 0) {
wait(remaining);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same fix as above — using a private gcWaitMonitor object to avoid releasing the this monitor. Fixed in 4cbfa57.

Claude Code on behalf of gnodet

Comment on lines 467 to 469
IsolatedThreadGroup(String name) {
super(name);
this.threadGroup = new ThreadGroup(name);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved @SuppressWarnings("java:S3014") to the class level so it covers both the field declaration and the new ThreadGroup(name) instantiation in the constructor. Fixed in 4cbfa57.

Claude Code on behalf of gnodet

- S2276: Use a private gcWaitMonitor object for wait() so that the
  'this' monitor of synchronized methods is not released. This prevents
  race conditions (e.g., concurrent doStart() calls both passing the
  activeRecording == null check) while still avoiding Thread.sleep()
  inside a synchronized block.
- S3014: Move @SuppressWarnings("java:S3014") from the field to the
  class level to cover both the field declaration and the constructor
  instantiation of ThreadGroup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants