# Call Java from Node.js
You are a Node.js Moleculer developer. You want to add some Java functionality to your system — a Spring Boot service, a JVM library you can only reach from Java, a CPU-heavy job — and call it from your existing JavaScript code, without replacing your architecture.
You do not rewrite anything. You start a Java node, point it at the same message bus (see Setup), and call its actions exactly like any other Moleculer service. This page is the Node.js developer's view; the reverse direction is Call Node.js from Java.
# 1. See the Java node join the cluster
Once the Java node is up, it appears in the built-in $node introspection service like any other node.
From your Node.js code:
// $node.list returns every node in the cluster (local + remote).
const nodes = await broker.call("$node.list");
const java = nodes.find(n => n.id === "java-node");
console.log(java.available); // true
console.log(java.client.type); // "java" — the remote is a moleculer-java node
// $node.services aggregates the services advertised by every node.
const services = await broker.call("$node.services");
const names = services.map(s => s.name);
console.log(names.includes("mathJava")); // true — the Java service is visible
No registration step is needed on your side: discovery is automatic over the transporter.
# 2. Call a Java action
Say the Java side exposes a mathJava service. From Node.js you call mathJava.add and mathJava.greet
just like a local action — the framework handles discovery, routing, serialization and deserialization
across the language boundary.
The request body you pass as the second argument becomes ctx.params on the Java side (an
io.datatree.Tree), and whatever the Java action returns comes back to you as a plain JavaScript value.
# 3. Send an event to Java
Java services can subscribe to your events. Broadcast (or emit) an event from Node.js and a Java
listener receives the payload:
The difference between emit (load-balanced to one listener per group) and broadcast (delivered to
every listener) works across languages too — see the
Events section of the data-types reference.
# 4. Errors and timeouts
If a Java action throws, the failure crosses back as a rejected promise, so a normal try/catch handles
it. Add a per-call timeout through the call options:
You can also pin a call to a specific node with { nodeID: "java-node" } (in Java,
CallOptions.nodeID("java-node"), chainable with .timeout(5000)) when more than one node offers the
same service.
# Next
- Data types & features — pass lists, nested objects, cached values, metadata and binary streams to and from Java.
- Call Node.js from Java — the same story from the Java side.
Every snippet here is trimmed from a runnable, test-verified integration demo where a Node.js node and a Java node prove these calls and events in both directions.