Developer Setup & Getting Started Guide¶
⚠️ Outdated — this page predates 0.3.0 and several of its commands and APIs are wrong. Use Quickstart instead, where every command has been executed against the current
main.Known errors on this page: the archetype version below is
1.0.0-SNAPSHOTbut the project is at0.3.0;java -jar …-server.jarcannot work because no shade or assembly plugin is configured; the UI imports arecom.zeroz4j.ui.components.*but the real packages arecom.zeroz4j.ui.componentandcom.zeroz4j.ui.layout; andButtonhas noonClickmethod — it isaddClickListener.
The easiest way to scaffold a new zeroz4j project is to use the provided Maven Archetype. This will automatically generate a complete, multi-module project (client, shared, server) with all TeaVM, annotation processors, and Helidon dependencies correctly configured.
1. Generate the Project¶
Run the following Maven command to scaffold your project:
mvn archetype:generate \
-DarchetypeGroupId=com.zeroz4j \
-DarchetypeArtifactId=zerozstack-archetype \
-DarchetypeVersion=1.0.0-SNAPSHOT \
-DgroupId=com.mycompany \
-DartifactId=myapp \
-Dversion=1.0.0-SNAPSHOT
2. Project Structure¶
The generated project will contain:
* myapp-shared: Contains your API interfaces and Domain Models.
* myapp-client: Contains the Java UI code that compiles to WebAssembly.
* myapp-server: Contains the Helidon-based backend that persists your data.
3. Build and Run¶
To build the entire project (including compiling the WASM client):
To run the server:
Navigate to http://localhost:8080 to see your running ZeroZ Stack application!
4. Code Example¶
With ZeroZ Stack, you avoid boilerplate HTTP mapping, JSON translation, and ORM schemas. Here is how simple it is to build a full-stack feature.
1. The Domain Model (Shared)¶
Define your data structure. It automatically becomes serializable and persistable.
import com.zeroz4j.api.DataModel;
@DataModel
public class ChatMessage {
private String author;
private String text;
public ChatMessage() {}
public ChatMessage(String author, String text) {
this.author = author;
this.text = text;
}
// getters and setters...
}
2. The API (Shared)¶
Define the RPC interface.
import com.zeroz4j.api.RmiService;
@RmiService
public interface ChatService {
void sendMessage(ChatMessage msg);
}
3. The Server Backend¶
Implement the service. The method receives the exact object sent from the client.
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import com.zeroz4j.db.net.ZeroZDbNode;
@ApplicationScoped
public class ChatServiceImpl implements ChatService {
@Inject
private ZeroZDbNode db;
@Override
public void sendMessage(ChatMessage msg) {
// Automatically persist or broadcast!
System.out.println("Received: " + msg.getText());
// Example: save to your data root graph, atomically
// db.localDb().write(ctx -> { ctx.edit(root.getMessages()); root.getMessages().add(msg); });
// root.getMessages().add(msg);
// storage.store(root.getMessages());
}
}
4. The Client UI (Wasm)¶
Invoke the backend directly from a UI button click event. The UI never touches JSON or REST.
import com.zeroz4j.ui.components.Button;
import com.zeroz4j.ui.components.Div;
public class ChatView extends Div {
public ChatView(ChatService chatService) {
Button sendBtn = new Button("Send Hello");
sendBtn.onClick(event -> {
// Suspends cooperatively, calls backend over binary WebSocket
chatService.sendMessage(new ChatMessage("Alice", "Hello World!"));
});
add(sendBtn);
}
}