Cettia Java Server 1.2.0 released

wrote this on

It is my pleasure to announce that Cettia Java Server 1.2.0 is available now. As announced in August, we dropped support for Java 7 in this release and added useful features based on Java 8 features such as functional interfaces and lambda expressions. To migrate from 1.1 to 1.2, update the version of the dependency. There is no backward incompatible changes other than the minimum Java version.


When we added Spring MVC and Spring WebFlux supports to Asity 2, we were inspired by the Spring WebFlux’s functional programming model. In this release, we added a ServerSocketPredicates class, a helper for ServerSocketPredicate which consists of static methods that return various useful ServerSocketPredicates, and the default methods, and(ServerSocketPredicate that), or(ServerSocketPredicate that), and negate(), to ServerSocketPredicate. ServerSocketPredicate and ServerSocketPredicates are analogous to RequestPredicate and RequestPredicates of Spring WebFlux.

The following are static methods to create socket predicates defined in the ServerSocketPredicates.

A predicate that always matches.
attr(String key, Object value)
A predicate that tests the socket attributes against the given key-value pair.
id(ServerSocket socket)
A predicate that tests the socket id against the given socket's id.
id(String id)
A predicate that tests the socket id against the given socket id.
tag(String... tags)
A predicate that tests the socket tags against the given tags.

For example, you can find sockets whose username is the same with the given username excluding the given socket as follows. Assume the attr and id are statically imported from the ServerSocketPredicates class.

// import static io.cettia.ServerSocketPredicates.attr;
// import static io.cettia.ServerSocketPredicates.id;
ServerSocketPredicate p = attr("username", username).and(id(socket).negate());

The above predicate can be utilized to limit only one socket per user declaratively like only one session per user. Assume that the username is given through a security framework like Apache Shiro and Spring Security and the signout event handler in the client side closes a connection and stops reconnecting.

server.onsocket(socket -> {
  // Limits only one socket per user
  server.find(attr("username", username).and(id(socket).negate())).send("signout").close();

In favor of the ServerSocketPredicates class, the existing finder methods such as Server#all() and Server#byTag(String tags...) are deprecated. Replace them with all() and tag(String... tags) defined in the ServerSocketPredicates with Server#find(ServerSocketPredicate predicate). The finders will be removed in the next major version.

Also, Sentence#find(ServerSocketPredicate predicate) is added which creates and returns a sentence with a given predicate like Server#find(ServerSocketPredicate predicate) but has a composed predicate that represents a short-circuiting logical AND of the original sentence’s predicate and the given predicate. We expect that it will greatly improve the reusability of a sentence. For example, if sockets are tagged with the application type e.g. web, android, desktop when initailized, we can find sockets by the user and then by the application type again.

// import static io.cettia.ServerSocketPredicates.attr;
// import static io.cettia.ServerSocketPredicates.tag;

// Sockets opened by the user
Sentence user = server.find(attr("username", "flowersinthesand"));

// Sockets opened through the user's android application
Sentence android = user.find(tag("android"));

// Sockets opened through the user's web application
Sentence web = user.find(tag("web"));

Cettia starter kit based on Servlet 3 and Java API for WebSocket 1 and ralscha/cettia-demo based on Spring framework 5 are updated with Cettia Java Server 1.2.0. Check out the working examples to see it in action. If you have any feedback, let us know via Cettia Groups.

All posts