You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by "allthingssecurity (via GitHub)" <gi...@apache.org> on 2026/10/14 00:03:42 UTC

[PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

allthingssecurity opened a new pull request, #27793:
URL: https://github.com/apache/camel/pull/27793

   # Description
   
   [CAMEL-25606](https://issues.apache.org/jira/browse/CAMEL-25606)
   
   Part 2 of 4 of the camel-wasm redesign (part 1: #27678, merged): an optional runtime compiler for the `wasm` endpoint.
   
   Author: Shashank Mohan Jain (@allthingssecurity), working with Claude Code (Claude Opus 5.5).
   
   Scope: camel-wasm only. The Endive version alignment of camel-opa and camel-quickjs (both still resolve some Endive 1.0.0 artifacts through their libraries) is **not** in this PR. It will be proposed separately, once the container integration tests of camel-opa have run on Endive 1.1.0. camel-wasm itself already resolves Endive 1.1.0 for every Endive artifact, with and without this PR.
   
   ## What changes
   
   - **`compile` option** (boolean, default `false`) on the `wasm` endpoint. With `compile=true` the module is translated to JVM bytecode with the Endive runtime compiler (`MachineFactoryCompiler`) instead of being interpreted. `WasiCommand` compiles in its constructor and passes the machine factory to every per-exchange instance (`Instance.Builder.withMachineFactory`), so exchanges still run on separate instances and share only the generated classes.
   - **Loaded once per endpoint**: the endpoint loads the module, checks it and (with `compile=true`) compiles it when its first producer is initialized, and keeps that immutable `WasiCommand` for as long as the endpoint exists. Since #27678 every producer parsed the module itself, and a route start creates a new producer, so with a compiler the same module would be compiled at every route start. Consequences:
     - compilation happens when the route is first started, or at the first message with `lazyStartProducer=true` or a `toD`;
     - a route stop and start gets a new producer but the same command: the module is neither read nor compiled again (this is a change from #27678, where a restarted route read the module again; it is in the upgrade note);
     - the generated classes can only be unloaded when the endpoint is no longer reachable (route removed, context stopped), not when a route stops;
     - a dev-mode route reload removes all routes and clears the endpoint registry by default (`RouteWatcherReloadStrategy`), so it reads and compiles the module again;
     - with `toD`, every different URI is its own endpoint with its own compiled copy, so many different compiled URIs grow metaspace. The docs say so.
     - a failed load is not kept: the next producer that is initialized tries again.
   - **Functions too large for a JVM method**: Endive leaves such a function to the interpreter and compiles the rest. Its default (`InterpreterFallback.WARN`) reports that with `System.err.println`. `WasiCommand` instead compiles with `FAIL` first; if that fails it compiles again with `SILENT` and logs once per endpoint at WARN, naming the module. The module keeps working, nothing is written to `System.err`, and the second compilation only happens for a module that has such a function.
   - **A module the compiler cannot translate** (for example one with a vector instruction: Endive's parser accepts `v128.const`, its compiler does not) fails when the first producer is initialized, with an `IllegalStateException` that names the module by its program name (the file name only, as for argument zero in #27678) and has the Endive exception as cause.
   - **Missing compiler**: `WasiCommand` refers to the compiler through one nested class, so it loads and interprets without `run.endive:compiler` on the classpath; `compile=true` then fails with an `IllegalStateException` that names the artifact.
   - **Same behaviour with the compiler on**: result headers, exit codes, traps (`TrapException` as the cause, stderr in the message, the hint about a memory at its maximum), `maxMemoryPages`, `maxOutputSize`, environment, arguments, `SecureRandom` for `random_get`, `timeout`, and what #27678 gained in review (with a timeout the body is read into memory on the calling thread, a stream opened by the type converter is closed, a stream of the caller is not, the body after a failed run).
   - **Default off**: compiling costs start-up time and generates classes at run time, which a GraalVM native image cannot load.
   
   New public API: `WasmConfiguration.isCompile/setCompile`, `WasiCommand(WasmModule, List<String>, int, boolean)` and `WasiCommand.isCompiled()`. The three-argument `WasiCommand` constructor is kept. Package-private, for tests: `WasmProducer.command()`, `WasiCommand.usesInterpreterFallback()`.
   
   Not changed: the `wasm` language, instance handling (a new instance per exchange), all other options. No component-wide module cache and no instance pooling.
   
   ## Questions a reviewer may have
   
   - **Does `timeout` stop compiled code?** Yes. The Endive 1.1.0 compiler emits a call to `Shaded.checkInterruption` (which throws when the thread is interrupted) at calls, at indirect calls and at branches inside a function; I read this in the bytecode of the compiler. `timeoutInterruptsASpinningModule` (a module in an endless loop, stopped by `timeout=500`) passes with `compile=true`.
   - **Is the compiled code really used?** `compileOptionSelectsCompiledCodeOrTheInterpreter` asserts that the guest frames of a trap are only `run.endive.$gen.*` classes with `compile=true`, and only `InterpreterMachine` frames without.
   - **Is sharing the machine factory between threads safe?** The factory is a function from an `Instance` to a new `Machine`; every exchange builds its own instance and so gets its own machine. Evidence: `parallelExchanges` (8 threads x 50 exchanges on one endpoint) passes with `compile=true`. I did not review Endive's generated code for shared static state beyond that.
   - **Security model**: unchanged. A module is trusted route code; the option gives the guest no new capability (same streams, arguments and environment, no files, no sockets), relaxes no default and is not marked `insecure:*`. Endive's documentation recommends the interpreter for untrusted modules because the generated bytecode is not verified after compilation; in Camel the module is chosen by the route author, like a bean.
   - **Dependencies**: `run.endive:compiler` 1.1.0 (163 KB, Apache-2.0) as a normal dependency of camel-wasm, which brings ASM 9.10.1 (`asm`, `asm-commons`, `asm-tree`, `asm-util`, `asm-analysis`, 384 KB together, the version `parent/pom.xml` already manages). `dependency:tree` of camel-wasm on this commit: `runtime`, `wasm`, `wasi`, `log`, `compiler` all 1.1.0, `wabt` 1.1.0 in test scope. `camel-sbom` is not regenerated here.
   
   ## Docs and generated files
   
   - `wasm-component.adoc`, "Performance": describes `compile=true`, when the module is compiled and when it is not compiled again (see above), the `toD` note, when to keep the default (start-up time, native image), the fallback for functions that are too large, and a pointer to Endive's build-time compiler plugin with the statement that the endpoint does not use classes generated at build time. The section is qualitative: no numbers.
   - 4.24 upgrade guide: one paragraph inside the existing camel-wasm section (the `compile` option, the new `run.endive:compiler` and ASM dependency, the module loaded once per endpoint).
   - Regenerated: component metadata (`wasm.json`, configurers, URI factory) by the camel-wasm build; the endpoint DSL (`WasmEndpointBuilderFactory`) with the `generate-endpoint-dsl` mojo. The two catalog files (`components/wasm.json`, `docs/wasm-component.adoc`) are copies of the component files; I did not run `prepare-catalog` for them.
   
   ## Tests
   
   All on the commit of this PR, on top of `main` at d05541613fc7.
   
   camel-wasm with `verify` (formatter, import sort, generation): **132 tests, 0 failures** (`WasmComponentTest` 58, `WasmCompiledComponentTest` 58, `WasmLanguageTest` 6, `WasiCommandTest` 7, `WasmFunctionTest` 3).
   
   - `WasmCompiledComponentTest` extends `WasmComponentTest` and runs every test of it with `compile=true`: body and headers, exit codes, traps with and without a timeout, environment and arguments, `random_get`, the spinning module stopped by `timeout`, the sleeping module ended by the interrupt, the tests #27678 added in review, the route restart with a timeout, `maxMemoryPages`, `maxOutputSize`, a fresh instance per exchange, 8 threads x 50 exchanges, and the start failures. The test modules are written in WAT and translated when the tests run; no binary is added.
   - `moduleIsLoadedOncePerEndpoint` (both classes): after the first exchange the module file is deleted; a second producer of the same endpoint starts, processes an exchange and has the same `WasiCommand` instance as the endpoint returned before.
   - `routeStopAndStartKeepsTheLoadedModule` (both classes): the route is stopped, the module file deleted, the route started; the next exchange works and the endpoint still returns the same `WasiCommand` instance.
   - `moduleIsLoadedAgainAfterAFailedLoad` (both classes): a producer of an endpoint whose module file does not exist fails to start; after the file is written, the next producer of the same endpoint starts and runs it.
   - `compileOptionSelectsCompiledCodeOrTheInterpreter` (both classes): see above.
   - `WasiCommandTest.functionTooLargeForAJvmMethodIsInterpreted`: a module whose `_start` has 70000 times `i32.const 1; drop` (210 KB, built in the test) is compiled with the fallback, runs and exits with 0, and nothing about it is printed to `System.err` during the compilation. The WARN line itself is not asserted (I saw it in the test log).
   - `WasiCommandTest.moduleThatCannotBeCompiledFailsWithItsName`: a module with a `v128.const` instruction fails with the message that starts with `The Wasm module simd.wasm cannot be compiled to JVM bytecode (compile=true): ` and a `WasmEngineException` as cause.
   - `WasiCommandTest.compiledCodeIsGeneratedOnceAndRunsEveryInstance`, `interpretedByDefault`, `compileWithoutTheCompilerOnTheClasspathFails`: as before (same generated classes for two runs; no generated class when interpreted; with a class loader that hides `run.endive.compiler.*` the interpreter works and `compile=true` fails with the message that names `run.endive:compiler`).
   
   Sensitivity, on this commit: with the endpoint not keeping the command, Endive's default compile call instead of the explicit fallback handling, and the wrapping of compile failures removed, 6 tests fail: `moduleIsLoadedOncePerEndpoint` and `routeStopAndStartKeepsTheLoadedModule` in both classes (`FileNotFoundException`), and the two new `WasiCommandTest` tests. `moduleIsLoadedAgainAfterAFailedLoad` pins the existing behaviour and does not fail under these changes.
   
   Not run:
   
   - A GraalVM native image (neither that `compile=true` fails there nor that the interpreter works there).
   - The full build from the root, and `prepare-catalog`.
   - A dev-mode route reload with a compiled module (the statement above comes from reading `RouteWatcherReloadStrategy`), and a measurement of metaspace with `toD`.
   - camel-opa and camel-quickjs: not touched by this PR, so not run.
   
   ## Performance
   
   Not measured on this commit. The numbers below were measured through a route (`ProducerTemplate.requestBody` -> `direct:` -> `wasm:`), one thread, median after a warm-up, two rounds in one JVM, Apple M4 Pro, JDK 21, Endive 1.1.0, with a probe that is not part of the PR, **on an earlier base** (an earlier head of #27678, before its final review changes and before the changes of this PR to the fallback handling). Indicative only; that is why the component page has no numbers.
   
   | Module, body | Interpreted | `compile=true` | First route start, interpreted / compiled |
   |---|---|---|---|
   | WAT upper-case module (538 B), 1 KiB (n=2000 after 300) | 225-275 us | 32-35 us | 3-45 ms / 5-50 ms |
   | same, 1 MiB (n=30 after 5) | 210-269 ms | 1.4 ms in round 2, 17 ms in round 1 (before the JIT compiled the loop) | 3-4 ms / 8 ms |
   | Rust `no_std` WASI command (3.9 KB), 1 KiB (n=2000 after 300) | 230-237 us | 32-45 us | 3-10 ms / 7-12 ms |
   | standard Go 1.26 `GOOS=wasip1` program (2.3 MB), 1 KiB (n=50 after 5 / n=200 after 20) | 30-31 ms | 3.9-4.1 ms | 0.2-0.3 s / 0.6-1.1 s |
   
   The first round of each row includes class loading of Camel and Endive in the start time. None of these modules has a function that is too large for a JVM method, so none was compiled twice.
   
   ## Questions
   
   1. `run.endive:compiler` as a normal dependency (this PR) or optional? Normal adds about 0.55 MB of jars (compiler + ASM) for every camel-wasm user; optional would need `--dep` with `camel run`.
   2. Build-time compiled modules: Endive's Maven plugin generates a class with a machine factory, which is the native-image friendly way. The endpoint has no option to use such a class, so the docs only point to the plugin and say so. Should a later PR add a hook (for example a `#bean` reference to a `run.endive.runtime.CompiledModule`)?
   3. `InterpreterFallback`: this PR keeps a module with a function that is too large working (compile with `FAIL`, then with `SILENT`, and a WARN in the log), at the price of a second compilation for such modules. The alternatives are `SILENT` only (one compilation, but no way to tell the user through the public API of Endive) or `FAIL` (the route does not start). Which do you prefer?
   4. Module loading moved from the producer to the endpoint, and the command is kept for as long as the endpoint exists: a module file that changes is only read again by a new endpoint (in #27678: at the next route start). Is that the lifecycle you want, or should the endpoint drop the command when it stops, which would compile again at every restart of the context but not of a route?
   
   ## Plan
   
   1. #27678 (merged): WASI runner, endpoint and limits replacing the custom ABI, docs and upgrade note.
   2. **This PR**: optional runtime compiler (`compile=true`, off by default because of native images), docs pointer to the Endive build-time compiler plugin.
   3. The `wasm` language: rebase it on `WasiCommand`, or drop it.
   4. Rust and Go examples in camel-examples.
   
   Separately: one Endive version for camel-opa and camel-quickjs.
   
   @davsclaus please review.
   
   # Target
   
   - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch)
   
   # Tracking
   - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it).
   
   # Apache Camel coding standards and style
   
   - [x] I checked that each commit in the pull request has a meaningful subject line and body.
   - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes.
     (I built and tested camel-wasm with `verify`, including the formatter and import-sort plugins, and regenerated the endpoint DSL with the camel-package-maven-plugin mojo. I did not run the full root build.)
   
   # AI-assisted contributions
   
   - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used.
     Prepared by Shashank Mohan Jain (@allthingssecurity) with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer.
   
   _Claude Code on behalf of allthingssecurity_
   
   🤖 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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "allthingssecurity (via GitHub)" <gi...@apache.org>.
allthingssecurity commented on code in PR #27793:
URL: https://github.com/apache/camel/pull/27793#discussion_r4265513310


##########
components/camel-wasm/pom.xml:
##########
@@ -54,6 +54,12 @@
             <artifactId>wasi</artifactId>
             <version>${endive-version}</version>
         </dependency>
+        <!-- used with compile=true only: translates a module to JVM bytecode, once per endpoint -->
+        <dependency>
+            <groupId>run.endive</groupId>
+            <artifactId>compiler</artifactId>
+            <version>${endive-version}</version>
+        </dependency>

Review Comment:
   Thanks. This is question 1 in the description, and I would like a maintainer to decide it before I change the pom. The trade-off as I see it: optional saves about 0.55 MB of jars (compiler plus ASM, in the version Camel already manages) for users who never set `compile=true`, but then `compile=true` does not work out of the box: with `camel run` it needs `--dep run.endive:compiler:<version>`, and a user finds that out from the `IllegalStateException` at the first start. The code path and the test for the missing jar are there, so switching to `<optional>true</optional>` is a one-line change plus a sentence in the component page; I will make it if that is the preferred default.
   
   _Claude Code on behalf of allthingssecurity_



##########
components/camel-wasm/src/main/java/org/apache/camel/wasm/WasiCommand.java:
##########
@@ -73,10 +91,77 @@ public final class WasiCommand {
      *                                  than the initial memory the module declares
      */
     public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages) {
+        this(module, arguments, maxMemoryPages, false);
+    }
+
+    /**
+     * @param  module                   the parsed module
+     * @param  arguments                the program's arguments, the program name first
+     * @param  maxMemoryPages           the maximum number of 64 KiB pages the module's memory may grow to, or 0 to keep
+     *                                  the maximum the module declares
+     * @param  compile                  whether to translate the module to JVM bytecode now, with the Endive runtime
+     *                                  compiler, instead of interpreting it. This defines classes at run time, which a
+     *                                  GraalVM native image cannot do. A function that is too large for a JVM method is
+     *                                  left to the interpreter, which is logged once, at WARN
+     * @throws IllegalArgumentException if the module is not a WASI Preview 1 command module, or maxMemoryPages is lower
+     *                                  than the initial memory the module declares
+     * @throws IllegalStateException    if compile is set and the Endive runtime compiler is not on the classpath, or
+     *                                  cannot compile the module. The message names the module by its program name (the
+     *                                  first argument)
+     */
+    public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages, boolean compile) {
         this.module = Objects.requireNonNull(module);
         this.arguments = List.copyOf(arguments);
         validate(module);
         this.memoryLimits = memoryLimits(module, maxMemoryPages);
+
+        Function<Instance, Machine> factory = null;
+        boolean fallback = false;
+        if (compile) {
+            String name = this.arguments.isEmpty() ? "(no name)" : this.arguments.get(0);
+            try {
+                try {
+                    factory = RuntimeCompiler.compile(module, false);
+                } catch (WasmEngineException e) {
+                    // Endive could not compile every function. When the reason is a function that is too large for a
+                    // JVM method, the module still works with that function interpreted, so compile again with the
+                    // interpreter as fallback; for any other reason this second attempt fails as the first one did.
+                    factory = RuntimeCompiler.compile(module, true);
+                    fallback = true;
+                    LOG.warn("The Wasm module {} is compiled in part only: it has functions that are too large for a"

Review Comment:
   Thanks. I chose WARN because it is logged once per endpoint, at the first start, and it tells the operator that `compile=true` is only partly in effect for this module, which they asked for and are not getting in full; nothing else reports it. INFO would also be fine with me, since the module does run correctly. It belongs to question 3 in the description (fallback with a log line, silent fallback, or failure), so I will follow what the maintainers prefer there and change the level in the same step.
   
   _Claude Code on behalf of allthingssecurity_



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on code in PR #27793:
URL: https://github.com/apache/camel/pull/27793#discussion_r4266921943


##########
components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmEndpoint.java:
##########
@@ -63,6 +75,44 @@ public WasmConfiguration getConfiguration() {
         return configuration;
     }
 
+    /**
+     * The module of this endpoint as a command. The module is loaded, checked and, with compile=true, compiled on the
+     * first call, by the first producer that is initialized; all producers of the endpoint then share the result, which
+     * is immutable, for as long as the endpoint exists. So a route that is stopped and started again gets a new
+     * producer, but neither loads nor compiles the module again, and the classes generated for a compiled module can
+     * only be unloaded when the endpoint is no longer reachable (removed from the context, or the context stopped), not
+     * when a route stops.
+     * <p/>
+     * A failed call leaves nothing behind, so the next call (of the next producer that is initialized) tries again.
+     */
+    WasiCommand command() throws Exception {
+        WasiCommand answer = command;
+        if (answer == null) {
+            lock.lock();
+            try {
+                answer = command;
+                if (answer == null) {
+                    List<String> arguments
+                            = WasmProducer.arguments(WasmProducer.programName(module), configuration.getArgs());

Review Comment:
   Nit: the endpoint now calls `WasmProducer.arguments`, `WasmProducer.programName` and `WasmProducer.checkNoNul` (which lost its `private` for this). The module is loaded and checked by the endpoint now, so these helpers belong next to `command()`. Consider moving them to `WasmEndpoint` (or a small package-private helper). `WasmProducer` can call them from there for the environment checks.



##########
docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc:
##########
@@ -111,6 +111,12 @@ module.
 * `WasmSupport.deserialize(byte[], Exchange)`.
 * The constructor `WasmProducer(Endpoint, String, String)` is replaced by `WasmProducer(WasmEndpoint)`.
 
+The endpoint has a new `compile` option (default `false`) that runs a module as JVM bytecode instead of interpreting
+it. For this option `camel-wasm` has a new dependency, `run.endive:compiler`, which brings in ASM (`org.ow2.asm`).
+The module is now loaded once per endpoint and no longer by every producer, so stopping and starting a route does
+not read the module again: remove the route and add it again, or restart the application, to load a module that
+has changed.

Review Comment:
   Suggestion: lead with what changes for an upgrading user (the new dependency and the loading change). CLAUDE.md keeps the upgrade guide to migration notes, not features.
   
   ```suggestion
   `camel-wasm` has a new dependency, `run.endive:compiler`, which brings in ASM (`org.ow2.asm`). It is used by the
   new `compile` option of the endpoint (default `false`). The module is now loaded once per endpoint and no longer by
   every producer, so stopping and starting a route does not read the module again: remove the route and add it
   again, or restart the application, to load a module that has changed.
   ```



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on PR #27793:
URL: https://github.com/apache/camel/pull/27793#issuecomment-6163046916

   2 remove wasm language, this module was an experiment so its fine to do such changes


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #27793:
URL: https://github.com/apache/camel/pull/27793#issuecomment-6161801765

   <!-- ci-tested-modules -->
   :test_tube: **CI tested the following changed modules:**
   
   - `catalog/camel-catalog`
   - `components/camel-wasm`
   - `docs`
   - `dsl/camel-endpointdsl`
   
   ---
   
   <details><summary>:microscope: Scalpel shadow comparison — Scalpel: 8 of 703 tested, 3 compile-only — current: 8 all tested</summary>
   
   [Maveniverse Scalpel](https://github.com/maveniverse/scalpel) detected **8 affected modules** (current approach: 8).
   
   **Skip-tests mode would test 8 modules** (4 direct + 0 downstream), **skip tests for 3** (generated code, meta-modules)
   
   <details><summary>Modules Scalpel would test (8)</summary>
   
   - `camel-jbang-mcp` ← depends on affected reactor module org.apache.camel:camel-yaml-dsl-validator
   - `camel-jbang-plugin-mcp` ← depends on affected reactor module org.apache.camel:camel-jbang-core
   - `camel-jbang-plugin-tui` ← depends on affected reactor module org.apache.camel:camel-yaml-dsl-validator
   - `camel-jbang-plugin-validate` ← depends on affected reactor module org.apache.camel:camel-yaml-dsl-validator
   - `camel-launcher-container` ← depends on affected reactor module org.apache.camel:camel-launcher
   - `camel-wasm` ← components/camel-wasm/src/generated/java/org/apache/camel/component/wasm/WasmConfigurationConfigurer.java, components/camel-wasm/src/generated/java/org/apache/camel/component/wasm/WasmEndpointConfigurer.java, components/camel-wasm/src/generated/java/org/apache/camel/component/wasm/WasmEndpointUriFactory.java, components/camel-wasm/src/generated/resources/META-INF/org/apache/camel/component/wasm/wasm.json, components/camel-wasm/src/main/docs/wasm-component.adoc, components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmConfiguration.java, components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmEndpoint.java, components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmProducer.java, components/camel-wasm/src/main/java/org/apache/camel/wasm/WasiCommand.java, components/camel-wasm/src/test/java/org/apache/camel/component/wasm/WasmCompiledComponentTest.java, components/camel-wasm/src/test/java/org/apache/camel/component/wasm/
 WasmComponentTest.java, components/camel-wasm/src/test/java/org/apache/camel/wasm/WasiCommandTest.java, own pom components/camel-wasm/pom.xml changed
   - `camel-yaml-dsl-validator` ← depends on affected reactor module org.apache.camel:camel-catalog
   - `camel-yaml-dsl-validator-maven-plugin` ← depends on affected reactor module org.apache.camel:camel-yaml-dsl-validator
   
   </details>
   
   <details><summary>Modules with tests skipped (3)</summary>
   
   - `camel-itest`
   - `camel-yaml-dsl`
   - `camel-yaml-dsl-deserializers`
   
   </details>
   
   > :information_source: Shadow mode — Scalpel observes but does not affect test execution. [Learn more](https://github.com/maveniverse/scalpel)
   
   </details>
   
   <details><summary>All tested modules (35 modules, 5m 16s total)</summary>
   
   **Total reactor time:** 5m 16s
   
   | Module | Duration | Status |
   | --- | --- | --- |
   | Camel :: Launcher | 43.7s | SUCCESS |
   | Camel :: JBang :: MCP | 37.6s | SUCCESS |
   | Camel :: YAML DSL :: Validator | 23.0s | SUCCESS |
   | Camel :: Catalog :: Camel Catalog | 21.9s | SUCCESS |
   | Camel :: Component DSL | 21.5s | SUCCESS |
   | Camel :: YAML DSL | 20.3s | SUCCESS |
   | Camel :: JBang :: Plugin :: Kubernetes | 19.8s | SUCCESS |
   | Camel :: Wasm | 19.0s | SUCCESS |
   | Camel :: JBang :: Plugin :: Validate | 16.4s | SUCCESS |
   | Camel :: JBang :: Plugin :: Testing | 12.4s | SUCCESS |
   | Camel :: Docs | 11.7s | SUCCESS |
   | Camel :: Kamelet Main | 10.3s | SUCCESS |
   | Camel :: YAML DSL :: Validator Maven Plugin | 8.6s | SUCCESS |
   | Camel :: Catalog :: Camel Route Parser | 8.0s | SUCCESS |
   | Camel :: YAML DSL :: Deserializers | 7.8s | SUCCESS |
   | Camel :: Catalog :: Camel Report Maven Plugin | 7.3s | SUCCESS |
   | Camel :: All Components Sync point | 5.8s | SUCCESS |
   | Camel :: YAML DSL :: Maven Plugins | 3.1s | SUCCESS |
   | Camel :: Catalog :: Maven | 3.1s | SUCCESS |
   | Camel :: Catalog :: Suggest (deprecated) | 2.6s | SUCCESS |
   | Camel :: Assembly | 2.0s | SUCCESS |
   | Camel :: JBang :: Plugin :: Edit | 1.4s | SUCCESS |
   | Camel :: JBang :: Plugin :: MCP | 1.4s | SUCCESS |
   | Camel :: Coverage | 1.1s | SUCCESS |
   | Camel :: Catalog :: Dummy Component | 1.1s | SUCCESS |
   | Camel :: JBang :: Integration tests | 1.0s | SUCCESS |
   | Camel :: JBang :: Plugin :: Generate | 1.0s | SUCCESS |
   | Camel :: Endpoint DSL :: Support | 0.8s | SUCCESS |
   | Camel :: Catalog :: Console | 0.7s | SUCCESS |
   | Camel :: Launcher :: Container | 0.7s | SUCCESS |
   | Camel :: JBang :: Main | 0.6s | SUCCESS |
   | Camel :: Endpoint DSL | n/a |  |
   | Camel :: Integration Tests | n/a |  |
   | Camel :: JBang :: Core | n/a |  |
   | Camel :: JBang :: Plugin :: TUI | n/a |  |
   
   **Top 20 slowest modules:**
   - `Camel :: Launcher` (43.7s)
   - `Camel :: JBang :: MCP` (37.6s)
   - `Camel :: YAML DSL :: Validator` (23.0s)
   - `Camel :: Catalog :: Camel Catalog` (21.9s)
   - `Camel :: Component DSL` (21.5s)
   - `Camel :: YAML DSL` (20.3s)
   - `Camel :: JBang :: Plugin :: Kubernetes` (19.8s)
   - `Camel :: Wasm` (19.0s)
   - `Camel :: JBang :: Plugin :: Validate` (16.4s)
   - `Camel :: JBang :: Plugin :: Testing` (12.4s)
   - `Camel :: Docs` (11.7s)
   - `Camel :: Kamelet Main` (10.3s)
   - `Camel :: YAML DSL :: Validator Maven Plugin` (8.6s)
   - `Camel :: Catalog :: Camel Route Parser` (8.0s)
   - `Camel :: YAML DSL :: Deserializers` (7.8s)
   - `Camel :: Catalog :: Camel Report Maven Plugin` (7.3s)
   - `Camel :: All Components Sync point` (5.8s)
   - `Camel :: YAML DSL :: Maven Plugins` (3.1s)
   - `Camel :: Catalog :: Maven` (3.1s)
   - `Camel :: Catalog :: Suggest (deprecated)` (2.6s)
   
   </details>
   
   ---
   :gear: [View full build and test results](https://github.com/apache/camel/actions/runs/38487957225)


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "allthingssecurity (via GitHub)" <gi...@apache.org>.
allthingssecurity commented on code in PR #27793:
URL: https://github.com/apache/camel/pull/27793#discussion_r4267170128


##########
components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmEndpoint.java:
##########
@@ -63,6 +75,44 @@ public WasmConfiguration getConfiguration() {
         return configuration;
     }
 
+    /**
+     * The module of this endpoint as a command. The module is loaded, checked and, with compile=true, compiled on the
+     * first call, by the first producer that is initialized; all producers of the endpoint then share the result, which
+     * is immutable, for as long as the endpoint exists. So a route that is stopped and started again gets a new
+     * producer, but neither loads nor compiles the module again, and the classes generated for a compiled module can
+     * only be unloaded when the endpoint is no longer reachable (removed from the context, or the context stopped), not
+     * when a route stops.
+     * <p/>
+     * A failed call leaves nothing behind, so the next call (of the next producer that is initialized) tries again.
+     */
+    WasiCommand command() throws Exception {
+        WasiCommand answer = command;
+        if (answer == null) {
+            lock.lock();
+            try {
+                answer = command;
+                if (answer == null) {
+                    List<String> arguments
+                            = WasmProducer.arguments(WasmProducer.programName(module), configuration.getArgs());

Review Comment:
   Done in 0a6a9c226b4d: `programName`, `arguments` and `checkNoNul` (with `DEFAULT_PROGRAM_NAME`) moved from `WasmProducer`
   to `WasmEndpoint`, static with package access. `WasmProducer` calls `WasmEndpoint.checkNoNul` for the environment
   variables and headers; the tests that called `WasmProducer.programName`/`arguments` call the endpoint now. No
   behaviour change. camel-wasm: 132 run, 0 failures.
   
   _Claude Code on behalf of allthingssecurity_



##########
docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc:
##########
@@ -111,6 +111,12 @@ module.
 * `WasmSupport.deserialize(byte[], Exchange)`.
 * The constructor `WasmProducer(Endpoint, String, String)` is replaced by `WasmProducer(WasmEndpoint)`.
 
+The endpoint has a new `compile` option (default `false`) that runs a module as JVM bytecode instead of interpreting
+it. For this option `camel-wasm` has a new dependency, `run.endive:compiler`, which brings in ASM (`org.ow2.asm`).
+The module is now loaded once per endpoint and no longer by every producer, so stopping and starting a route does
+not read the module again: remove the route and add it again, or restart the application, to load a module that
+has changed.

Review Comment:
   Applied your wording in 0a6a9c226b4d: the paragraph now starts with the new dependency, then the `compile` option, then
   the loading change.
   
   _Claude Code on behalf of allthingssecurity_



##########
components/camel-wasm/pom.xml:
##########
@@ -54,6 +54,12 @@
             <artifactId>wasi</artifactId>
             <version>${endive-version}</version>
         </dependency>
+        <!-- used with compile=true only: translates a module to JVM bytecode, once per endpoint -->
+        <dependency>
+            <groupId>run.endive</groupId>
+            <artifactId>compiler</artifactId>
+            <version>${endive-version}</version>
+        </dependency>

Review Comment:
   davsclaus decided this in his review: `run.endive:compiler` stays a normal dependency (optional dependencies need
   extra steps with `camel run`, the Spring Boot starter and Camel Quarkus, and the compiler is already in the SBOM through
   camel-opa). The pom is unchanged, and the open question is removed from the description.
   
   _Claude Code on behalf of allthingssecurity_



##########
components/camel-wasm/src/main/java/org/apache/camel/wasm/WasiCommand.java:
##########
@@ -73,10 +91,77 @@ public final class WasiCommand {
      *                                  than the initial memory the module declares
      */
     public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages) {
+        this(module, arguments, maxMemoryPages, false);
+    }
+
+    /**
+     * @param  module                   the parsed module
+     * @param  arguments                the program's arguments, the program name first
+     * @param  maxMemoryPages           the maximum number of 64 KiB pages the module's memory may grow to, or 0 to keep
+     *                                  the maximum the module declares
+     * @param  compile                  whether to translate the module to JVM bytecode now, with the Endive runtime
+     *                                  compiler, instead of interpreting it. This defines classes at run time, which a
+     *                                  GraalVM native image cannot do. A function that is too large for a JVM method is
+     *                                  left to the interpreter, which is logged once, at WARN
+     * @throws IllegalArgumentException if the module is not a WASI Preview 1 command module, or maxMemoryPages is lower
+     *                                  than the initial memory the module declares
+     * @throws IllegalStateException    if compile is set and the Endive runtime compiler is not on the classpath, or
+     *                                  cannot compile the module. The message names the module by its program name (the
+     *                                  first argument)
+     */
+    public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages, boolean compile) {
         this.module = Objects.requireNonNull(module);
         this.arguments = List.copyOf(arguments);
         validate(module);
         this.memoryLimits = memoryLimits(module, maxMemoryPages);
+
+        Function<Instance, Machine> factory = null;
+        boolean fallback = false;
+        if (compile) {
+            String name = this.arguments.isEmpty() ? "(no name)" : this.arguments.get(0);
+            try {
+                try {
+                    factory = RuntimeCompiler.compile(module, false);
+                } catch (WasmEngineException e) {
+                    // Endive could not compile every function. When the reason is a function that is too large for a
+                    // JVM method, the module still works with that function interpreted, so compile again with the
+                    // interpreter as fallback; for any other reason this second attempt fails as the first one did.
+                    factory = RuntimeCompiler.compile(module, true);
+                    fallback = true;
+                    LOG.warn("The Wasm module {} is compiled in part only: it has functions that are too large for a"

Review Comment:
   davsclaus answered question 3 in his review: the current handling (`FAIL`, then `SILENT` with one log line) is fine.
   So the line stays at WARN, logged once per endpoint, and the open question is removed from the description.
   
   _Claude Code on behalf of allthingssecurity_



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "allthingssecurity (via GitHub)" <gi...@apache.org>.
allthingssecurity commented on PR #27793:
URL: https://github.com/apache/camel/pull/27793#issuecomment-6163228682

   Thanks, clear. I will remove the `wasm` language in a follow-up PR (part 3), with its own JIRA and an upgrade note, and leave this PR as it is.
   
   _Claude Code on behalf of allthingssecurity_


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "allthingssecurity (via GitHub)" <gi...@apache.org>.
allthingssecurity commented on PR #27793:
URL: https://github.com/apache/camel/pull/27793#issuecomment-6162324698

   A question for part 3 of the camel-wasm work, so that it can follow this PR without waiting: the `wasm` expression language still calls a named exported function with the old alloc/dealloc + JSON-envelope protocol, while the endpoint now runs WASI command modules (since #27678). Which direction would you prefer?
   
   1. **Move the language to the WASI model**: the expression names only a module (plus optional arguments), the message body goes to stdin, stdout is the result, a non-zero exit code fails it; predicates would need a rule (exit code 0 = true, or the printed text `true`/`false`). This changes the language options in the core model and in the Java, XML and YAML DSLs, and modules written for the old protocol stop working (upgrade note).
   2. **Remove the `wasm` language** (deprecate first, or remove in 4.24 with an upgrade note), and point users to the endpoint, which does the same job as a normal route step.
   
   Option 2 is small; option 1 is a larger change across the DSLs. I am happy to do either once you have a preference.
   
   _Claude Code on behalf of allthingssecurity_
   


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "gnodet-bot (via GitHub)" <gi...@apache.org>.
gnodet-bot commented on code in PR #27793:
URL: https://github.com/apache/camel/pull/27793#discussion_r4265444237


##########
components/camel-wasm/src/main/java/org/apache/camel/wasm/WasiCommand.java:
##########
@@ -73,10 +91,77 @@ public final class WasiCommand {
      *                                  than the initial memory the module declares
      */
     public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages) {
+        this(module, arguments, maxMemoryPages, false);
+    }
+
+    /**
+     * @param  module                   the parsed module
+     * @param  arguments                the program's arguments, the program name first
+     * @param  maxMemoryPages           the maximum number of 64 KiB pages the module's memory may grow to, or 0 to keep
+     *                                  the maximum the module declares
+     * @param  compile                  whether to translate the module to JVM bytecode now, with the Endive runtime
+     *                                  compiler, instead of interpreting it. This defines classes at run time, which a
+     *                                  GraalVM native image cannot do. A function that is too large for a JVM method is
+     *                                  left to the interpreter, which is logged once, at WARN
+     * @throws IllegalArgumentException if the module is not a WASI Preview 1 command module, or maxMemoryPages is lower
+     *                                  than the initial memory the module declares
+     * @throws IllegalStateException    if compile is set and the Endive runtime compiler is not on the classpath, or
+     *                                  cannot compile the module. The message names the module by its program name (the
+     *                                  first argument)
+     */
+    public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages, boolean compile) {
         this.module = Objects.requireNonNull(module);
         this.arguments = List.copyOf(arguments);
         validate(module);
         this.memoryLimits = memoryLimits(module, maxMemoryPages);
+
+        Function<Instance, Machine> factory = null;
+        boolean fallback = false;
+        if (compile) {
+            String name = this.arguments.isEmpty() ? "(no name)" : this.arguments.get(0);
+            try {
+                try {
+                    factory = RuntimeCompiler.compile(module, false);
+                } catch (WasmEngineException e) {
+                    // Endive could not compile every function. When the reason is a function that is too large for a
+                    // JVM method, the module still works with that function interpreted, so compile again with the
+                    // interpreter as fallback; for any other reason this second attempt fails as the first one did.
+                    factory = RuntimeCompiler.compile(module, true);
+                    fallback = true;
+                    LOG.warn("The Wasm module {} is compiled in part only: it has functions that are too large for a"

Review Comment:
   💡 **Log level question.** `WARN` for partial compilation (interpreter fallback for oversized functions) may surprise operators monitoring for warnings, since the module still works correctly — just with lower performance for those specific functions. `INFO` would better match the semantics. That said, `WARN` is defensible for startup visibility — this is a configuration decision worth a deliberate call either way.



##########
components/camel-wasm/pom.xml:
##########
@@ -54,6 +54,12 @@
             <artifactId>wasi</artifactId>
             <version>${endive-version}</version>
         </dependency>
+        <!-- used with compile=true only: translates a module to JVM bytecode, once per endpoint -->
+        <dependency>
+            <groupId>run.endive</groupId>
+            <artifactId>compiler</artifactId>
+            <version>${endive-version}</version>
+        </dependency>

Review Comment:
   💡 **Optional dependency worth considering.** The code already handles the compiler's absence gracefully: `RuntimeCompiler` is isolated behind an inner-class boundary (classloading barrier), `NoClassDefFoundError` is caught with a clear error message, and there is a dedicated test for that scenario. Making the dependency `<optional>true</optional>` would avoid pulling `run.endive:compiler` and its ASM transitive deps for users who never set `compile=true` (the default). The trade-off is that users who do want compilation would need to add it explicitly.
   
   ```suggestion
           <!-- used with compile=true only: translates a module to JVM bytecode, once per endpoint -->
           <dependency>
               <groupId>run.endive</groupId>
               <artifactId>compiler</artifactId>
               <version>${endive-version}</version>
               <optional>true</optional>
           </dependency>
   ```



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "gnodet-bot (via GitHub)" <gi...@apache.org>.
gnodet-bot commented on code in PR #27793:
URL: https://github.com/apache/camel/pull/27793#discussion_r4267211153


##########
components/camel-wasm/src/main/java/org/apache/camel/wasm/WasiCommand.java:
##########
@@ -73,10 +91,77 @@ public final class WasiCommand {
      *                                  than the initial memory the module declares
      */
     public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages) {
+        this(module, arguments, maxMemoryPages, false);
+    }
+
+    /**
+     * @param  module                   the parsed module
+     * @param  arguments                the program's arguments, the program name first
+     * @param  maxMemoryPages           the maximum number of 64 KiB pages the module's memory may grow to, or 0 to keep
+     *                                  the maximum the module declares
+     * @param  compile                  whether to translate the module to JVM bytecode now, with the Endive runtime
+     *                                  compiler, instead of interpreting it. This defines classes at run time, which a
+     *                                  GraalVM native image cannot do. A function that is too large for a JVM method is
+     *                                  left to the interpreter, which is logged once, at WARN
+     * @throws IllegalArgumentException if the module is not a WASI Preview 1 command module, or maxMemoryPages is lower
+     *                                  than the initial memory the module declares
+     * @throws IllegalStateException    if compile is set and the Endive runtime compiler is not on the classpath, or
+     *                                  cannot compile the module. The message names the module by its program name (the
+     *                                  first argument)
+     */
+    public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages, boolean compile) {
         this.module = Objects.requireNonNull(module);
         this.arguments = List.copyOf(arguments);
         validate(module);
         this.memoryLimits = memoryLimits(module, maxMemoryPages);
+
+        Function<Instance, Machine> factory = null;
+        boolean fallback = false;
+        if (compile) {
+            String name = this.arguments.isEmpty() ? "(no name)" : this.arguments.get(0);
+            try {
+                try {
+                    factory = RuntimeCompiler.compile(module, false);
+                } catch (WasmEngineException e) {
+                    // Endive could not compile every function. When the reason is a function that is too large for a
+                    // JVM method, the module still works with that function interpreted, so compile again with the
+                    // interpreter as fallback; for any other reason this second attempt fails as the first one did.
+                    factory = RuntimeCompiler.compile(module, true);

Review Comment:
   ⚠️ **Catch-and-retry pays full compilation cost on non-size errors**
   
   When `compile(module, false)` throws `WasmEngineException` for a reason other than an oversized function (e.g. malformed bytecode, unsupported feature), `compile(module, true)` is unconditionally invoked in the catch block. This second call runs the full compilation pipeline again — paying the same cost — before failing with the same exception.
   
   The comment acknowledges this ("for any other reason this second attempt fails as the first one did"), so correctness is not affected. The impact is a wasted compilation pass on an already-rare error path, which is acceptable. If Endive exposes a typed exception subclass for the oversized-function case, catching it specifically (instead of the base `WasmEngineException`) would eliminate this cost entirely. Worth checking the Endive API.



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #27793:
URL: https://github.com/apache/camel/pull/27793#issuecomment-6160927558

   :star2: Thank you for your contribution to the Apache Camel project! :star2:
     :robot: CI automation will test this PR automatically.
   
     :camel: Apache Camel Committers, please review the following items:
   
     * First-time contributors **require MANUAL approval** for the GitHub Actions to run
     * You can use the command `/component-test (camel-)component-name1 (camel-)component-name2..` to request a test from the test bot although they are normally detected and executed by CI.
     * You can label PRs using `skip-tests` and `test-dependents` to fine-tune the checks executed by this PR.
     * Build and test logs are available in the summary page. **Only** [Apache Camel committers](https://camel.apache.org/community/team/#committers) have access to the summary.
     
     :warning: Be careful when sharing logs. Review their contents before sharing them publicly.


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "allthingssecurity (via GitHub)" <gi...@apache.org>.
allthingssecurity commented on code in PR #27793:
URL: https://github.com/apache/camel/pull/27793#discussion_r4267574150


##########
components/camel-wasm/src/main/java/org/apache/camel/wasm/WasiCommand.java:
##########
@@ -73,10 +91,77 @@ public final class WasiCommand {
      *                                  than the initial memory the module declares
      */
     public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages) {
+        this(module, arguments, maxMemoryPages, false);
+    }
+
+    /**
+     * @param  module                   the parsed module
+     * @param  arguments                the program's arguments, the program name first
+     * @param  maxMemoryPages           the maximum number of 64 KiB pages the module's memory may grow to, or 0 to keep
+     *                                  the maximum the module declares
+     * @param  compile                  whether to translate the module to JVM bytecode now, with the Endive runtime
+     *                                  compiler, instead of interpreting it. This defines classes at run time, which a
+     *                                  GraalVM native image cannot do. A function that is too large for a JVM method is
+     *                                  left to the interpreter, which is logged once, at WARN
+     * @throws IllegalArgumentException if the module is not a WASI Preview 1 command module, or maxMemoryPages is lower
+     *                                  than the initial memory the module declares
+     * @throws IllegalStateException    if compile is set and the Endive runtime compiler is not on the classpath, or
+     *                                  cannot compile the module. The message names the module by its program name (the
+     *                                  first argument)
+     */
+    public WasiCommand(WasmModule module, List<String> arguments, int maxMemoryPages, boolean compile) {
         this.module = Objects.requireNonNull(module);
         this.arguments = List.copyOf(arguments);
         validate(module);
         this.memoryLimits = memoryLimits(module, maxMemoryPages);
+
+        Function<Instance, Machine> factory = null;
+        boolean fallback = false;
+        if (compile) {
+            String name = this.arguments.isEmpty() ? "(no name)" : this.arguments.get(0);
+            try {
+                try {
+                    factory = RuntimeCompiler.compile(module, false);
+                } catch (WasmEngineException e) {
+                    // Endive could not compile every function. When the reason is a function that is too large for a
+                    // JVM method, the module still works with that function interpreted, so compile again with the
+                    // interpreter as fallback; for any other reason this second attempt fails as the first one did.
+                    factory = RuntimeCompiler.compile(module, true);

Review Comment:
   Done in 16a799c1dedf: the second compilation with the interpreter fallback now happens only when the cause chain of the `WasmEngineException` contains ASM's `MethodTooLargeException`, which is how Endive 1.1.0 reports an oversized function (`Compiler.handleMethodTooLarge`, and the FAIL branch of `compileExtraClasses`, both wrap it as the direct cause). Any other failure is rethrown at once with the existing "cannot be compiled" message. The check lives in the nested `RuntimeCompiler` and compares the class name, so camel-wasm still loads and interprets without the compiler jar. `WasiCommandTest.onlyAFunctionTooLargeForAJvmMethodIsCompiledAgainWithTheInterpreterAsFallback` covers the check, `moduleThatCannotBeCompiledFailsWithItsName` asserts that its unsupported-instruction failure does not qualify for a retry, and `functionTooLargeForAJvmMethodIsInterpreted` still passes (camel-wasm suite: 133 tests, 0 failures).
   
   _Claude Code on behalf of allthingssecurity_



-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on PR #27793:
URL: https://github.com/apache/camel/pull/27793#issuecomment-6163052639

   the removal can be in a follow up PR


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-25606: camel-wasm - Optional runtime compiler [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus merged PR #27793:
URL: https://github.com/apache/camel/pull/27793


-- 
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: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org