Your first S8 app

Launch a server, paint a remote screen, and persist a row. This is the whole loop.

What you will build

A boot method that creates a HomeScreen on the front and writes a welcome row into a table. No extra web framework. No ORM. No REST layer to keep honest.

1. Launch the server

The SPI façade is S8. Implementations are loaded with ServiceLoader — keep the implementation module on the module path.

LaunchServer.java
import com.s8.meta.api.S8;
import com.s8.meta.api.server.S8BootMethod;
import com.s8.meta.api.server.S8WebServer;

public class LaunchServer {
  public static void main(String[] args) throws Exception {
    S8WebServer server = S8.WEB_SERVER_FACTORY.createWebServer(
        "/path/to/app-config.xml",
        LaunchServer.class,
        params -> params.addBootMethod(
            S8BootMethod.MAIN_BOOT_PAGE, AppBoot.INSTANCE));
    server.start();
  }
}

2. Boot on the flow

Every request and every script receives a fresh S8SyncFlow. Do not store it. Do not cache it. Write ordinary Java; the flow already runs on a virtual thread.

AppBoot.java
public final class AppBoot implements S8BootMethod {
  static final AppBoot INSTANCE = new AppBoot();

  @Override
  public void boot(S8SyncFlow flow) throws Exception {
    HomeScreen screen = new HomeScreen(flow.front());
    screen.setTitle("Hello S8");
    screen.vertex.expose(0);

    UserRow row = new UserRow("welcome");
    row.email = "ada@stack8.tech";
    flow.tables().putRow(new PutRowS8Request("users", row, true, true));

    flow.refresh();
  }
}

3. Declare a front object

Subclass S8FrontObject. The type name you pass to super is the name the browser side will bind. Outbound fields push state to the screen; inbound methods receive events from it.

HomeScreen.java
@S8ObjectType(name = "app.HomeScreen")
public class HomeScreen extends S8FrontObject {
  public HomeScreen(S8FrontSession front) {
    super(front, "app.HomeScreen");
    vertex.inbound().setVoidMethodLambda("onReady", () -> {
      // operate, then S8 refreshes the front for you
    });
  }

  public void setTitle(String title) {
    vertex.outbound().setStringUTF8Field("title", title);
  }
}
Intent Treat the browser as a remote display attached to your process. If you would call a setter on a Swing or JavaFX widget, call it on the vertex outbound instead.

Next