To run a web fragment on your framework, you need to plug the web fragment in to the framework through a dedicated bridge for the framework. A bridge is a minimal implementation; just enough to convert a framework's HTTP request-response exchange and WebSocket connection to the Asity's ServerHttpExchange and ServerWebSocket , and feed web fragments with them. Note that even if your favorite framework is not supported now, with about 200 lines of code, you can write a bridge to your framework.

Let's map the echo fragment above to the path /echo .

Java API for WebSocket 1 Add a io.cettia.asity:asity-bridge-jwa1:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-jwa1 </artifactId> <version> 3.0.0 </version> </dependency> Then register a AsityServerEndpoint as a WebSocket server endpoint in a server container. When registering the server endpoint, you should put a handshake request instance into a map returned by ServerEndpointConfig#getUserProperties with the javax.websocket.server.HandshakeRequest key by overriding a Configurator#modifyHandshake method. package io . cettia . asity . example . jwa1 ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.jwa1.AsityServerEndpoint ; import io.cettia.asity.example.echo.WebSocketEchoServer ; import io.cettia.asity.websocket.ServerWebSocket ; import javax.servlet.ServletContext ; import javax.servlet.ServletContextEvent ; import javax.servlet.ServletContextListener ; import javax.servlet.annotation.WebListener ; import javax.websocket.DeploymentException ; import javax.websocket.HandshakeResponse ; import javax.websocket.server.HandshakeRequest ; import javax.websocket.server.ServerContainer ; import javax.websocket.server.ServerEndpointConfig ; @WebListener public class EchoServerInitializer implements ServletContextListener { @Override public void contextInitialized ( ServletContextEvent event ) { // Web fragments Action < ServerWebSocket > wsAction = new WebSocketEchoServer (); ServletContext context = event . getServletContext (); ServerContainer container = ( ServerContainer ) context . getAttribute ( ServerContainer . class . getName ()); ServerEndpointConfig . Configurator configurator = new ServerEndpointConfig . Configurator () { @Override public < T > T getEndpointInstance ( Class < T > endpointClass ) { AsityServerEndpoint asityServerEndpoint = new AsityServerEndpoint (). onwebsocket ( wsAction ); return endpointClass . cast ( asityServerEndpoint ); } @Override public void modifyHandshake ( ServerEndpointConfig config , HandshakeRequest request , HandshakeResponse response ) { config . getUserProperties (). put ( HandshakeRequest . class . getName (), request ); } }; try { container . addEndpoint ( ServerEndpointConfig . Builder . create ( AsityServerEndpoint . class , "/echo" ). configurator ( configurator ). build ()); } catch ( DeploymentException e ) { throw new RuntimeException ( e ); } } @Override public void contextDestroyed ( ServletContextEvent sce ) {} } Now you can handle WebSocket connections from /echo asynchronously through a AsityServerEndpoint 's onwebsocket method. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-jwa1.

