1 2 next »

Vert.x – an asynchronous, event-driven Java web framework

by Eberhard Wolff

Vert.x is a new web framework which takes its inspiration from Node.js, aims to be an alternative to the Java EE programming model and includes its own runtime environment.

At first glance, vert.x looks like just another new web framework – something of which there is no shortage in the Java landscape. But a second look shows that vert.x has been rebuilt from the ground up to offer a completely new approach to development – and not just web application development. The only things to have been spared the new broom are the foundations – vert.x is built on top of the Java Virtual Machine. But vert.x goes its own way, even when it comes to programming languages. As well as Java, it currently supports Groovy, JavaScript with the Rhino framework, and Ruby, via JRuby.

In theory these languages can be used in every Java framework, but vert.x offers an additional wrapper around the Java framework, so that in every language it feels like a native framework written just for that language.

Vert.x also faces up to contemporary expectations of a web framework. Web application logic is increasingly being implemented in JavaScript and run in the browser. The focus of the framework is therefore no longer on rendering HTML pages and processing form data. The server needs to be able to output static pages for HTML and JavaScript and process connections to JavaScript clients using WebSockets.

Vert.x also supports SockJS, an additional JavaScript communications library. This enables JavaScript to communicate with the server directly. Data is generally accessed via a REST interface which in turn uses functionality from the HTTP protocol. As a result, abstraction from HTTP is less important for web frameworks than it used to be.

Asynchronous and event-driven

Protocols such as WebSockets and SockJS give rise to new problems. In conventional web applications, a connection is usually only open for a single request and a single response. That's usually a very short time span, but while it lasts, the connection is highly active and a single thread is usually assigned to it. With WebSockets and SockJS, there is a permanently open connection for each client, and it is used only occasionally. Applications with many mobile or embedded clients face similar challenges. Allocating a thread to each connection results in a large number of threads, most of which, at any one time, are inactive. Threads require dedicated data for tasks such as administration, and switching between threads also takes time. Avoiding this kind of overhead is a key priority.

Vert.x therefore takes a different route; it uses asynchronous processing. The programmer registers callbacks in response to specific events. The code does not read data, but is called when new data arrives. As a result, the framework requires just a single thread for multiple connections. This thread simply processes the callbacks for all connections when there is new data which requires processing. This is illustrated by the following web application code:

public class HttpServerExample extends Verticle {

public void start() {

vertx.createHttpServer().requestHandler(

new Handler<HttpServerRequest>() {

public void handle(HttpServerRequest req) {

req.response.headers().

put("Content-Type", "text/html; charset=UTF-8");

req.response.

end("<html><body><h1>Hallo!</h1></body></html>");

}

}).listen(8080);

}

}

Verticle is a superclass. The name 'Verticle' designates an application in vert.x. When launched, the application registers a callback which is called for every HTTP request. In response, the callback outputs an HTML file. Finally, an HTTP server running this logic is launched on port 8080.

This approach brings its own problem: if a thread needs longer to process a request, because it has to wait for I/O, for example, this affects other connections handled by the same thread. Vert.x is therefore fully asynchronous. The methods used do not write output to the socket; that happens later, just as the handler is called at some point after the HttpRequest is received. This prevents I/O function blocking, so that no connection has to wait too long when new data arrives.

Vert.x manages actions of this type as events, which it processes in turn in an 'event loop' thread. Vert.x can also run several event loops in parallel. The number of event loops is limited to the number of processor cores in the system, as they are active almost continuously and can therefore utilise a full core capacity.

As a result, vert.x has to break with Java standards such as servlets which run contrary to this programming model. 'Worker verticles' can be used to run more time-consuming tasks which might block an event loop. This particularly includes the use of blocking APIs which do not conform to vert.x's asynchronous model – for example database APIs. The worker verticles are executed by threads from a dedicated thread pool and are therefore largely separated from the event loops.

This approach has some big effects on the programming model. The developer uses many more callbacks, which, at least in Java, are not always easy to understand. Other languages use closures or functions, which are a lot simpler.

Further, a verticle is always assigned to a single thread, so that only one thread is ever active in a single verticle. As a result, significantly less concurrent programming is required, making the code a lot more simple.

WebSockets works in exactly the same way as HTTP:

public class WebSocketsEcho extends Verticle {

public void start() {

vertx.createHttpServer()

.websocketHandler(new Handler<ServerWebSocket>() {

public void handle(final ServerWebSocket ws) {

ws.dataHandler(new Handler<Buffer>() {

public void handle(Buffer data) {

ws.writeTextFrame(data.toString());

}

});

}

}).requestHandler(new Handler<HttpServerRequest>() {

public void handle(HttpServerRequest req) {

if (req.path.equals("/"))

req.response.sendFile("websockets/ws.html");

}

}).listen(8080);

}

}

Essentially, the developer again registers appropriate handlers for HTTP requests and WebSockets queries. This allows JavaScript clients to communicate with the logic on the server without difficulty. The concepts implemented in vert.x thus work in a wide range of communication scenarios. Vert.x is also able to output data for JavaScript clients as JSON (JavaScript Object Notation) and includes a library for that purpose.

Next: Coordinating verticles

1 2 next »

Print Version | Permalink: http://h-online.com/-1615383