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();