diff --git a/.github/workflows/native-image-wasm-spring-shell.yml b/.github/workflows/native-image-wasm-spring-shell.yml
index 13bbdc8e8..d9b2ce9d2 100644
--- a/.github/workflows/native-image-wasm-spring-shell.yml
+++ b/.github/workflows/native-image-wasm-spring-shell.yml
@@ -38,6 +38,7 @@ jobs:
- name: Run 'native-image/wasm-spring-shell'
run: |
cd native-image/wasm-spring-shell
- ./mvnw --no-transfer-progress -Pnative native:compile
+ ./mvnw --no-transfer-progress -Pnative,cli package
node target/wasm-spring-shell help
node target/wasm-spring-shell hello Jane
+ ./mvnw --no-transfer-progress -Pnative,web package
diff --git a/native-image/wasm-spring-shell/README.md b/native-image/wasm-spring-shell/README.md
index 6baff91a5..66bf69166 100644
--- a/native-image/wasm-spring-shell/README.md
+++ b/native-image/wasm-spring-shell/README.md
@@ -12,9 +12,9 @@ This demo requires:
## Run Spring Shell on Node
-1. Build the Wasm module with the `native` profile:
+1. Build the Wasm module with the `native` and `cli` profiles:
```bash
- $ ./mvnw -Pnative package
+ $ ./mvnw -Pnative,cli package
```
The demo uses the [Native Build Tools](https://graalvm.github.io/native-build-tools/latest/index.html) for building native images with GraalVM and Maven.
This command generates a Wasm file and a corresponding JavaScript binding in the `target` directory.
@@ -25,3 +25,20 @@ This demo requires:
node target/wasm-spring-shell hello Jane
```
This requires Node.js 22 or later.
+
+## Run Spring Shell in the Browser
+
+1. Build the Wasm module with the `native` and `web` profiles:
+ ```bash
+ ./mvnw -Pnative,web package
+ ```
+ This command generates a Wasm file and a corresponding JavaScript binding in the `web` directory.
+
+2. Run a local web server in the `web` directory:
+ ```bash
+ cd web
+ python server.py
+ ```
+ This will serve the `web` directory locally on port `8000`.
+
+3. Navigate to http://localhost:8000 to run the Spring Shell in the browser.
diff --git a/native-image/wasm-spring-shell/pom.xml b/native-image/wasm-spring-shell/pom.xml
index 209bb1e19..af541495d 100644
--- a/native-image/wasm-spring-shell/pom.xml
+++ b/native-image/wasm-spring-shell/pom.xml
@@ -31,11 +31,15 @@
3.4.1
+
+ org.graalvm.sdk
+ webimage-preview
+ 25.0.1
+
org.springframework.shell
spring-shell-starter
-
org.springframework.boot
spring-boot-starter-test
@@ -59,28 +63,88 @@
-
-
-
- org.graalvm.buildtools
- native-maven-plugin
-
-
-
- --tool:svm-wasm
-
- -g
-
- --initialize-at-build-time=apple.security.AppleProvider
- --initialize-at-build-time=apple.security.AppleProvider$ProviderService
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+
+
+ cli
+
+
+
+ org.graalvm.buildtools
+ native-maven-plugin
+
+
+ build-native
+
+ compile-no-fork
+
+ package
+
+
+
+
+
+ --tool:svm-wasm
+
+ -g
+
+ --initialize-at-build-time=apple.security.AppleProvider
+ --initialize-at-build-time=apple.security.AppleProvider$ProviderService
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ com.example.wasm_spring_shell.cli.WasmSpringShellApplication
+
+
+
+
+
+
+ web
+
+ web
+
+
+
+
+ org.graalvm.buildtools
+ native-maven-plugin
+
+
+ build-native
+
+ compile-no-fork
+
+ package
+
+
+
+ ../web/wasm-spring-shell
+
+
+ --tool:svm-wasm
+
+ -g
+
+ --initialize-at-build-time=apple.security.AppleProvider
+ --initialize-at-build-time=apple.security.AppleProvider$ProviderService
+ -H:-AutoRunVM
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ com.example.wasm_spring_shell.web.Worker
+
+
+
+
+
+
diff --git a/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/WasmSpringShellApplication.java b/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/cli/WasmSpringShellApplication.java
similarity index 66%
rename from native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/WasmSpringShellApplication.java
rename to native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/cli/WasmSpringShellApplication.java
index 5c227320a..2760e5ad2 100644
--- a/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/WasmSpringShellApplication.java
+++ b/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/cli/WasmSpringShellApplication.java
@@ -4,23 +4,18 @@
* Licensed under the Universal Permissive License v 1.0 as shown at https://opensource.org/license/UPL.
*/
-package com.example.wasm_spring_shell;
+package com.example.wasm_spring_shell.cli;
+import com.example.wasm_spring_shell.common.MyCommands;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.ansi.AnsiOutput.Enabled;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-@SpringBootApplication
+@SpringBootApplication(scanBasePackageClasses = {WasmSpringShellApplication.class, MyCommands.class})
public class WasmSpringShellApplication {
-
public static void main(String[] args) {
- SpringApplication.run(WasmSpringShellApplication.class, args);
- }
-
- static {
- /* Always enable colorful terminal output. */
AnsiOutput.setEnabled(Enabled.ALWAYS);
- }
-
+ SpringApplication.run(WasmSpringShellApplication.class, args);
+ }
}
diff --git a/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/MyCommands.java b/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/common/MyCommands.java
similarity index 92%
rename from native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/MyCommands.java
rename to native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/common/MyCommands.java
index a46ef6a07..8910cf539 100644
--- a/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/MyCommands.java
+++ b/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/common/MyCommands.java
@@ -4,7 +4,7 @@
* Licensed under the Universal Permissive License v 1.0 as shown at https://opensource.org/license/UPL.
*/
-package com.example.wasm_spring_shell;
+package com.example.wasm_spring_shell.common;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
@@ -17,5 +17,5 @@ public class MyCommands {
public String hello(@ShellOption(defaultValue = "Spring") String arg) {
return "Hello " + arg + " from WebAssembly built with GraalVM!";
}
-
+
}
diff --git a/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/web/CustomResultHandler.java b/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/web/CustomResultHandler.java
new file mode 100644
index 000000000..4d2b4ccfb
--- /dev/null
+++ b/native-image/wasm-spring-shell/src/main/java/com/example/wasm_spring_shell/web/CustomResultHandler.java
@@ -0,0 +1,29 @@
+package com.example.wasm_spring_shell.web;
+
+import org.jline.utils.AttributedCharSequence;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
+import org.springframework.shell.ResultHandler;
+import org.springframework.stereotype.Component;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+@Component
+public class CustomResultHandler implements ResultHandler