Servlet 3 Add io.cettia.asity:asity-bridge-servlet3:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-servlet3 </artifactId> <version> 3.0.0 </version> </dependency> Then register a AsityServlet as a servlet in a servlet context. When registering the servlet, you should set asyncSupported to true . package io . cettia . asity . example . servlet3 ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.servlet3.AsityServlet ; import io.cettia.asity.example.echo.HttpEchoServer ; import io.cettia.asity.http.ServerHttpExchange ; import javax.servlet.Servlet ; import javax.servlet.ServletContext ; import javax.servlet.ServletContextEvent ; import javax.servlet.ServletContextListener ; import javax.servlet.ServletRegistration ; import javax.servlet.annotation.WebListener ; @WebListener public class EchoServerInitializer implements ServletContextListener { @Override public void contextInitialized ( ServletContextEvent event ) { // Web fragments Action < ServerHttpExchange > httpAction = new HttpEchoServer (); ServletContext context = event . getServletContext (); Servlet servlet = new AsityServlet (). onhttp ( httpAction ); ServletRegistration . Dynamic reg = context . addServlet ( AsityServlet . class . getName (), servlet ); reg . setAsyncSupported ( true ); reg . addMapping ( "/echo" ); } @Override public void contextDestroyed ( ServletContextEvent sce ) {} } Now you can handle HTTP requests from /echo asynchronously through a AsityServlet 's onhttp method. Quirks It works with Servlet 3.1 and 4 containers.

ServerHttpExchange 's onclose isn't supported. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-servlet3.

Spring WebFlux 5 Add a io.cettia.asity:asity-bridge-spring-webflux5:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-spring-webflux5 </artifactId> <version> 3.0.0 </version> </dependency> Then register a AsityHandlerFunction as a handler function and a AsityWebSocketHandler as a WebSocket handler. 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.example.echo.HttpEchoServer ; import io.cettia.asity.example.echo.WebSocketEchoServer ; 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 org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter ; 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 ; @SpringBootApplication @EnableWebFlux public class EchoServer { @Bean public Action < ServerHttpExchange > httpAction () { return new HttpEchoServer (); } @Bean public Action < ServerWebSocket > wsAction () { return new WebSocketEchoServer (); } @Bean public RouterFunction < ServerResponse > httpMapping () { AsityHandlerFunction asityHandlerFunction = new AsityHandlerFunction (). onhttp ( httpAction ()); return RouterFunctions . route ( path ( "/echo" ) // Excludes WebSocket handshake requests . and ( headers ( headers -> ! "websocket" . equalsIgnoreCase ( headers . asHttpHeaders (). getUpgrade ()))), asityHandlerFunction ); } @Bean public HandlerMapping wsMapping () { AsityWebSocketHandler asityWebSocketHandler = new AsityWebSocketHandler (). onwebsocket ( wsAction ()); Map < String , WebSocketHandler > map = new LinkedHashMap <>(); map . put ( "/echo" , asityWebSocketHandler ); SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping (); mapping . setUrlMap ( map ); return mapping ; } @Bean public WebSocketHandlerAdapter webSocketHandlerAdapter () { return new WebSocketHandlerAdapter (); } public static void main ( String [] args ) { SpringApplication . run ( EchoServer . class , args ); } } Now you can handle HTTP requests and WebSocket connections from /echo asynchronously through a AsityHandlerFunction 's onhttp method and a AsityWebSocketHandler 's onwebsocket method. Quirks ServerHttpExchange 's onclose isn't supported. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-spring-webflux5.

Spring MVC 4 Add a io.cettia.asity:asity-bridge-spring-webmvc4:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-spring-webmvc4 </artifactId> <version> 3.0.0 </version> </dependency> Then register a AsityController as a controller bean and a AsityWebSocketHandler as a WebSocket handler bean. package io . cettia . asity . example . spring . webmvc4 ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.spring.webmvc4.AsityController ; import io.cettia.asity.bridge.spring.webmvc4.AsityWebSocketHandler ; import io.cettia.asity.example.echo.HttpEchoServer ; import io.cettia.asity.example.echo.WebSocketEchoServer ; 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.core.Ordered ; import org.springframework.web.servlet.HandlerMapping ; import org.springframework.web.servlet.config.annotation.EnableWebMvc ; import org.springframework.web.servlet.handler.AbstractHandlerMapping ; import org.springframework.web.socket.config.annotation.EnableWebSocket ; import org.springframework.web.socket.config.annotation.WebSocketConfigurer ; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry ; import javax.servlet.http.HttpServletRequest ; @SpringBootApplication @EnableWebMvc @EnableWebSocket public class EchoServer implements WebSocketConfigurer { @Bean public Action < ServerHttpExchange > httpAction () { return new HttpEchoServer (); } @Bean public Action < ServerWebSocket > wsAction () { return new WebSocketEchoServer (); } @Bean public HandlerMapping httpMapping () { AsityController asityController = new AsityController (). onhttp ( httpAction ()); AbstractHandlerMapping mapping = new AbstractHandlerMapping () { @Override protected Object getHandlerInternal ( HttpServletRequest request ) { // Check whether a path equals '/echo' return "/echo" . equals ( request . getRequestURI ()) && // Delegates WebSocket handshake requests to a webSocketHandler bean ! "websocket" . equalsIgnoreCase ( request . getHeader ( "upgrade" )) ? asityController : null ; } }; mapping . setOrder ( Ordered . HIGHEST_PRECEDENCE ); return mapping ; } @Override public void registerWebSocketHandlers ( WebSocketHandlerRegistry registry ) { AsityWebSocketHandler asityWebSocketHandler = new AsityWebSocketHandler (). onwebsocket ( wsAction ()); registry . addHandler ( asityWebSocketHandler , "/echo" ); } public static void main ( String [] args ) { SpringApplication . run ( EchoServer . class ); } } Now you can handle HTTP requests and WebSocket connections from /echo asynchronously through a AsityController 's onhttp method and a AsityWebSocketHandler 's onwebsocket method. Quirks ServerHttpExchange 's onclose isn't supported. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-spring-webmvc4.

Vert.x 3 Add a io.cettia.asity:asity-bridge-vertx3:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-vertx3 </artifactId> <version> 3.0.0 </version> </dependency> Then register a AsityRequestHandler as a HTTP request handler and a AsityWebSocketHandler as a WebSocket connection handler in a http server. package io . cettia . asity . example . vertx3 ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.vertx3.AsityRequestHandler ; import io.cettia.asity.bridge.vertx3.AsityWebSocketHandler ; import io.cettia.asity.example.echo.HttpEchoServer ; import io.cettia.asity.example.echo.WebSocketEchoServer ; import io.cettia.asity.http.ServerHttpExchange ; import io.cettia.asity.websocket.ServerWebSocket ; import io.vertx.core.AbstractVerticle ; import io.vertx.core.http.HttpServer ; public class EchoServerVerticle extends AbstractVerticle { @Override public void start () { // Web fragments Action < ServerHttpExchange > httpAction = new HttpEchoServer (); Action < ServerWebSocket > wsAction = new WebSocketEchoServer (); HttpServer httpServer = vertx . createHttpServer (); AsityRequestHandler asityRequestHandler = new AsityRequestHandler (). onhttp ( httpAction ); httpServer . requestHandler ( request -> { if ( request . path (). equals ( "/echo" )) { asityRequestHandler . handle ( request ); } }); AsityWebSocketHandler asityWebsocketHandler = new AsityWebSocketHandler (). onwebsocket ( wsAction ); httpServer . websocketHandler ( socket -> { if ( socket . path (). equals ( "/echo" )) { asityWebsocketHandler . handle ( socket ); } }); httpServer . listen ( 8080 ); } } Now you can handle HTTP requests and WebSocket connections from /echo asynchronously through a AsityRequestHandler 's onhttp method and a AsityWebSocketHandler 's onwebsocket method. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-vertx3.

Netty 4 Add a io.cettia.asity:asity-bridge-netty4:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-netty4 </artifactId> <version> 3.0.0 </version> </dependency> Then add a AsityServerCodec as a channel handler to a channel pipeline. When configuring the handler, you should add HttpServerCodec in front of the handler. package io . cettia . asity . example . netty4 ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.netty4.AsityServerCodec ; import io.cettia.asity.example.echo.HttpEchoServer ; import io.cettia.asity.example.echo.WebSocketEchoServer ; import io.cettia.asity.http.ServerHttpExchange ; import io.cettia.asity.websocket.ServerWebSocket ; import io.netty.bootstrap.ServerBootstrap ; import io.netty.channel.Channel ; import io.netty.channel.ChannelInitializer ; import io.netty.channel.ChannelPipeline ; import io.netty.channel.EventLoopGroup ; import io.netty.channel.nio.NioEventLoopGroup ; import io.netty.channel.socket.SocketChannel ; import io.netty.channel.socket.nio.NioServerSocketChannel ; import io.netty.handler.codec.http.HttpRequest ; import io.netty.handler.codec.http.HttpServerCodec ; import java.net.URI ; public class EchoServer { public static void main ( String [] args ) throws Exception { // Web fragments Action < ServerHttpExchange > httpAction = new HttpEchoServer (); Action < ServerWebSocket > wsAction = new WebSocketEchoServer (); EventLoopGroup bossGroup = new NioEventLoopGroup (); EventLoopGroup workerGroup = new NioEventLoopGroup (); try { ServerBootstrap bootstrap = new ServerBootstrap (); bootstrap . group ( bossGroup , workerGroup ) . channel ( NioServerSocketChannel . class ) . childHandler ( new ChannelInitializer < SocketChannel >() { @Override public void initChannel ( SocketChannel ch ) { AsityServerCodec codec = new AsityServerCodec () { @Override protected boolean accept ( HttpRequest req ) { return URI . create ( req . uri ()). getPath (). equals ( "/echo" ); } }; codec . onhttp ( httpAction ). onwebsocket ( wsAction ); ChannelPipeline pipeline = ch . pipeline (); pipeline . addLast ( new HttpServerCodec ()). addLast ( codec ); } }); Channel channel = bootstrap . bind ( 8080 ). sync (). channel (); channel . closeFuture (). sync (); } finally { workerGroup . shutdownGracefully (); bossGroup . shutdownGracefully (); } } } Now you can handle HTTP requests and WebSocket connections from /echo asynchronously through a AsityServerCodec 's onhttp and onwebsocket methods. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-netty4.

Play Framework 2 Add a io.cettia.asity:asity-bridge-play2:3.0.0 (Javadoc) as a dependency of your application. libraryDependencies += "io.cettia.asity" % "asity-bridge-play2" % "3.0.0" Then write an action that returns AsityHttpAction 's CompletionStage<Result> as a HTTP request handler and an action that returns AsityWebSocket as a WebSocket handler, and add them to the routes file. package io . cettia . asity . example . play2 ; import akka.actor.ActorSystem ; import akka.stream.Materializer ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.play2.AsityHttpAction ; import io.cettia.asity.bridge.play2.AsityWebSocket ; import io.cettia.asity.example.echo.HttpEchoServer ; import io.cettia.asity.example.echo.WebSocketEchoServer ; import io.cettia.asity.http.ServerHttpExchange ; import io.cettia.asity.websocket.ServerWebSocket ; import play.mvc.BodyParser ; import play.mvc.Controller ; import play.mvc.Http ; import play.mvc.Result ; import play.mvc.WebSocket ; import javax.inject.Inject ; import java.util.concurrent.CompletionStage ; public class EchoController extends Controller { // Web fragments private final Action < ServerHttpExchange > httpAction = new HttpEchoServer (); private final Action < ServerWebSocket > wsAction = new WebSocketEchoServer (); private final ActorSystem actorSystem ; private final Materializer materializer ; @Inject public EchoController ( ActorSystem actorSystem , Materializer materializer ) { this . actorSystem = actorSystem ; this . materializer = materializer ; } @BodyParser . Of ( BodyParser . Raw . class ) public CompletionStage < Result > http ( Http . Request request ) { AsityHttpAction action = new AsityHttpAction (); action . onhttp ( httpAction ); return action . apply ( request ); } public WebSocket websocket () { AsityWebSocket webSocket = new AsityWebSocket ( actorSystem , materializer ); webSocket . onwebsocket ( wsAction ); return webSocket ; } } GET /echo io.cettia.asity.example.play2.EchoController.websocket POST /echo io.cettia.asity.example.play2.EchoController.http(request: Request) Now you can handle POST HTTP requests and WebSocket connections from /echo asynchronously through a AsityHttpAction 's onhttp and a AsityWebSocket 's onwebsocket methods. Add more routes to handle requests using other HTTP methods with AsityHttpAction . Quirks It requires Play Framework 2.6 and above.

ServerHttpExchange 's onclose isn't supported.

's onclose isn't supported. Play Framework doesn't support to read request body by chunk asynchronously. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-play2.

Grizzly 2 Add a io.cettia.asity:asity-bridge-grizzly2:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-grizzly2 </artifactId> <version> 3.0.0 </version> </dependency> Then register a AsityHttpHandler as a HTTP request handler in a server configuration and a AsityWebSocketApplication as a WebSocket application in a WebSocket engine. package io . cettia . asity . example . grizzly2 ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.grizzly2.AsityHttpHandler ; import io.cettia.asity.bridge.grizzly2.AsityWebSocketApplication ; import io.cettia.asity.example.echo.HttpEchoServer ; import io.cettia.asity.example.echo.WebSocketEchoServer ; import io.cettia.asity.http.ServerHttpExchange ; import io.cettia.asity.websocket.ServerWebSocket ; import org.glassfish.grizzly.http.server.HttpServer ; import org.glassfish.grizzly.http.server.NetworkListener ; import org.glassfish.grizzly.http.server.ServerConfiguration ; import org.glassfish.grizzly.websockets.WebSocketAddOn ; import org.glassfish.grizzly.websockets.WebSocketEngine ; public class EchoServer { public static void main ( String [] args ) throws Exception { // Web fragments Action < ServerHttpExchange > httpAction = new HttpEchoServer (); Action < ServerWebSocket > wsAction = new WebSocketEchoServer (); HttpServer httpServer = HttpServer . createSimpleServer (); ServerConfiguration config = httpServer . getServerConfiguration (); config . addHttpHandler ( new AsityHttpHandler (). onhttp ( httpAction ), "/echo" ); NetworkListener listener = httpServer . getListener ( "grizzly" ); listener . registerAddOn ( new WebSocketAddOn ()); WebSocketEngine . getEngine (). register ( "" , "/echo" , new AsityWebSocketApplication (). onwebsocket ( wsAction )); httpServer . start (); System . in . read (); } } Now you can handle HTTP requests and WebSocket connections from /echo asynchronously through a AsityHttpHandler 's onhttp method and a AsityWebSocketApplication 's onwebsocket method. Quirks Grizzly 2.4 requires javax.servlet:javax.servlet-api:4.y.z . Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-grizzly2.

Vert.x 2 Add a io.cettia.asity:asity-bridge-vertx2:3.0.0 (Javadoc) as a dependency of your application. <dependency> <groupId> io.cettia.asity </groupId> <artifactId> asity-bridge-vertx2 </artifactId> <version> 3.0.0 </version> </dependency> Then register a AsityRequestHandler as a HTTP request handler and a AsityWebSocketHandler as a WebSocket connection handler in a http server. package io . cettia . asity . example . vertx2 ; import io.cettia.asity.action.Action ; import io.cettia.asity.bridge.vertx2.AsityRequestHandler ; import io.cettia.asity.bridge.vertx2.AsityWebSocketHandler ; import io.cettia.asity.example.echo.HttpEchoServer ; import io.cettia.asity.example.echo.WebSocketEchoServer ; import io.cettia.asity.http.ServerHttpExchange ; import io.cettia.asity.websocket.ServerWebSocket ; import org.vertx.java.core.http.HttpServer ; import org.vertx.java.core.http.RouteMatcher ; import org.vertx.java.platform.Verticle ; public class EchoServerVerticle extends Verticle { @Override public void start () { // Web fragments Action < ServerHttpExchange > httpAction = new HttpEchoServer (); Action < ServerWebSocket > wsAction = new WebSocketEchoServer (); HttpServer httpServer = vertx . createHttpServer (); RouteMatcher httpMatcher = new RouteMatcher (); httpMatcher . all ( "/echo" , new AsityRequestHandler (). onhttp ( httpAction )); httpServer . requestHandler ( httpMatcher ); AsityWebSocketHandler websocketHandler = new AsityWebSocketHandler (). onwebsocket ( wsAction ); httpServer . websocketHandler ( socket -> { if ( socket . path (). equals ( "/echo" )) { websocketHandler . handle ( socket ); } }); httpServer . listen ( 8080 ); } } Now you can handle HTTP requests and WebSocket connections from /echo asynchronously through a AsityRequestHandler 's onhttp method and a AsityWebSocketHandler 's onwebsocket method. Working Example A full example is available at https://github.com/cettia/asity/tree/master/example-vertx2.