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

gnodet pushed a commit to branch fix-flaky-test-themetest-34-flaky-rate-on-devel
in repository https://gitbox.apache.org/repos/asf/camel.git

commit c63a7fdfa80becf53461c0391a58925b327aeab4
Author: Guillaume Nodet <[email protected]>
AuthorDate: Mon Jul 6 21:06:15 2026 +0000

    CAMEL-23912: Fix flaky ThemeTest by using Theme's own classloader for CSS
    
    Load CSS resources via Theme.class.getClassLoader() and
    addStylesheet() instead of StyleEngine.loadStylesheet() which uses
    StyleEngine.class.getClassLoader(). Under parallel test execution
    (camel.surefire.parallel=true in the DSL parent), the two classloaders
    can diverge, causing intermittent "resource not found" failures that
    make the engine fall back to built-in defaults. The light theme test
    then fails because fallback values differ from CSS-resolved ones.
    
    Also make accent() and zebra() synchronized to match all other
    Theme accessors, and use ConcurrentHashMap for the style cache
    as a defensive measure.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
 .../camel/dsl/jbang/core/commands/tui/Theme.java   | 40 +++++++++++++++++++---
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
index 1d549acaa65b..6b62c45fa96a 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
@@ -16,11 +16,14 @@
  */
 package org.apache.camel.dsl.jbang.core.commands.tui;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import dev.tamboui.css.Styleable;
 import dev.tamboui.css.engine.StyleEngine;
@@ -70,7 +73,7 @@ final class Theme {
     private static final Style FALLBACK_MCP_DOWN = 
Style.EMPTY.fg(Color.LIGHT_RED);
     private static final Color FALLBACK_ZEBRA = Color.rgb(0x1C, 0x1C, 0x1C);
 
-    private static final Map<String, Style> CACHE = new HashMap<>();
+    private static final Map<String, Style> CACHE = new ConcurrentHashMap<>();
 
     private static boolean initialized;
     private static boolean fallbackLogged;
@@ -81,7 +84,7 @@ final class Theme {
     private Theme() {
     }
 
-    static Color accent() {
+    static synchronized Color accent() {
         StyleEngine e = engine();
         if (e == null) {
             return ACCENT;
@@ -98,7 +101,7 @@ final class Theme {
      * Subtle alternating-row background for zebra striping. Theme-aware (dark 
gray on dark, light gray on light) so
      * stripes stay readable on both terminals. Applied at the row level so it 
never overrides the selection highlight.
      */
-    static Color zebra() {
+    static synchronized Color zebra() {
         StyleEngine e = engine();
         if (e == null) {
             return FALLBACK_ZEBRA;
@@ -243,7 +246,12 @@ final class Theme {
         }
         try {
             StyleEngine e = StyleEngine.create();
-            e.loadStylesheet(mode, "tui/themes/" + mode + ".tcss");
+            // Read CSS content via Theme's own classloader instead of 
delegating
+            // to StyleEngine.loadStylesheet() which uses 
StyleEngine.class.getClassLoader().
+            // Under parallel test execution the two classloaders can diverge, 
causing
+            // intermittent "resource not found" failures in CI.
+            String cssContent = loadCssResource("tui/themes/" + mode + 
".tcss");
+            e.addStylesheet(mode, cssContent);
             e.setActiveStylesheet(mode);
             engine = e;
         } catch (Exception ex) {
@@ -253,6 +261,28 @@ final class Theme {
         return engine;
     }
 
+    /**
+     * Reads a CSS resource from the classpath using this class's own 
classloader, which is guaranteed to have access to
+     * project resources regardless of classloader hierarchy.
+     */
+    private static String loadCssResource(String path) throws IOException {
+        InputStream is = 
Theme.class.getClassLoader().getResourceAsStream(path);
+        if (is == null) {
+            // Fallback to the thread context classloader in case the class's 
own classloader
+            // doesn't have visibility (e.g., in OSGi or custom classloader 
setups).
+            ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+            if (tccl != null) {
+                is = tccl.getResourceAsStream(path);
+            }
+        }
+        if (is == null) {
+            throw new IOException("Theme CSS resource not found on classpath: 
" + path);
+        }
+        try (InputStream in = is) {
+            return new String(in.readAllBytes(), StandardCharsets.UTF_8);
+        }
+    }
+
     private static String loadPersistedMode() {
         String[] holder = { DARK };
         try {

Reply via email to