Asity is here chirping *universally reusable web fragments on the JVM*


Asity is here chirping *universally reusable web fragments on the JVM*

Have you met Asity ? It is probably the most Java-intelligent exotic bird you’ll ever meet!

By establishing an ecosystem of universally reusable web fragments that run across different frameworks in the Java ecosystem, Asity gives all the tools (and reasons) you need to achieve and exploit the “Write Once, Run Anywhere” principle that has been central to the Java ecosystem for ages!

According to the official web page , Asity provides abstractions for HTTP and WebSocket, and implementations per framework, called bridges, which are transparent to end-users and don’t affect the framework’s performance, productivity and philosophy.

SEE ALSO: Meet Jib: Containerizing a Java application has never been easier

Feeling intrigued? Wait until you hear the news!

Just hours ago, Asity 2.0.0 was officially released and I cannot wait to give you a quick tour of how working with reusable web fragments on the JVM looks like!

More “Write Once, Use Anywhere” things coming your way

In order to demonstrate how to build an echo fragment which simply responds to the client with whatever data the client sent, here is a comprehensive example of Asity 2.

Add the following dependencies:




And the following class:

package io.cettia.asity.example.spring.webflux5;

import io.cettia.asity.action.Action;
import io.cettia.asity.bridge.spring.webflux5.AsityHandlerFunction;
import io.cettia.asity.bridge.spring.webflux5.AsityWebSocketHandler;
import io.cettia.asity.http.HttpStatus;
import io.cettia.asity.http.ServerHttpExchange;
import io.cettia.asity.websocket.ServerWebSocket;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.WebSocketHandler;

import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import java.util.Map;

import static org.springframework.web.reactive.function.server.RequestPredicates.headers;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;

public class EchoServer {
  public Action httpAction() {
    return new HttpEchoServer();

  public Action wsAction() {
    return new WebSocketEchoServer();

  public RouterFunction httpMapping() {
    AsityHandlerFunction asityHandlerFunction = new AsityHandlerFunction().onhttp(httpAction());

    return RouterFunctions.route(
        // Excludes WebSocket handshake requests
        .and(headers(headers -> !"websocket".equalsIgnoreCase(headers.asHttpHeaders().getUpgrade()))), asityHandlerFunction);

  public HandlerMapping wsMapping() {
    AsityWebSocketHandler asityWebSocketHandler = new AsityWebSocketHandler().onwebsocket(wsAction());
    Map map = new LinkedHashMap();
    map.put("/echo", asityWebSocketHandler);

    SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();

    return mapping;

  public WebSocketHandlerAdapter webSocketHandlerAdapter() {
    return new WebSocketHandlerAdapter();

  public static void main(String[] args) {, args);

  public static class HttpEchoServer implements Action {
    public void on(ServerHttpExchange http) {
      // Reads request URI, method and headers
      System.out.println(http.method() + " " + http.uri());
      http.headerNames().stream().forEach(name -> System.out.println(name + ": " + String.join(", ", http.headers(name))));

      // Writes response status code and headers
      http.setStatus(HttpStatus.OK).setHeader("content-type", http.header("content-type"));

      // Reads a chunk from request body and writes it to response body
      http.readAsText().onchunk((String chunk) -> http.write(chunk));
      // If request body is binary,
      // http.readAsBinary().onchunk((ByteBuffer binary) -> http.write(binary));

      // Ends response if request ends
      http.onend((Void v) -> http.end());

      // Exception handling
      http.onerror((Throwable t) -> t.printStackTrace()).onclose((Void v) -> System.out.println("disconnected"));

  public static class WebSocketEchoServer implements Action {
    public void on(ServerWebSocket ws) {
      // Reads handshake request URI and headers
      ws.headerNames().stream().forEach(name -> System.out.println(name + ": " + String.join(", ", ws.headers(name))));

      // Sends the received text frame and binary frame back
      ws.ontext((String text) -> ws.send(text)).onbinary((ByteBuffer binary) -> ws.send(binary));

      // Exception handling
      ws.onerror((Throwable t) -> t.printStackTrace());

As you would expect, HttpEchoServer and WebSocketEchoServer are web fragments and can be reused in other frameworks through other bridges like asity-bridge-spring-webmvc4 . You can also see that a bridge implementation is completely transparent to end-users who still have full control over web fragments on frameworks they selected.

Asity 2.0.0 now supports Java API for WebSocket 1, Servlet 3, Spring WebFlux 5, Spring MVC 4, Vert.x 3, Netty 4, Grizzly 2, Vert.x 2 and Atmosphere 2. You can find a list of working examples per supported frameworks here and the full documentation here .



Asity is here chirping *universally reusable web fragments on the JVM*

微软edge浏览器iOS端beta版更新 加入视觉搜索功能





Asity is here chirping *universally reusable web fragments on the JVM*