Getting Started

The easiest way to get started with Cettia is to play with the Cettia Starter Kit that is a basic chat application made with Cettia.

cettia-starter-kit-1555758896147

Running the Starter Kit

The starter kit requires Java 8+. Clone or download the repository and run ./mvnw install. If you have installed Maven 3+, you can do mvn install.

git clone https://github.com/cettia/cettia-starter-kit.git
cd cettia-starter-kit
./mvnw install

Server

The server example is located in the example-server project.

To run the example, you should integrate it with a web framework first. The starter kit provides example projects integrated with each web framework supporting Cettia as follows. Pick one according to your favorite framework, enter the project directory, and run the Maven command.

Web framework Maven project Maven command pom.xml Main class
Atmosphere atmosphere2 ../mvnw jetty:run pom.xml CettiaInitializer
Grizzly grizzly2 ../mvnw clean package exec:java pom.xml CettiaServer
Java EE javaee7 ../mvnw jetty:run pom.xml CettiaInitializer
Netty netty4 ../mvnw clean package exec:java pom.xml CettiaServer
Play framework play2 sbt run or ../mvnw play2:run build.sbt CettiaController
Spring WebFlux spring-webflux5 ../mvnw spring-boot:run pom.xml CettiaServer
Spring Web MVC spring-webmvc4 ../mvnw spring-boot:run pom.xml CettiaServer
Vert.x vertx2 ../mvnw clean package vertx:runMod pom.xml CettiaServerVerticle
  vertx3 ../mvnw clean package exec:java pom.xml CettiaServerVerticle

Then, it will run a server that listens on port 8080 and exposes an endpoint /cettia. For how to integrate Cettia with the framework of your choice, see the above projects’ source code and the reference documentation’s Plugging Into the Web Framework section.

Web

The browser-based client example is located in the example-web project.

Enter the example-web Maven project, start a static web server as follows, and then visit http://localhost:8070/.

cd example-web
../mvnw jetty:run -Djetty.port=8070
On the fly

If you prefer to run code snippets on the fly, open the developer tools on this page, click the console tab and then type cettia to the console.

> cettia;
< {open: function, transport: Object, util: Object}

Then, you should see that the cettia object is available. For your information, every page of https://cettia.io loads the latest version of cettia object so that you can play with the cettia object at any time.

React Native

Note It uses Cettia JavaScript Client 1.1.0-SNAPSHOT.

The React Native example is located in the example-react-native project.

Make sure that you have set up the React Native development environment. Enter the example-react-native npm project, and type the following command.

cd example-react-native
npm install

Then, you can run the example with React Native CLI as follows.

iOS
react-native run-ios
Android
react-native run-android

Node.js

The Node.js example is located in the example-node project.

You need to have installed Node.js version 4 and above. Enter the example-web npm project, install the dependencies, and start main.js.

cd example-node
npm install
npm start
On the fly

If you prefer to run code snippets on the fly, open a Node.js console and copy the contents of the main.js and paste it into the console. You can deal with the socket directly.

Understanding the Example

Here are the user stories implemented in the example.

  • As a guest I want to sign in to the application by entering a username only so that I don’t have to go through an annoying sign-up process.
  • As a user I want to join the lounge channel automatically after sign in so that I can talk with everyone.
  • As a user I want to send messages to the lounge channel so that everyone can receive my messages.
  • As a user I want to receive messages when others send them to the lounge channel so that I can keep conversation in real-time.

In this guide we will skip explanation about view components and focus on how we can exchange events between the server and the client in real-time.

Opening a Socket

Add a socket event handler in the server side.

server.onsocket((ServerSocket socket) -> {
  System.out.println(socket + " is created");
});

Then, in the client, open a socket side adding a username parameter to the query string of the URI.

const uri = `http://localhost:8080/cettia?username=${encodeURIComponent(username)}`;
const socket = cettia.open(uri);

For convenience sake, in the rest of the guide, we will assume that a socket is already opened. For the details, see the reference documentation’s Opening a Socket.

Tracking the Socket Lifecycle

Register the following built-in event handlers to track each side of socket.

The server-side:

server.onsocket((ServerSocket socket) -> {
  Action<Void> logState = v -> System.out.println(socket + " transitions to " + socket.state());
  // If it performs the handshake successfully, or the connection is recovered by the client reconnection
  socket.onopen(logState);
  // If it fails to perform the handshake, or the connection is disconnected for some reason
  socket.onclose(logState);
  // After one minute has elapsed since disconnection
  socket.ondelete(logState);
});

The client-side:

const addSystemMessage = text => addMessage({sender: "system", text});
socket.on("connecting", () => addSystemMessage("The socket starts a connection."));
socket.on("open", () => addSystemMessage("The socket establishes a connection."));
socket.on("close", () => addSystemMessage("All transports failed to connect or the connection was disconnected."));
socket.on("waiting", (delay) => addSystemMessage(`The socket will reconnect after ${delay} ms`));

addMessage is a function to add a message to the message list by manipulating the DOM. If you are in the console, declare the following function and register it as a message event handler, as follows.

const addMessage = ({sender, text}) => console.log(`${sender} sends ${text}`);
socket.on("message", addMessage);

For the details including state transition diagrams, see the reference documentation’s Socket Lifecycle.

Storing Information in a Socket

A server-side socket can have custom properties in the form of a key-value pair and a set element.

server.onsocket((ServerSocket socket) -> {
  // Sets a username
  socket.set("username", findParam(socket.uri(), "username"));
  // Joins the lounge channel where everyone gets together
  socket.tag("channel:lounge");
});

See the reference documentation’s Attributes and Tags for the details.

Working with Sockets

To send an event to certain sockets in the server, write a socket predicate that selects which sockets to handle, and pass it to find(), and write a socket action that sends an event to the given socket, and pass it to execute(). The server will find sockets that matches the given predicate and execute the given action passing found sockets one by one.

server.onsocket((ServerSocket socket) -> {
  socket.on("message", (Map<String, Object> input) -> {
    String text = (String) input.get("text");

    Map<String, Object> output = new LinkedHashMap<>();
    output.put("sender", socket.get("username"));
    output.put("text", text);

    System.out.println(socket.get("username") + "@" + socket.id() + " sends '" + text + "' to the lounge");
    server.find(s -> s.tags().contains("channel:lounge")).execute(s -> s.send("message", output));
  });
});

Unless you need to deal with a socket passed to a socket predicate and a socket action directly, you can rewrite the above code more concisely with predefined predicates and convenient methods as follows.

server.onsocket((ServerSocket socket) -> {
  socket.on("message", (Map<String, Object> input) -> {
    // ...
    // With 'import static io.cettia.ServerSocketPredicates.tag;'
    server.find(tag("channel:lounge")).send("message", output);
  });
});

In the client side, register a message event handler

socket.on("message", message => addMessage(message));

And send a message event with with a message, text. You will see all sockets joined the lounge channel receive the message.

socket.send("message", {text});

For the details, See the reference documentation’s Working with Sockets and Advanced Sockets Handling sections.

Conclusion

In this guide, we walked through basic features of Cettia with the Cettia Starter Kit; opening a socket, tracking the socket lifecycle, storing information in a socket, and working with sockets. To learn more about Cettia, including

  • How to run an application on your favorite web framework
  • What types are allowed for event data
  • How to handle binary data
  • How to use POJOs as event data
  • How to scale an application
  • How to recover missed events, and so on

Take a look at the reference documentation – Building Real-Time Web Applications With Cettia. If you have any questions, please let us know on the Cettia Groups.