Live demo: https://java-wasm-graphs-demo.vercel.app
Proof of concept for client-side graph processing using Java libraries (Guava, Commons CSV) compiled to WebAssembly via GraalVM.
Query geographical hierarchies (e.g., "Is Collo in Algeria?") entirely in the browser—no backend required.
Once the graph is built, the user can query it, asking questions like: Is Collo in Algeria?
The Java/Wasm runtime traverses the graph using Guava's graph APIs to determine relationships and returns the result to JavaScript.
Note: JS library graphology is decent. We did not really need to use Guava. Still, it has much needed data structures like RangeSet.
The following build both the frontend and .wasm/wasm.js files.
For just graph queries, JS libraries suffice. But for bringing Gephi, PDFBox, or complex solvers to the browser? That's where this shines.
Wasm allows us to use cool and battle-tested libraries (originally written for C++, Rust, or Java) in the browser/Node.
Imagine, constraint solvers like OptaPlanner/Timefold or Choco solver.
Imagine the possibilities.
Many libraries and frameworks support GraalVM Native Image.
The Java ecosystem has mature projects. Some cool examples:
Core libraries
Graph & visualization
- https://github.com/gephi/gephi
- https://github.com/francesco-ficarola/gexf4j
- https://github.com/coobird/thumbnailator
Or any of Apache or Eclipse projects:
We use a worker to decouple UI rendering from computation, allowing the Java/Wasm runtime to operate independently and keep the UI interactive.
Workflow (notice languages used):
-
Web: Edit data using a data grid.
-
JS/Web page: Generate a CSV text describing geographical or group hierarchies: what subregion is part of what region. For example:
-
JS: Submit the query and CSV data to the Worker.
-
JS/Wasm/Java: Listen to messages/queries.
-
Java: Parse the CSV.
-
Java: Build the graph.
-
Java: Traverse the graph to answer the query.
-
Java: Serialize the graph to GEXF.
-
Java/Wasm/JS: Reply with the graph and answer.
-
JS: Update the UI to draw the graph and answer.
-
Google Guava Graph
- Tested, works with the Graal Wasm target.
- To model the search space and traverse the graph to answer the query.
-
- Tested, works with the Graal Wasm target.
-
- Tested, works with the Graal Wasm target.
- Gexf4j, a new Java library to create GEXF files | Gephi blog
-
Sigma
- To visualize the result.
-
Handsontable
- To edit data and export it as CSV.
See Export to CSV - JavaScript Data Grid | Handsontable
- To edit data and export it as CSV.
Tested with:
-
Kubuntu 24.04 x64
-
Node 22 / npm 11
-
GraalVM 26 Early Access (sdk install java 26.ea.13-graal)
-
GraalVM 25 (sdk install java 25.0.1-graal)
-
Binaryen version 124
-
Chrome version 141
- Bundle size (non-debug): 10 MB raw / 4.3 MB gzip / 3.4 MB Brotli.
-
The wasm module is loaded asynchronously, which means it's a bit involved to know when the worker is ready. You can't just start calling postMessage as soon as you create it.
However, you can simply listen to a "READY" even that the worker emits once it's ready.
That's what I did here. -
DataCloneError when trying to post a JSObject to BroadcastChannel since it violates structure clone algorithm's rules: apparently, GraalVM wraps objects with proxies/functions.
Tried JSON.parse(JSON.stringify(theObject)) but the result was just {}.
Ended up using Gson to convert it to a string before posting to self (Web Worker) or BroadcastChannel.
Stuff I tried but failed to compile as Wasm even if they compile as native binaries just fine:
-
Quarkus and Timefold AI
-
PlantUML ELK (which uses Eclipse Layout Kernel)
- Considered creating a mindmap using PlantUML
- PlantUML EPL artifact provides the ELK implementation.
<dependency> <groupId>net.sourceforge.plantuml</groupId> <artifactId>plantuml-epl</artifactId> <version>1.2025.9</version> </dependency>"><!-- https://mvnrepository.com/artifact/net.sourceforge.plantuml/plantuml-epl --> <dependency> <groupId>net.sourceforge.plantuml</groupId> <artifactId>plantuml-epl</artifactId> <version>1.2025.9</version> </dependency>
-
Wasm target architecture for native image · Issue #3391 | oracle/graal
- It works, but improvements (e.g. better Java-JS interop and multithreading) are in development.
-
The class annotated with @JS.Export isn’t available from JavaScript. · Issue #11122 · oracle/graal
WTFPL - Abdeldjalil Hebal
.png)



