davsclaus opened a new pull request, #28688: URL: https://github.com/apache/camel/pull/28688
_Claude Code on behalf of davsclaus_ Stage 1c-1 of [CAMEL-24727](https://issues.apache.org/jira/browse/CAMEL-24727), stacked on #28675 (and so on #28671): retarget to `main` once those merge. `camel-jbang-export` is the engine that `camel export` and `camel run` use, and its Java API is for tools such as Kaoto that export without the CLI. This PR makes an export keep to its request and leave the JVM as it found it, so an application can export many times, and several exports can run at the same time. There are no CLI-only or API-only branches: the CLI sets up what it needs (logging, system properties) before it calls the engine. ## Changes - **Work directory per request.** `ExportRequest.workDir` holds the run settings of the silent run and the project being built. The default is `.camel-jbang` in the current directory, as before. The silent `Run` writes its settings, compile dir and generated OpenAPI file there. - **No logging configuration in the engine.** The silent run of an export no longer calls `RuntimeUtil.configureLog`, which reconfigured log4j for the whole JVM and set system properties. `camel export` already configures logging before it exports. In the CLI, the second call only reset the root level, back to `info`, which ignored `--logging-level` of the export. - **No system properties in the engine.** `ProjectExporter.prepare` no longer reads them. `ExportBaseCommand.applySystemProperties` maps them onto the request for `camel export`, `camel dependency`/`sbom` and `camel run --runtime=...`: - `camel.jbang.camelSpringBootVersion` - the Quarkus platform properties - `camel.jbang.repos`, which now also reaches the downloads of the silent run, not only the pom.xml The `camel.jbang.quarkus.platform.url` fallback moves to the CLI option of the Quarkus Extension Registry. `CatalogLoader.loadSpringBootCatalog` gets an overload with an explicit provider version. - **Extra default repositories as an option.** `MavenDownloader` gets `setExtraRepos`/`getExtraRepos`. The precedence is: 1. the configured value (empty means none); 2. the `camel.extra.repos` system property; 3. `camel.default.extra.repos.default.value`. The first one set wins. `MavenResolver` carries the value, `KameletMain`/`MavenDependencyDownloader` pass it to the downloader of the silent run, and the exporter puts the repositories the downloads use into the pom.xml. The CLI leaves it unset, so the system properties work as before. - **An export releases its silent run.** Every export kept its whole silent run (`Run`, `KameletMain`, `CamelContext`, about 0.6 MB each) for the life of the JVM. A heap dump showed two GC roots: - The default shutdown strategy of Camel Main adds a JVM shutdown hook that is never removed. The silent run of an export now uses `SimpleMainShutdownStrategy`. - The static `ProcessorReifier` registry held the transacted reifier of `TransactedDownloader`, which captured the `KameletMain` that registered it. It now binds the policies in the registry of the route's `CamelContext`, which is the same `MainRegistry`. - **Kamelet catalog cache.** Two threads that loaded a released catalog at the same time each put their own map in the cache, so the callers did not share one (the concurrent test classes made `KameletCatalogHelperTest` flaky). It now uses `putIfAbsent`. - **Docs.** The "Exporting from Java" section of `camel-jbang-projects.adoc` describes the above. ## Tests - `ProjectExporterTest` (export, stub resolver): - 4 exports in parallel, each with its own work dir, and `./.camel-jbang` untouched; - `prepare` reads no system properties; - explicit, empty and system-property extra repos in the pom.xml. - `ExportApiTest` (core, the real silent run): - the log4j configuration and the system properties are the same after an export (this fails on the old code); - 20 exports in a row: their `CamelContext`s are all garbage collected (checked with `CamelContextTracker` and weak references), and no threads are left (this fails without the shutdown strategy fix). - `MavenDownloaderImplTest.testExtraReposPrecedence`. I ran these suites locally, and they all pass: | Module | Tests | |---|---| | camel-tooling-maven | 38 (14 skipped) | | camel-kamelet-main | 66 | | camel-jbang-export | 109 (3 more runs with retries off) | | camel-jbang-core | 2417 + 242 serial | | camel-jbang-plugin-kubernetes | 156 | | camel-jbang-plugin-validate | 23 | | camel-jbang-plugin-test | 6 | | camel-jbang-mcp | 505 | | camel-jbang-plugin-tui | 2283 | | camel-launcher | 292 (36 skipped) | The generate and mcp plugins also build. The one exception is `EvalSimpleTest`, which fails the same way on `main`: it runs the Camel installed with JBang, not this build. I did not run the camel-jbang-it integration tests. The builds left no generated files to commit. Not changed here, and left for 1c-2/1c-3: the transform runs of `camel transform` (and the TUI) boot `KameletMain` with the default shutdown strategy too, and the silent run still sets the static printer of `CommandHelper` (a ThreadLocal of the calling thread). 🤖 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]
