June 18, 2013
Ravi Luthra
SourceVert.x is the framework for the next generation of asynchronous, effortlessly scalable, concurrent applications.
Vert.x is an event driven application framework that runs on the JVM - a run-time with real concurrency and unrivalled performance. Vert.x then exposes the API in Ruby, Java, Groovy, JavaScript and Python. So you choose what language you want to use. Scala and Clojure support is on the roadmap too.
Verticles are instantiated by Vert.x, can use the Vert.x API's to compose applications. The start method is called when an instance is created. From here, Verticles will typically call various Vert.x APIs to set up handlers.
package org.pjug.vertxpres; import org.vertx.java.platform.Verticle; // * A Java class can be run from the command line // | vertx run org/pjug/vertxpres/TestVerticle1.java // | (Compilation will happen in vertx) // v public class TestVerticle1 extends Verticle { public void start() { getContainer().logger().info("Test Verticle Started!"); } }
package org.pjug.vertxpres; import org.vertx.java.core.Handler; import org.vertx.java.core.http.HttpServerRequest; import org.vertx.java.platform.Verticle; public class TestVerticle2 extends Verticle { public void start() { // * vertx Variable comes from the Verticle class that TestVerticle2 // | extends. From here we have access to the rich Async APIs that // | Vert.x provides. This is anywhere from network clients, servers // | file I/O, timers and the shared data structures. // v vertx.createHttpServer() // * Here's where the Async concepts become // | clearly visible. There are optional // | methods on most of the API's the provide // | a user to pass in a callback. // v .requestHandler(new Handler<HttpServerRequest>() { // * The APIs are designed with Java 8 and other languages // | that support "functional interfaces" that is interfaces // | with a single method. Languages like Java 8 and Groovy // | can instead use a type-hinted closure instead of all // | of the usual boiler plate code. // v @Override public void handle(HttpServerRequest request) { // * The response is part of the request object // | think of this as similar streamlining we get // | from the concepts behind Vert.x - to present // | a simpler application development platform. // | This is a concept Node.js started, and Vert.x // | takes to heart. // | * For more methods available in the // | | Vert.x API, please see the manual. // v v request.response().end("Thanks!"); } }).listen(8080); vertx.setTimer(1000, new Handler<Long>() { @Override public void handle(Long event) { container.logger().info("1 second elapsed"); } }); } }
In addition to supporting blocking calls, worker verticles are also able to make network connections. Normal verticles will throw an exception if a network connection is made in a non-async way.
package org.pjug.vertxpres; import org.vertx.java.core.Handler; import org.vertx.java.core.eventbus.Message; import org.vertx.java.platform.Verticle; public class TestVerticle3 extends Verticle { public void start() { // * To access the Event Bus API // | * Register a handler (subscription) to an address // | | and all messages published will arrive here. // v v vertx.eventBus().registerHandler("random", new Handler<Message<Long>>() { @Override public void handle(Message<Long> event) { // * The event object contains a body method to access the primitive // | value that was sent. // | * The reply method is used to send a message back to the // | | caller. This is how communication on the eventBus works, // | | send a message, get a reply, which can be repeated any // | | number of times until no reply Handler is provided. // | | * event.body() is the message // | | | from the original send call // v v v event.reply((long) (Math.random() * event.body())); } }); // Do the following every second vertx.setPeriodic(1000, new Handler<Long>() { @Override public void handle(Long event) { // * Send a message to the address random. // | * The optional third // | | parameter is a Handler // | | instance that can receive // | | the reply message. // v v vertx.eventBus().send("random", 1000L, new Handler<Message<Long>>() { @Override public void handle(Message<Long> event) { // Once the reply is received, handle is called, event.body() // is the random number sent from the service. container.logger().info( "Random number from random service: " + event.body()); } }); } }); } }
vertx run org/pjug/vertxpres/TestVerticle3.java
Random number from random service: 145 Random number from random service: 307 Random number from random service: 10 Random number from random service: 774 Random number from random service: 52 Random number from random service: 471 Random number from random service: 84 Random number from random service: 416 Random number from random service: 449 Random number from random service: 445 Random number from random service: 662 Random number from random service: 645 Random number from random service: 607 Random number from random service: 619
package org.pjug.vertxpres; import java.util.Date; import org.vertx.java.core.AsyncResult; import org.vertx.java.core.Handler; import org.vertx.java.core.eventbus.Message; import org.vertx.java.core.json.JsonObject; import org.vertx.java.platform.Verticle; public class TestVerticle4 extends Verticle { public void start() { // * Construct a config object for the Module we're deploying // | The configuration manual is located on the website // | of the module itself. (These are typically github sites) // v final JsonObject config = new JsonObject(); config.putString("db_name", "test"); config.putString("address", "vertx.mongopersistor"); // * The module is specified by the name found at the // | main Vert.x Module registry. The module is // | downloaded at runtime. (the vertx process will // | actually fetch this module when the verticle // | hits this async operation. // v container.deployModule("io.vertx~mod-mongo-persistor~2.0.0-beta2", config, new Handler<AsyncResult<String>>() { @Override public void handle(AsyncResult<String> event) { if (event.succeeded()) { // * Once we're sure the persistor has started, we can do // | additional things. In this case we'll just call another // | method that saves a single object in MongoDB. It's important // | to run this code INSIDE this callback handler. If the module // | is not set up when we try to send a message to be persisted // | the message will not go anywhere. (Vert.x just eats messages // | that are sent to addresses that nothing is listening on. // v afterDeploySuccess(); } else { container.logger().info(event.result()); } } }); } protected void afterDeploySuccess() { JsonObject doc = new JsonObject(); doc.putNumber("RandomNumber", Math.random()); doc.putString("timestamp", (new Date()).toString()); JsonObject save = new JsonObject(); save.putString("action", "save"); save.putString("collection", "test"); save.putObject("document", doc); vertx.eventBus().send("vertx.mongopersistor", save, new Handler<Message>() { @Override public void handle(Message event) { container.logger().info("Saved: " + event.body()); } }); } }
vertx.sharedData()
// * Access to the 'vertx' API // | * Each supported language comes with a language module "shim" // | | to make vertx programs fit well with the idioms of the language // | | Here we see require() as is typical in Node.js or any "CommonJS" // | | environment // v v var vertx = require('vertx'); var console = require('vertx/console'); // We see the API is often chained. This is typical in environments // that support async features vertx.createNetServer().connectHandler(function(sock) { console.log("We have a connection"); sock.dataHandler(function(buffer) { console.log('RCV: ' + buffer); }); }).listen(8080);
vertx run test1.js
telnet localhost 8080
// * Note the vertx variable. In groovy this variable is simply added // | to the default binding // | * Groovy supports closures!, so // v v shall the Groovy vertx shim! vertx.createHttpServer().requestHandler { request -> println "A request has arrived on the server!" request.response.putHeader("Content-Type", "text/plain") // * end(...) is a way of saying, close the stream and send // v this data. request.response.end("Hello!") }.listen(8080)See it!
vertx = require('vertx'); vertx.createHttpServer().requestHandler((req) -> req.response.end('<html><body><h1>Hello from vert.x!</h1></body></html>') ).listen 8080
Download & Installing
git clone git@github.com:vert-x/vert.x.git gradle dist tar xfz /path/to/vert.x/build/distributions/vert.x-xxxx.tar.gz -C /install_parentWhere xxxx is the version (in my case 2.0.0-CR1). It is also useful to remove the version information from the folder.
Create /etc/profile.d/vertx.sh
PATH=$PATH:/install_parent/vert.x-xxxx/bin EXPORT PATH
Developing
Modules