This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 15445c1f97ba CAMEL-23271: Fix SonarCloud blocker reliability issues 
(resource leaks) (#22343)
15445c1f97ba is described below

commit 15445c1f97ba708cd9fab2926768e14177d35590
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Apr 8 09:10:21 2026 +0200

    CAMEL-23271: Fix SonarCloud blocker reliability issues (resource leaks) 
(#22343)
    
    * CAMEL-23271: Fix SonarCloud blocker reliability issues (resource leaks)
    
    - JcrConsumer: store ScheduledExecutorService in a field and shut it down 
in doStop()
    - ModelWriterGeneratorMojo: wrap DynamicClassLoader in try-with-resources
    - Set sonar.java.source=17 to eliminate 23 HttpClient false positives
    - Add @SuppressWarnings for ExecutorService/CamelContext lifecycle false 
positives
    
    * CAMEL-23271: Use ${jdk.version} for sonar.java.source
    
    Address review feedback: use the existing jdk.version property
    instead of hardcoding '17', consistent with other compiler settings.
    
    * CAMEL-23271: Address review feedback
    
    - Move sonar.java.source above the NOTE comment so it stays with
      sonar.coverage.jacoco.xmlReportPaths (apupier)
    - Replace method-level @SuppressWarnings with line-level // NOSONAR
      to avoid masking future real leaks (squakez)
    
    * CAMEL-23271: Move @SuppressWarnings to statement level
    
    Narrow suppression scope: move @SuppressWarnings("java:S2095") from
    method level to the local variable declarations where the resources
    are created, so it won't mask future issues in the same methods.
    
    * CAMEL-23271: Use try-with-resources for CamelContext in CamelYamlParser
    
    CamelContext implements AutoCloseable, so use try-with-resources
    instead of manual stop in finally block. Removes the need for
    @SuppressWarnings.
    
    * CAMEL-23271: Remove redundant comment on sonar.java.source
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 <[email protected]>
---
 .../java/org/apache/camel/component/jcr/JcrConsumer.java | 16 +++++++++-------
 .../camel/component/salesforce/SalesforceComponent.java  |  3 ++-
 .../java/org/apache/camel/reifier/AggregateReifier.java  |  2 ++
 .../java/org/apache/camel/reifier/ThreadsReifier.java    |  2 ++
 .../apache/camel/dsl/yaml/validator/CamelYamlParser.java | 12 +++---------
 pom.xml                                                  |  1 +
 .../camel/maven/packaging/ModelWriterGeneratorMojo.java  | 10 +++++++---
 7 files changed, 26 insertions(+), 20 deletions(-)

diff --git 
a/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrConsumer.java
 
b/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrConsumer.java
index 63d628337de8..c01cb229b8e6 100644
--- 
a/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrConsumer.java
+++ 
b/components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrConsumer.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.jcr;
 
 import java.util.Arrays;
 import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
 import javax.jcr.RepositoryException;
@@ -40,7 +39,7 @@ public class JcrConsumer extends DefaultConsumer {
 
     private Session session;
     private EventListener eventListener;
-    private ScheduledFuture<?> sessionListenerCheckerScheduledFuture;
+    private ScheduledExecutorService sessionListenerCheckerExecutor;
 
     public JcrConsumer(JcrEndpoint endpoint, Processor processor) {
         super(endpoint, processor);
@@ -157,20 +156,23 @@ public class JcrConsumer extends DefaultConsumer {
     }
 
     private void cancelSessionListenerChecker() {
-        if (sessionListenerCheckerScheduledFuture != null) {
-            sessionListenerCheckerScheduledFuture.cancel(true);
+        if (sessionListenerCheckerExecutor != null) {
+            getJcrEndpoint().getCamelContext().getExecutorServiceManager()
+                    .shutdownNow(sessionListenerCheckerExecutor);
+            sessionListenerCheckerExecutor = null;
         }
     }
 
     private void scheduleSessionListenerChecker() {
         String name = "JcrConsumerSessionChecker[" + 
getJcrEndpoint().getEndpointConfiguredDestinationName() + "]";
-        ScheduledExecutorService executor = 
getJcrEndpoint().getCamelContext().getExecutorServiceManager()
+        sessionListenerCheckerExecutor = 
getJcrEndpoint().getCamelContext().getExecutorServiceManager()
                 .newSingleThreadScheduledExecutor(this, name);
         JcrConsumerSessionListenerChecker sessionListenerChecker = new 
JcrConsumerSessionListenerChecker();
         long sessionLiveCheckIntervalOnStart = 
JcrConsumer.this.getJcrEndpoint().getSessionLiveCheckIntervalOnStart();
         long sessionLiveCheckInterval = 
JcrConsumer.this.getJcrEndpoint().getSessionLiveCheckInterval();
-        sessionListenerCheckerScheduledFuture = 
executor.scheduleWithFixedDelay(sessionListenerChecker,
-                sessionLiveCheckIntervalOnStart, sessionLiveCheckInterval, 
TimeUnit.MILLISECONDS);
+        sessionListenerCheckerExecutor.scheduleWithFixedDelay(
+                sessionListenerChecker, sessionLiveCheckIntervalOnStart, 
sessionLiveCheckInterval,
+                TimeUnit.MILLISECONDS);
     }
 
     private class JcrConsumerSessionListenerChecker implements Runnable {
diff --git 
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
 
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
index 8224c736f693..7766a18ab09e 100644
--- 
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
+++ 
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
@@ -963,7 +963,8 @@ public class SalesforceComponent extends DefaultComponent 
implements SSLContextP
             int workerPoolMaxSize) {
         SecurityUtils.adaptToIBMCipherNames(sslContextFactory);
 
-        final SalesforceHttpClient httpClient = new SalesforceHttpClient(
+        // ExecutorService lifecycle is managed by SalesforceHttpClient
+        final SalesforceHttpClient httpClient = new SalesforceHttpClient( // 
NOSONAR
                 context, 
context.getExecutorServiceManager().newThreadPool(source, 
"SalesforceHttpClient", workerPoolSize,
                         workerPoolMaxSize),
                 sslContextFactory);
diff --git 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
index 55f2a12c0534..d3f2f4744e67 100644
--- 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
+++ 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/AggregateReifier.java
@@ -76,6 +76,8 @@ public class AggregateReifier extends 
ProcessorReifier<AggregateDefinition> {
 
         boolean parallel = parseBoolean(definition.getParallelProcessing(), 
false);
         boolean shutdownThreadPool = willCreateNewThreadPool(definition, 
parallel);
+        // ExecutorService lifecycle is managed by AggregateProcessor via 
shutdownThreadPool flag
+        @SuppressWarnings("java:S2095")
         ExecutorService threadPool = 
getConfiguredExecutorService("Aggregator", definition, parallel);
         if (threadPool == null && !parallel) {
             // executor service is mandatory for the Aggregator
diff --git 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java
 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java
index 67db283c8f55..62636c656649 100644
--- 
a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java
+++ 
b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThreadsReifier.java
@@ -43,6 +43,8 @@ public class ThreadsReifier extends 
ProcessorReifier<ThreadsDefinition> {
         }
         // prefer any explicit configured executor service
         boolean shutdownThreadPool = willCreateNewThreadPool(definition, true);
+        // ExecutorService lifecycle is managed by ThreadsProcessor via 
shutdownThreadPool flag
+        @SuppressWarnings("java:S2095")
         ExecutorService threadPool = getConfiguredExecutorService(name, 
definition, false);
 
         // resolve what rejected policy to use
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
index b8444f4b30bd..bf2975578880 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java
@@ -50,12 +50,10 @@ import org.apache.camel.support.ResourceHelper;
 public class CamelYamlParser {
 
     public List<ValidationMessage> parse(File file) throws Exception {
-        CamelContext camelContext = null;
-        try {
-            DefaultRegistry registry = new DefaultRegistry();
-            registry.addBeanRepository(new StubBeanRepository("*"));
+        DefaultRegistry registry = new DefaultRegistry();
+        registry.addBeanRepository(new StubBeanRepository("*"));
 
-            camelContext = new DefaultCamelContext(registry);
+        try (CamelContext camelContext = new DefaultCamelContext(registry)) {
             camelContext.setAutoStartup(false);
             
camelContext.getCamelContextExtension().addContextPlugin(ComponentResolver.class,
                     (name, context) -> new StubComponent());
@@ -101,10 +99,6 @@ public class CamelYamlParser {
             ValidationMessage vm = ValidationMessage.builder().type("parser")
                     .messageSupplier(() -> e.getClass().getName() + ": " + 
e.getMessage()).build();
             return List.of(vm);
-        } finally {
-            if (camelContext != null) {
-                camelContext.stop();
-            }
         }
     }
 
diff --git a/pom.xml b/pom.xml
index 994f1d1d320a..fb2306bcc59f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -120,6 +120,7 @@
         <!-- reproducible builds: 
https://maven.apache.org/guides/mini/guide-reproducible-builds.html -->
         
<project.build.outputTimestamp>2026-02-17T16:11:10Z</project.build.outputTimestamp>
 
+        <sonar.java.source>${jdk.version}</sonar.java.source>
         <!-- NOTE: this is required to correctly map each module coverage in 
Sonarqube. The ${maven.multiModuleProjectDirectory} may require some change
             when upgrading to Maven 4.x, according to any of the new variables 
that will replace this one. -->
         <sonar.coverage.jacoco.xmlReportPaths>
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelWriterGeneratorMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelWriterGeneratorMojo.java
index 4ccebcfaa24a..276208ad0461 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelWriterGeneratorMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/ModelWriterGeneratorMojo.java
@@ -113,13 +113,17 @@ public abstract class ModelWriterGeneratorMojo extends 
AbstractGeneratorMojo {
     abstract String getWriterPackage();
 
     protected String generateWriter() throws MojoExecutionException {
-        ClassLoader classLoader;
-        try {
-            classLoader = 
DynamicClassLoader.createDynamicClassLoader(project.getCompileClasspathElements());
+        try (DynamicClassLoader classLoader
+                = 
DynamicClassLoader.createDynamicClassLoader(project.getCompileClasspathElements()))
 {
+            return doGenerateWriter(classLoader);
         } catch (DependencyResolutionRequiredException e) {
             throw new 
MojoExecutionException("DependencyResolutionRequiredException: " + 
e.getMessage(), e);
+        } catch (IOException e) {
+            throw new MojoExecutionException("IOException: " + e.getMessage(), 
e);
         }
+    }
 
+    private String doGenerateWriter(ClassLoader classLoader) throws 
MojoExecutionException {
         List<Path> jsonFiles;
         try (Stream<Path> stream = 
PackageHelper.findJsonFiles(modelDir.toPath())) {
             jsonFiles = stream.toList();

Reply via email to