This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.22.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.22.x by this push:
new a6660150c283 [backport camel-4.22.x] CAMEL-25734: camel-core - the
bean introspection can be used by another thread while Camel starts (#28022)
a6660150c283 is described below
commit a6660150c2834f81ff20cec2c365160dddfcdf4b
Author: Guillaume Nodet <[email protected]>
AuthorDate: Sat Oct 17 20:41:25 2026 +0200
[backport camel-4.22.x] CAMEL-25734: camel-core - the bean introspection
can be used by another thread while Camel starts (#28022)
---
.../impl/engine/DefaultBeanIntrospection.java | 25 +++++---
.../impl/engine/DefaultBeanIntrospectionTest.java | 71 ++++++++++++++++++++++
2 files changed, 88 insertions(+), 8 deletions(-)
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
index 93377a086ca3..bf7851fc5a8b 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultBeanIntrospection.java
@@ -108,12 +108,17 @@ public class DefaultBeanIntrospection extends
ServiceSupport implements BeanIntr
+ obj + "]";
}
- if (preStartDone) {
- logger.log(line);
- } else {
- // remember log lines before we are starting
- preStartLogs.add(line);
+ if (!preStartDone) {
+ // other threads (such as the cli-connector, which is started
early) can use this while camel is starting
+ synchronized (preStartLogs) {
+ if (!preStartDone) {
+ // remember log lines before we are starting
+ preStartLogs.add(line);
+ return;
+ }
+ }
}
+ logger.log(line);
}
@Override
@@ -233,9 +238,13 @@ public class DefaultBeanIntrospection extends
ServiceSupport implements BeanIntr
@Override
public void afterPropertiesConfigured(CamelContext camelContext) {
// log any pre starting logs so we can see them all
- preStartLogs.forEach(logger::log);
- preStartLogs.clear();
- preStartDone = true;
+ List<String> lines;
+ synchronized (preStartLogs) {
+ lines = new ArrayList<>(preStartLogs);
+ preStartLogs.clear();
+ preStartDone = true;
+ }
+ lines.forEach(logger::log);
}
@Override
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultBeanIntrospectionTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultBeanIntrospectionTest.java
new file mode 100644
index 000000000000..941e8ac14ffb
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/impl/engine/DefaultBeanIntrospectionTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.impl.engine;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Another thread (such as the cli-connector, which is started early) can use
the bean introspection while Camel is
+ * starting, when the log lines from before the start are logged.
+ */
+public class DefaultBeanIntrospectionTest {
+
+ @Test
+ public void testUsedByAnotherThreadWhileStarting() throws Exception {
+ for (int i = 0; i < 20; i++) {
+ DefaultBeanIntrospection introspection = new
DefaultBeanIntrospection();
+ // many log lines from before the start, so logging them takes a
while
+ for (int j = 0; j < 10000; j++) {
+ introspection.cacheClass(String.class);
+ }
+
+ AtomicBoolean done = new AtomicBoolean();
+ AtomicReference<Throwable> failure = new AtomicReference<>();
+ CountDownLatch using = new CountDownLatch(1);
+ Thread other = new Thread(() -> {
+ try {
+ while (!done.get()) {
+ introspection.cacheClass(Integer.class);
+ using.countDown();
+ }
+ } catch (Throwable e) {
+ failure.set(e);
+ }
+ }, "other");
+ other.start();
+ try {
+ assertTrue(using.await(5, TimeUnit.SECONDS));
+ assertDoesNotThrow(() ->
introspection.afterPropertiesConfigured(null));
+ } finally {
+ done.set(true);
+ other.join(5000);
+ }
+ assertFalse(other.isAlive(), "the other thread should have
stopped");
+ assertNull(failure.get());
+ }
+ }
+}