ammachado opened a new pull request, #24258:
URL: https://github.com/apache/camel/pull/24258
## Summary
Running the TUI from the `camel-launcher` fat-jar (`./camel.sh tui` or
`podman run camel-launcher tui`) fails immediately with:
```
dev.tamboui.terminal.BackendException: No BackendProvider found on classpath.
Add a backend dependency such as tamboui-jline3-backend or
tamboui-panama-backend.
at
dev.tamboui.terminal.BackendFactory.tryProviders(BackendFactory.java:139)
at dev.tamboui.terminal.BackendFactory.create(BackendFactory.java:91)
at dev.tamboui.tui.TuiRunner.create(TuiRunner.java:186)
at
org.apache.camel.dsl.jbang.core.commands.tui.TuiBackendHelper.createTuiRunner(TuiBackendHelper.java:36)
...
```
The same command works when the CLI is installed via JBang. This is **not**
a packaging problem: `tamboui-jline3-backend` and its
`META-INF/services/dev.tamboui.terminal.BackendProvider` SPI entry are
correctly bundled under `BOOT-INF/lib/`.
JIRA: https://issues.apache.org/jira/browse/CAMEL-23835
## Root cause
TamboUI discovers its terminal backend via
`ServiceLoader.load(BackendProvider.class)`, which keys off the
**thread-context classloader** (TCCL). The TUI deliberately installs its own
classloader as the TCCL before starting (`CamelMonitor.java:266-267`):
```java
// to make ServiceLoader work with tamboui for downloaded JARs
Thread.currentThread().setContextClassLoader(classLoader);
```
That `classLoader` arrives as `null` for **embedded** (fat-jar) plugins,
because `PluginHelper.loadPluginFromService(...)` instantiates the plugin and
calls `customize(...)` but, unlike the two downloaded-plugin paths
(`PluginHelper.java:344` and `:520`, which both call
`instance.setClassLoader(...)`), never calls `setClassLoader`. So
`TuiPlugin.classLoader` stays `null` → `CamelMonitor.classLoader` is `null` →
the TCCL is set to `null`.
With a `null` TCCL, `ServiceLoader` falls back to the system class loader
(`AppClassLoader`), which cannot see the nested `BOOT-INF/lib/*.jar` of a
Spring Boot fat-jar (only `LaunchedClassLoader` can). The provider is never
found, and TamboUI's `SafeServiceLoader.load(Class)` silently swallows the
resulting `ServiceConfigurationError`/`LinkageError` (it passes a `null` error
handler), producing the misleading "No BackendProvider found".
Proven directly inside the actual fat-jar:
```
probe loaded by: LaunchedClassLoader
system CL: AppClassLoader
[TCCL=null] SPI class not visible: ClassNotFoundException:
dev.tamboui.terminal.BackendProvider -> providers=-1
[TCCL=launched] providers=1
```
JBang works because there the TUI plugin is a *downloaded* plugin, which
goes through a path that calls `setClassLoader(...)` with a non-null
classloader chaining to the TamboUI jars.
## Fix
In `PluginHelper.loadPluginFromService(...)`, hand the loading classloader
to the plugin before customizing it, mirroring the downloaded-plugin paths:
```java
Plugin plugin = (Plugin) pluginClass.getDeclaredConstructor().newInstance();
plugin.setClassLoader(classLoader); // added
```
`Plugin.setClassLoader` is a `default` no-op, so this is harmless for every
other bundled plugin.
## Tests
Added `PluginHelperTest#testEmbeddedPluginReceivesClassLoader`, which drives
`loadPluginFromService` with a capturing `Plugin` and asserts it receives the
exact classloader used to load it. Verified it fails without the fix
(`expected: <1> but was: <0>`) and passes with it. Full `PluginHelperTest` (10
tests) green.
## Notes
- The misleading error message originates upstream in TamboUI
(`SafeServiceLoader.load(Class)` discards the real
`LinkageError`/`ServiceConfigurationError`). Worth reporting to TamboUI
separately; out of scope here.
- No upgrade-guide entry: pure bug fix with nothing to migrate.
_Claude Code on behalf of Adriano Machado_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]