Quantcast
Channel: Vert.x
Viewing all 158 articles
Browse latest View live

Vert.x3 and PostgreSQL JSON type

$
0
0

One of the interesting features of NoSQL databases is their schema-less mode of operation. This feature is very useful during project prototyping and early development since at early the stages of development of projects all data structures are not clear or have been defined yet. The reason of this post is not to discuss about that subject, but to show that sometimes you can also use NoSQL with a more traditional database engine like PostgreSQL.

Since version 9.3 there is support for JSON however with version 9.4 there is even better support with the new type JSONB. I will now show how to use the basic JSON type in a simple REST application written with Vert.x3:

Now all you need to do is play with this REST service, for this you can use curl to create a sale:

$ curl \
    -i \
    -H "Content-Type: application/json" \
    -X POST \
    -d'{"id": 1, "customer_name": "John", "items": {"description": "milk", "quantity": 4}}' \
    http://localhost:8080/sales

HTTP/1.1201 Created
Content-Length: 0

And if you want to read that new document:

$ curl -i -H "Accept: application/json" -X GET http://localhost:8080/sales/1
HTTP/1.1200 OK
content-type: application/json
Content-Length: 75

{"id":1,"customer_name":"John","items":{"description":"milk","quantity":4}}

Checklist for Migrating from Vert.x 2.1.x to Vert.x 3 - Part One

$
0
0

This blog post presents feedbacks from a project migration using Vert.x 2 to Vert.x 3.

We are in the process of converting our Vert.x 2.1.5 application to Vert.x 3.0.

So while upgrading our application, I thought I should note down all the changes that we had to do in the process. Since Vert.x 3 is a major upgrade from the previous version, with so many changes.

It requires re-thinking your current 2.x Vert.x application. There are new classes, new apis, and a new package structure that has greatly simplified things that we used to have to work around. Therefore in our upgrade it required us to refactor and remove any unnecessary “hacks” that weren’t available in 2 that are now a part of Vert.x 3 that you really want and need to take advantage of. (I don’t mean there are hacks in 3.x, just that we had in our application with Vert.x 2.x)

There are Metrics, and Clustered shared data, with locking and many more features that are amazing new additions. These are things we had to hack into our application with Vert.x 2.x. We added our own MetricsRegistry from DropWizard which meant making our own Main class that called Vert.x’s Starter class after starting up the registry, but only in our Devops server deploys, not our developer machines. And we had to build our own distributed locked of clustered data that also required writing a comprehensive distributed timers. (The timers got fixed with a better actor model). But now we can use what Vert.x gives us internally for those use cases.

This blog post is part one, as I am sure there will be some new changes that we need to do that we haven’t gotten to yet. Which as we go, will post in part two. Also that this post is a work in progress in that whenever you are upgrading and refactoring your code, it doesn’t leave much time for taking detailed notes, or writing beautiful prose. I am a terrible writer even when I can fully concentrate on it. So the first draft will just be a list of my notes. These notes are not in any particular order, but some things like tests you might want to save for last. (Just DON’T delete your tests, tests are very important)

One of the first things that Vert.x has changed is the whole classloader setup. Read the Vert.x Docs for more information but basically, we have a flat classloader system now. YAY! And one of the first things I noticed that is gone is the Platform module.

Changes we have made.

Dependency changes

  1. So the first thing we did was to remove the vert.x-platform dependency from our pom file (Build dependency file of whatever build system you use) This also means that you will be removing any import statements from your code that has .platform. Which leads us to the next point.

  2. Change all the imports for Vertx. from org.vertx to io.vertx. This could be a lot of work, as it is in every class you use Vert.x in. We had at least 250 locations to change here. Some classes have moved packages and “jars” that have them, so there will be some new jars to include as dependencies and different import statements for them.

  3. If using a language other than Java, change the dependency to vertx-lang-<>

  4. Remove any modules references that are using Vert.x 2.x stuff. You can get an odd error like The type org.vertx.java.core.json.JsonObject cannot be resolved. It is indirectly referenced from required .class files.

  5. testtools dependency is gone. There is now Vertx-unit. So all your previous tests need to be completely re-written in the new style. This can be really difficult and time consuming as the tests you already have written really do need to be re-written from scratch. But these tests are also the backbone in knowing if your code is working. So this could take months if you have a really full set of test suites already. Also note the list below is to convert your JUnit Integration tests. as vertx-unit first and foremost provides its own testing framework/suite but it also works in JUnit, and if you are using JUnit you need to do the following

    • Remove all the imports to TestTools, including VertxAssert. I would do a find/replace to replace all the VertxAssert to testContext for when you have to add TestContext to all your @Test methods. I recommend naming the parameter testContext, just to put more context, into your context. Because if you just have context as your parameter name, how do you know what context the context is? Sorry, that was too much fun. Basically, what I am saying is if you have say Spring ApplicationContext in with your integration tests with Vert.x what does context represent? Spring or Vert.x test context.
    • Add @RunWith(VertxUnitRunner.class) above your test class
    • Remove any VertxAssert.testComplete() those are gone. It needs TestContext.async().complete(). It is also important to understand what async() means. When to call it, when to complete it. It also allows you to do multiple async() calls and nested ones. I think I needed that when I had a test that was a longer use case of many messages being sent, but only after responses to other ones occurred. For instance, to do chat in our app, you have to connect, subscribe, friend someone, then you can send a chat message. So that is 4 total Vert.x Messages sent from the Test client. And you can subscribe until connect completed, and you can send or receive messages unless you are subscribed and have a friend. So we need to have a few async() calls in that scenario.
    • What is in your start method override. Make that an @Before.
    • What is in your stop method override. Make that an @After.
    • If you have your assertions have custom message strings to log out when they fail, that parameter is now at the end of the assert method call. Yes, this one can be painful.

Build Changes

  1. Remove all vertx maven plugin code to generate modules, instead create fat jars, which requires adding the Shade maven plugin to put all jar files into a big fat jar. The vertx-examples project has simplest-maven which has the stuff to create the fat jar. simplest-gradle is the gradle equivalent.

  2. If you were running your application with runMod or something like that then you need to create a fat jar, changing the build file as in this one and create a Main class like here this one.

Class/Code Changes

  1. Verticle is now an interface and not a class to extend, so using Groovy as an example you now extend GroovyVerticle. In Java extend AbstractVerticle instead.

  2. There is no registerHandler on the eventBus anymore. So everywhere you do that has to change to create/call consumer() and to unregister that handler, you have to have a reference to the MessageConsumer that consumer() call returns and call its unregister method.

  3. JsonObject.toMap() changed to JsonObject.getMap()

  4. JsonObject also removed all the putXXX methods with just one put method with overloaded versions for different types.

  5. JsonObjectMessage no longer exists. What replaces depends on what you are doing. Meaning, if it is an async callback to a deploy, you will get a Message instance back that has succeeded() or failed() methods as well as body() to check any results. If it is a Consumer, it is typically a straight forward JsonObject. If you are in Groovy it is also a JsonObject, but the body() is a Map which you can use directly now, instead of having to convert from JsonObject to Map.

  6. There isn’t a container variable in Verticles anymore for deploying verticles and also a config file. You need to use vertx.getOrCreateContext().config() to get to it. I used that in the SockJS Example code below.

  7. SharedData no longer has shared sets. It has a Map of SharedData, so an entry in that Map of shared data could be the name of the set as the key, and a Set as the value. It actually gives you more flexibility of what you put into Shared data, so this is actually a big win for us.

  8. Getting the writeHandlerID from a Socket type, is now a method call instead of .writeHandlerID, so .writeHandlerID()

  9. SockJSSocket is in vertx-web package now, so include it to get the class.

  10. There isn’t a SockJSServer class anymore either. So you will create a WebServer, a Router and set SSL (if you are using SSL on the WebServer) then create a SockJSHandler to assign to the router via the route() method and handler() methods in the Router api. Here is an example of our code. Although I haven’t tested it yet. ;)

publicclassMyVerticleextendsGroovyVerticle {
  Router router

  @Overridevoid start() throws Exception {
     router = Router.router(vertx)
     (Map) sslConfig =
        (Map)vertx.getOrCreateContext()
          .config().get('ssl')

     HttpServer sslHttpServer = vertx.createHttpServer(
         SSL:true,
         keyStorePath: sslConfig.get("keystore"),
         keyStorePassword: sslConfig.get("password"))

     startWebApiServer(sslHttpServer)
  }

  privatevoid startWebApiServer(final HttpServer httpServer) {
    def sockHandler = SockJSHandler.create(vertx, [:])
    sockHandler.socketHandler {
      SockJSSocket ws -> sockJSConnectHandler(ws)
    }
    router.route("/hdpoker").handler(sockHandler)
    httpServer.requestHandler(router.&accept)
    httpServer.listen()
  }

}

More testing change

Testing messages in Integration Tests. To tell the test method that this has async calls put Async async = testContext.async() as the first line in the test method. Yes, this is a little redundant from above, but I always forgot to put async() calls in my integration tests and they would pass so quickly, without sending anything out, because it wasn’t waiting anymore

Runtime changes

If you don’t use Vert.x built-in Logging and need to use slf4j, then remember that you should set a system property called vertx.logger-delegate-factory-class-name with the name of a Java class which implements the interface LoggerFactory. Vert.x provides pre-built implementations for Log4J and SLF4J with the class names io.vertx.core.logging.Log4jLogDelegateFactory and io.vertx.core.logging.SLF4JLogDelegateFactory.

Still working

Well, that is all I have for you folks so far. We are still not done, as we haven’t gotten our application running with real clients just yet. But we do have all our integration tests from before completely passing so, if something does come up, it should be a small one (KNOCK ON WOOD)

Please feel free to post on the Vert.x Google Group with any comments or suggestions on what to add to this blog post or for Part Two.

Thanks

Mark S

Vert.x3 says "hello" to NPM users

$
0
0

In programming literature it has become the standard to create a hello world program as the first example. In this article I’ll be demonstrating how NPM users can quickly get started with vert.x. You will see that it is not that different and in fact it can be done using the tools you’re used to. Note that although we are using NPM we are not relying on node.js, all javascript code runs on the JVM.

Hello World Examples

Here are four simple hello world examples. The comments in the code explain how the code works and the text around it explain what it does and how to test it.

Hello Console

This example is about as plain as it can get. It prints the words “Hello World“ to the terminal. If you’re a javascript developer you should be already used to npm and know that you always start a project with the file package.json:

{
  "name": "vertx3-hello-console",
  "private": true,
  "dependencies": {
    "vertx3-min": "3.0.0-1"
  },
  "scripts": {
    "start": "./node_modules/.bin/vertx run server.js"
  }
}

Note that we have a dependency wich is obvious vert.x now note that there are 3 flavours of this dependency:

According to your needs you can pick a different flavour, since for a simple hello world we only need the minimal that is the one we add to the dependency property.

Now we need to do a simple hello app, we will call this file “server.js“:

// Call the console.log function.console.log("Hello World");

You can run this by executing:

npm install
npm start

The first command retrieve the vert.x stack while the seconds starts your program.

Hello HTTP

I’d guess that while it’s not the only use case for vert.x, most people are using it as a web application platform. So the next example will be a simple HTTP server that responds to every request with the plain text message “Hello Worldserver.js:

vertx.createHttpServer()
  .requestHandler(function(req){
    req.response()
      .putHeader("content-type", "text/plain")
      .end("Hello World!");
}).listen(8080);

Now you can reuse the same package.json we’ve just defined in the previous section and start the server with npm start. Once the server starts you can open a browser to http://localhost:8080 and enjoy the message.

Hello TCP

Vert.x also makes an excellent TCP server, and here is an example that responds to all TCP connections with the message “Hello World” and then closes the connection server.js:

var server = vertx.createNetServer();
server.connectHandler(function(socket){
  socket.write("Hello World!\n");
  socket.close();
});

server.listen(7000, "localhost");

Again reuse the previous package.json and test it by doing telnet localhost 7000.

Hello Web

Often you won’t be using vert.x built-in libraries because they are designed to be very low level. This makes vert.x quick, nimble, and easy to maintain, but if you are planning to build a complex application you want some productivity and rely on a simple web framework. For this specific case there is vert.x web, a simple, yet productive framework, to build fast web application with routing, template rendering, lots of middleware etc…usually not enough to get started on a real world application. This example shows an HTTP server that responds with “Hello World” to all requests to “/“ and responds with a 404 error to everything else server.js:

var Router = require("vertx-web-js/router");
var server = vertx.createHttpServer();

var router = Router.router(vertx);

router.get("/").handler(function(ctx){
  // This handler will be called for "/" requestsvar response = ctx.response();
  response.putHeader("content-type", "text/plain");

  // Write to the response and end it
  response.end("Hello World!");
});

server.requestHandler(router.accept).listen(8080);

In order to test this, you will need to install the vertx3-full stack. There are two ways to do this. You can either install it globally npm install -g vertx3-full or add it as a dependency to our package.json as we have done before, for example package.json:

{
  "name": "vertx3-hello-web",
  "private": true,
  "dependencies": {
    "vertx3-full": "3.0.0-1"
  },
  "scripts": {
    "start": "./node_modules/.bin/vertx run server.js"
  }
}

That’s it for now. Hopefully this will help you get started working with vert.x!

My first Vert.x 3 Application

$
0
0

Let’s say, you heard someone saying that Vert.x is awesome. Ok great, but you may want to try it by yourself. Well, the next natural question is “where do I start ?”. This post is a good starting point. It shows how is built a very simple vert.x application (nothing fancy), how it is tested and how it is packaged and executed. So, everything you need to know before building your own groundbreaking application.

The code developed in this post is available on github. This post is part of the Introduction to Vert.x series. The code of this post in in the post-1 branch.

Let’s start !

First, let’s create a project. In this post, we use Apache Maven, but you can use Gradle or the build process tool you prefer. You could use the Maven jar archetype to create the structure, but basically, you just need a directory with:

  1. a src/main/java directory
  2. a src/test/java directory
  3. a pom.xml file

So, you would get something like:

.
├── pom.xml├── src
│   ├── main
│   │   └── java
│   └── test
│       └── java

Let’s create the pom.xml file with the following content:

<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0modelVersion><groupId>io.vertx.bloggroupId><artifactId>my-first-appartifactId><version>1.0-SNAPSHOTversion><dependencies><dependency><groupId>io.vertxgroupId><artifactId>vertx-coreartifactId><version>3.0.0version>dependency>dependencies><build><plugins><plugin><artifactId>maven-compiler-pluginartifactId><version>3.3version><configuration><source>1.8source><target>1.8target>configuration>plugin>plugins>build>project>

This pom.xml file is pretty straightforward:

  • it declares a dependency on vertx-core
  • it configures the maven-compiler-plugin to use Java 8.

This second point is important, Vert.x applications require Java 8.

Let’s code !

Ok, now we have made the pom.xml file. Let’s do some real coding… Create the src/main/java/io/vertx/blog/first/MyFirstVerticle.java file with the following content:

package io.vertx.blog.first;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;

publicclassMyFirstVerticleextendsAbstractVerticle{

  @Overridepublicvoidstart(Future fut){
    vertx
        .createHttpServer()
        .requestHandler(r -> {
          r.response().end("

Hello from my first "

+ "Vert.x 3 application"); }) .listen(8080, result -> { if (result.succeeded()) { fut.complete(); } else { fut.fail(result.cause()); } }); } }

This is actually our not fancy application. The class extends AbstractVerticle. In the Vert.x world, a verticle is a component. By extending AbstractVerticle, our class gets access to the vertx field.

The start method is called when the verticle is deployed. We could also implement a stop method, but in this case Vert.x takes care of the garbage for us. The start method receives a Future object that will let us inform Vert.x when our start sequence is completed or report an error. One of the particularity of Vert.x is its asynchronous / non-blocking aspect. When our verticle is going to be deployed it won’t wait until the start method has been completed. So, the Future parameter is important to notify of the completion.

The start method creates a HTTP server and attaches a request handler to it. The request handler is a lambda, passed in the requestHandler method, called every time the server receives a request. Here, we just reply Hello ... (nothing fancy I told you). Finally, the server is bound to the 8080 port. As this may fails (because the port may already be used), we pass another lambda expression checking whether or not the connection has succeeded. As mentioned above it calls either fut.complete in case of success or fut.fail to report an error.

Let’s try to compile the application using:

mvn clean compile

Fortunately, it should succeed.

That’s all for the application.

Let’s test

Well, that’s good to have developed an application, but we can never be too careful, so let’s test it. The test uses JUnit and vertx-unit - a framework delivered with vert.x to make the testing of vert.x application more natural.

Open the pom.xml file to add the two following dependencies:

<dependency><groupId>junitgroupId><artifactId>junitartifactId><version>4.12version><scope>testscope>dependency><dependency><groupId>io.vertxgroupId><artifactId>vertx-unitartifactId><version>3.0.0version><scope>testscope>dependency>

Now create the src/test/java/io/vertx/blog/first/MyFirstVerticleTest.java with the following content:

package io.vertx.blog.first;

import io.vertx.core.Vertx;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.VertxUnitRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(VertxUnitRunner.class)
publicclassMyFirstVerticleTest{

  private Vertx vertx;

  @BeforepublicvoidsetUp(TestContext context){
    vertx = Vertx.vertx();
    vertx.deployVerticle(MyFirstVerticle.class.getName(),
        context.asyncAssertSuccess());
  }

  @AfterpublicvoidtearDown(TestContext context){
    vertx.close(context.asyncAssertSuccess());
  }

  @TestpublicvoidtestMyApplication(TestContext context){
    final Async async = context.async();

    vertx.createHttpClient().getNow(8080, "localhost", "/",
     response -> {
      response.handler(body -> {
        context.assertTrue(body.toString().contains("Hello"));
        async.complete();
      });
    });
  }
}

This is a JUnit test for our verticle. The test uses vertx-unit, so we use a custom runner. vert.x-unit makes easy to test asynchronous interactions, which are the basis of vert.x applications.

In the setUp method, we creates an instance of Vertx and deploy our verticle. You may have noticed that unlike the traditional JUnit @Before method, it receives a TestContext. This object lets us control the asynchronous aspect of our test. For instance, when we deploy our verticle, it starts asynchronously, as most Vert.x interactions. We cannot check anything until it gets started correctly. So, as second argument of the deployVerticle method, we pass a result handler: context.asyncAssertSuccess(). It fails the test if the verticle does not start correctly. In addition it waits until the verticle has completed its start sequence. Remember, in our verticle, we call fut.complete(). So it waits until this method is called, and in the case of a failures, fails the test.

Well, the tearDown method is straightforward, and just terminates the vertx instance we created.

Let’s now have a look to the test of our application: the testMyApplication method. The test emits a request to our application and checks the result. Emitting the request and receiving the response is asynchronous. So we need a way to control this. As the setUp and tearDown methods, the test method receives a TestContext. From this object we creates an async handle (async) that lets us notify the test framework when the test has completed (using async.complete()).

So, once the async handle is created, we create a HTTP client and emits a HTTP request handled by our application with the getNow() method (getNow is just a shortcut for get(...).end()). The response is handled by a lambda. In this lambda we retrieves the response body by passing another lambda to the handler method. The body argument is the response body (as a buffer object). We check that the body contains the "Hello" String and declare the test complete.

Let’s take a minute to mention the assertions. Unlike in traditional JUnit tests, it uses context.assert.... Indeed, if the assertion fails, it will interrupt the test immediately. So it’s pretty important to always uses these assertion methods because of the asynchronous aspect of the Vert.x application and so tests.

Our test can be run from an IDE, or using Maven:

mvn clean test

Packaging

So, let’s sum up. We have an application and a test. Well, let’s now package the application. In this post we package the application in a fat jar. A fat jar is a standalone executable Jar file containing all the dependencies required to run the application. This is a very convenient way to package Vert.x applications as it’s only one file. It also make them easy to execute.

To create a fat jar, edit the pom.xml file and add the following snippet just before :

<plugin><groupId>org.apache.maven.pluginsgroupId><artifactId>maven-shade-pluginartifactId><version>2.3version><executions><execution><phase>packagephase><goals><goal>shadegoal>goals><configuration><transformers><transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><Main-Class>io.vertx.core.StarterMain-Class><Main-Verticle>io.vertx.blog.first.MyFirstVerticleMain-Verticle>manifestEntries>transformer>transformers><artifactSet/><outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jaroutputFile>configuration>execution>executions>plugin>

It uses the maven-shade-plugin to create the fat jar. In the manifestEntries it indicates the name of our verticle. You may wonder from where comes the Starter class. It’s actually a class from vert.x, that is going to create the vertx instance and deploy our verticle.

So, with this plugin configured, let’s launch:

mvn clean package

This is going to create target/my-first-app-1.0-SNAPSHOT-fat.jar embedding our application along with all the dependencies (including vert.x itself).

Executing our application

Well, it’s nice to have a fat jar, but we want to see our application running! As said above, thanks to the fat jar packaging, running Vert.x application is easy as:

java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar

Then, open a browser to http://localhost:8080.

To stop the application, hit CTRL+C.

Conclusion

This Vert.x 3 crash class has presented how you can develop a simple application using Vert.x 3, how to test it, package it and run it. So, you now know everything you need to build amazing system on top of Vert.x 3. Next time we will see how to configure our application.

Happy coding & Stay tuned !

Vert.x Application Configuration

$
0
0

Previously in ‘Introduction to Vert.x’

In this post, we developed a very simple Vert.x 3 application, and saw how this application can be tested, packaged and executed. That was nice, isn’t it ? Well, ok, that was only the beginning. In this post, we are going to enhance our application to support external configuration.

So just to remind you, we have an application starting a HTTP server on the port 8080 and replying a polite “Hello” message to all HTTP requests. The previous code is available here. The code developed in this post is in the post-2 branch.

So, why do we need configuration?

That’s a good question. The application works right now, but well, let’s say you want to deploy it on a machine where the port 8080 is already taken. We would need to change the port in the application code and in the test, just for this machine. That would be sad. Fortunately, Vert.x applications are configurable.

Vert.x configurations are using the JSON format, so don’t expect anything complicated. They can be passed to verticle either from the command line, or using an API. Let’s have a look.

No ‘8080’ anymore

The first step is to modify the io.vertx.blog.first.MyFirstVerticle class to not bind to the port 8080, but to read it from the configuration:

publicvoidstart(Future fut){
  vertx
      .createHttpServer()
      .requestHandler(r -> {
        r.response().end("

Hello from my first "

+ "Vert.x 3 application"); }) .listen( // Retrieve the port from the configuration,// default to 8080. config().getInteger("http.port", 8080), result -> { if (result.succeeded()) { fut.complete(); } else { fut.fail(result.cause()); } } ); }

So, the only difference with the previous version is config().getInteger("http.port", 8080). Here, our code is now requesting the configuration and check whether the http.port property is set. If not, the port 8080 is used as fall-back. The retrieved configuration is a JsonObject.

As we are using the port 8080 by default, you can still package our application and run it as before:

mvn clean package
java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar

Simple right ?

API-based configuration - Random port for the tests

Now that the application is configurable, let’s try to provide a configuration. In our test, we are going to configure our application to use the port 8081. So, previously we were deploying our verticle with:

vertx.deployVerticle(MyFirstVerticle.class.getName(), context.asyncAssertSuccess());

Let’s now pass some deployment options:

port = 8081;
DeploymentOptions options = new DeploymentOptions()
    .setConfig(new JsonObject().put("http.port", port)
);
vertx.deployVerticle(MyFirstVerticle.class.getName(), options, context.asyncAssertSuccess());

The DeploymentOptions object lets us customize various parameters. In particular, it lets us inject the JsonObject retrieved by the verticle when using the config() method.

Obviously, the test connecting to the server needs to be slightly modified to use the right port (port is a field):

vertx.createHttpClient().getNow(port, "localhost", "/", response -> {
  response.handler(body -> {
    context.assertTrue(body.toString().contains("Hello"));
    async.complete();
  });
});

Ok, well, this does not really fix our issue. What happens when the port 8081 is used too. Let’s now pick a random port:

ServerSocket socket = new ServerSocket(0);
port = socket.getLocalPort();
socket.close();

DeploymentOptions options = new DeploymentOptions()
    .setConfig(new JsonObject().put("http.port", port)
    );

vertx.deployVerticle(MyFirstVerticle.class.getName(), options, context.asyncAssertSuccess());

So, the idea is very simple. We open a server socket that would pick a random port (that’s why we put 0 as parameter). We retrieve the used port and close the socket. Be aware that this method is not perfect and may fail if the picked port becomes used between the close method and the start of our HTTP server. However, it would work fine in the very high majority of the case.

With this in place, our test is now using a random port. Execute them with:

mvn clean test

External configuration - Let’s run on another port

Ok, well random port is not what we want in production. Could you imagine the face of your production team if you tell them that your application is picking a random port. It can actually be funny, but we should never mess with the production team.

So for the actual execution of your application, let’s pass the configuration in an external file. The configuration is stored in a json file.

Create the src/main/conf/my-application-conf.json with the following content:

{
  "http.port" : 8082
}

And now, to use this configuration just launch your application with:

java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar -conf src/main/conf/my-application-conf.json

Open a browser on http://localhost:8082, here it is !

How does that work ? Remember, our fat jar is using the Starter class (provided by Vert.x) to launch our application. This class is reading the -conf parameter and create the corresponding deployment options when deploying our verticle.

Conclusion

After having developed your first Vert.x application, we have seen how this application is configurable, and this without adding any complexity to our application. In the next post, we are going to see how we can use vertx-web to develop a small application serving static pages and a REST API. A bit more fancy, but still very simple.

Happy Coding and & Stay Tuned!

Some Rest with Vert.x

$
0
0

Previously in this blog series

This post is part of the Introduction to Vert.x series. So, let’s have a quick look about the content of the previous posts. In the first post, we developed a very simple Vert.x 3 application, and saw how this application can be tested, packaged and executed. In the last post, we saw how this application became configurable and how we can use a random port in test.

Well, nothing fancy… Let’s go a bit further this time and develop a CRUD-ish application. So an application exposing an HTML page interacting with the backend using a REST API. The level of RESTfullness of the API is not the topic of this post, I let you decide as it’s a very slippery topic.

So, in other words we are going to see:

  • Vert.x Web - a framework that let you create Web applications easily using Vert.x
  • How to expose static resources
  • How to develop a REST API

The code developed in this post is available on the post-3 branch of this Github project. We are going to start from the post-2 codebase.

So, let’s start.

Vert.x Web

As you may have notices in the previous posts, dealing with complex HTTP application using only Vert.x Core would be kind of cumbersome. That’s the main reason behind Vert.x Web. It makes the development of Vert.x base web applications really easy, without changing the philosophy.

To use Vert.x Web, you need to update the pom.xml file to add the following dependency:

<dependency><groupId>io.vertxgroupId><artifactId>vertx-webartifactId><version>3.0.0version>dependency>

That’s the only thing you need to use Vert.x Web. Sweet, no ?

Let’s now use it. Remember, in the previous post, when we requested http://localhost:8080, we reply a nice Hello World message. Let’s do the same with Vert.x Web. Open the io.vertx.blog.first.MyFirstVerticle class and change the start method to be:

@Overridepublicvoidstart(Future fut){
 // Create a router object.
 Router router = Router.router(vertx);

 // Bind "/" to our hello message - so we are still compatible.
 router.route("/").handler(routingContext -> {
   HttpServerResponse response = routingContext.response();
   response
       .putHeader("content-type", "text/html")
       .end("

Hello from my first Vert.x 3 application

"
); }); // Create the HTTP server and pass the "accept" method to the request handler. vertx .createHttpServer() .requestHandler(router::accept) .listen( // Retrieve the port from the configuration,// default to 8080. config().getInteger("http.port", 8080), result -> { if (result.succeeded()) { fut.complete(); } else { fut.fail(result.cause()); } } ); }

You may be surprise by the length of this snippet (in comparison to the previous code). But as we are going to see, it will make our app on steroids, just be patient.

As you can see, we start by creating a Router object. The router is the cornerstone of Vert.x Web. This object is responsible for dispatching the HTTP requests to the right handler. Two other concepts are very important in Vert.x Web:

  • Routes - which let you define how request are dispatched
  • Handlers - which are the actual action processing the requests and writing the result. Handlers can be chained.

If you understand these 3 concepts, you have understood everything in Vert.x Web.

Let’s focus on this code first:

router.route("/").handler(routingContext -> {
  HttpServerResponse response = routingContext.response();
  response
      .putHeader("content-type", "text/html")
      .end("

Hello from my first Vert.x 3 application

"
); });

It routes requests arriving on “/“ to the given handler. Handlers receive a RoutingContext object. This handler is quite similar to the code we had before, and it’s quite normal as it manipulates the same type of object: HttpServerResponse.

Let’s now have a look to the rest of the code:

vertx
    .createHttpServer()
    .requestHandler(router::accept)
    .listen(
        // Retrieve the port from the configuration,// default to 8080.
        config().getInteger("http.port", 8080),
        result -> {
          if (result.succeeded()) {
            fut.complete();
          } else {
            fut.fail(result.cause());
          }
        }
    );
}

It’s basically the same code as before, except that we change the request handler. We pass router::accept to the handler. You may not be familiar with this notation. It’s a reference to a method (here the method accept from the router object). In other worlds, it instructs vert.x to call the accept method of the router when it receives a request.

Let’s try to see if this work:

mvn clean package
java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar

By opening http://localhost:8080 in your browser you should see the Hello message. As we didn’t change the behavior of the application, our tests are still valid.

Exposing static resources

Ok, so we have a first application using vert.x web. Let’s see some of the benefits. Let’s start with serving static resources, such as an index.html page. Before we go further, I should start with a disclaimer: “the HTML page we are going to see here is ugly like hell : I’m not a UI guy”. I should also add that there are probably plenty of better ways to implement this and a myriad of frameworks I should try, but that’s not the point. I tried to keep things simple and just relying on JQuery and Twitter Bootstrap, so if you know a bit of JavaScript you can understand and edit the page.

Let’s create the HTML page that will be the entry point of our application. Create an index.html page in src/main/resources/assets with the content from here. As it’s just a HTML page with a bit of JavaScript, we won’t detail the file here. If you have questions, just post comments.

Basically, the page is a simple CRUD UI to manage my collection of not-yet-finished bottles of Whisky. It was made in a generic way, so you can transpose it to your own collection. The list of product is displayed in the main table. You can create a new product, edit one or delete one. These actions are relying on a REST API (that we are going to implement) through AJAX calls. That’s all.

Once this page is created, edit the io.vertx.blog.first.MyFirstVerticle class and change the start method to be:

@Overridepublicvoidstart(Future fut){
 Router router = Router.router(vertx);
 router.route("/").handler(routingContext -> {
   HttpServerResponse response = routingContext.response();
   response
       .putHeader("content-type", "text/html")
       .end("

Hello from my first Vert.x 3 application

"
); }); // Serve static resources from the /assets directory router.route("/assets/*").handler(StaticHandler.create("assets")); vertx .createHttpServer() .requestHandler(router::accept) .listen( // Retrieve the port from the configuration,// default to 8080. config().getInteger("http.port", 8080), result -> { if (result.succeeded()) { fut.complete(); } else { fut.fail(result.cause()); } } ); }

The only difference with the previous code is the router.route("/assets/*").handler(StaticHandler.create("assets")); line. So, what does this line mean? It’s actually quite simple. It routes requests on “/assets/*” to resources stored in the “assets” directory. So our index.html page is going to be served using http://localhost:8080/assets/index.html.

Before testing this, let’s take a few seconds on the handler creation. All processing actions in Vert.x web are implemented as handler. To create a handler you always call the create method.

So, I’m sure you are impatient to see our beautiful HTML page. Let’s build and run the application:

mvn clean package
java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar

Now, open your browser to http://localhost:8080/assets/index.html. Here it is… Ugly right? I told you.

As you may notice too… the table is empty, this is because we didn’t implement the REST API yet. Let’s do that now.

REST API with Vert.x Web

Vert.x Web makes the implementation of REST API really easy, as it basically routes your URL to the right handler. The API is very simple, and will be structured as follows:

  • GET /api/whiskies => get all bottles (getAll)
  • GET /api/whiskies/:id => get the bottle with the corresponding id (getOne)
  • POST /api/whiskies => add a new bottle (addOne)
  • PUT /api/whiskies/:id => update a bottle (updateOne)
  • DELETE /api/whiskies/id => delete a bottle (deleteOne)

We need some data…

But before going further, let’s create our data object. Create the src/main/java/io/vertx/blog/first/Whisky.java with the following content:

package io.vertx.blog.first;

import java.util.concurrent.atomic.AtomicInteger;

publicclassWhisky{

  privatestaticfinal AtomicInteger COUNTER = new AtomicInteger();

  privatefinalint id;

  private String name;

  private String origin;

  publicWhisky(String name, String origin){
    this.id = COUNTER.getAndIncrement();
    this.name = name;
    this.origin = origin;
  }

  publicWhisky(){
    this.id = COUNTER.getAndIncrement();
  }

  public String getName(){
    return name;
  }

  public String getOrigin(){
    return origin;
  }

  publicintgetId(){
    return id;
  }

  publicvoidsetName(String name){
    this.name = name;
  }

  publicvoidsetOrigin(String origin){
    this.origin = origin;
  }
}

It’s a very simple bean class (so with getters and setters). We choose this format because Vert.x is relying on Jackson to handle the JSON format. Jackson automates the serialization and deserialization of bean classes, making our code much simpler.

Now, let’s create a couple of bottles. In the MyFirstVerticle class, add the following code:

// Store our productprivate Map products = new LinkedHashMap<>();
// Create some productprivatevoidcreateSomeData(){
  Whisky bowmore = new Whisky("Bowmore 15 Years Laimrig", "Scotland, Islay");
  products.put(bowmore.getId(), bowmore);
  Whisky talisker = new Whisky("Talisker 57° North", "Scotland, Island");
  products.put(talisker.getId(), talisker);
}

Then, in the start method, call the createSomeData method:

@Overridepublicvoidstart(Future fut){

  createSomeData();

  // Create a router object.
  Router router = Router.router(vertx);

  // Rest of the method
}

As you have noticed, we don’t really have a backend here, it’s just a (in-memory) map. Adding a backend will be covered by another post.

Get our products

Enough decoration, let’s implement the REST API. We are going to start with GET /api/whiskies. It returns the list of bottles in a JSON Array.

In the start method, add this line just below the static handler line:

router.get("/api/whiskies").handler(this::getAll);

This line instructs the router to handle the GET requests on “/api/whiskies” by calling the getAll method. We could have inlined the handler code, but for clarity reasons let’s create another method:

privatevoidgetAll(RoutingContext routingContext){
  routingContext.response()
      .putHeader("content-type", "application/json; charset=utf-8")
      .end(Json.encodePrettily(products.values()));
}

As every handler our method receives a RoutingContext. It populates the response by setting the content-type and the actual content. Because our content may contain weird characters, we force the charset to UTF-8. To create the actual content, no need to compute the JSON string ourself. Vert.x lets us use the Json API. So Json.encodePrettily(products.values()) computes the JSON string representing the set of bottles.

We could have used Json.encodePrettily(products), but to make the JavaScript code simpler, we just return the set of bottles and not an object containing ID => Bottle entries.

With this in place, we should be able to retrieve the set of bottle from our HTML page. Let’s try it:

mvn clean package
java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar

Then open the HTML page in your browser (http://localhost:8080/assets/index.html), and should should see:

I’m sure you are curious, and want to actually see what is returned by our REST API. Let’s open a browser to http://localhost:8080/api/whiskies. You should get:

[ {
  "id" : 0,
  "name" : "Bowmore 15 Years Laimrig",
  "origin" : "Scotland, Islay"}, {
  "id" : 1,
  "name" : "Talisker 57° North",
  "origin" : "Scotland, Island"} ]

Create a product

Now we can retrieve the set of bottles, let’s create a new one. Unlike the previous REST API endpoint, this one need to read the request’s body. For performance reason, it should be explicitly enabled. Don’t be scared… it’s just a handler.

In the start method, add these lines just below the line ending by getAll:

router.route("/api/whiskies*").handler(BodyHandler.create());
router.post("/api/whiskies").handler(this::addOne);

The first line enables the reading of the request body for all routes under “/api/whiskies”. We could have enabled it globally with router.route().handler(BodyHandler.create()).

The second line maps POST requests on /api/whiskies to the addOne method. Let’s create this method:

privatevoidaddOne(RoutingContext routingContext){
  final Whisky whisky = Json.decodeValue(routingContext.getBodyAsString(),
      Whisky.class);
  products.put(whisky.getId(), whisky);
  routingContext.response()
      .setStatusCode(201)
      .putHeader("content-type", "application/json; charset=utf-8")
      .end(Json.encodePrettily(whisky));
}

The method starts by retrieving the Whisky object from the request body. It just reads the body into a String and passes it to the Json.decodeValue method. Once created it adds it to the backend map and returns the created bottle as JSON.

Let’s try this. Rebuild and restart the application with:

mvn clean package
java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar

Then, refresh the HTML page and click on the Add a new bottle button. Enter the data such as: “Jameson” as name and “Ireland” as origin (purists would have noticed that this is actually a Whiskey and not a Whisky). The bottle should be added to the table.

Status 201 ?
As you can see, we have set the response status to 201. It means CREATED, and is the generally used in REST API that create an entity. By default vert.x web is setting the status to 200 meaning OK.

Finishing a bottle

Well, bottles do not last forever, so we should be able to delete a bottle. In the start method, add this line:

router.delete("/api/whiskies/:id").handler(this::deleteOne);

In the URL, we define a path parameter:id. So, when handling a matching request, Vert.x extracts the path segment corresponding to the parameter and let us access it in the handler method. For instance, /api/whiskies/0 maps id to 0.

Let’s see how the parameter can be used in the handler method. Create the deleteOne method as follows:

privatevoiddeleteOne(RoutingContext routingContext){
  String id = routingContext.request().getParam("id");
  if (id == null) {
    routingContext.response().setStatusCode(400).end();
  } else {
    Integer idAsInteger = Integer.valueOf(id);
    products.remove(idAsInteger);
  }
  routingContext.response().setStatusCode(204).end();
}

The path parameter is retrieved using routingContext.request().getParam("id"). It checks whether it’s null (not set), and in this case returns a Bad Request response (status code 400). Otherwise, it removes it from the backend map.

Status 204 ?
As you can see, we have set the response status to 204 - NO CONTENT. Response to the HTTP Verb delete have generally no content.

The other methods

We won’t detail getOne and updateOne as the implementations are straightforward and very similar. Their implementations are available on GitHub.

Cheers !

It’s time to conclude this post. We have seen how Vert.x Web lets you implement a REST API easily and how it can serve static resources. A bit more fancy than before, but still pretty easy.

In the next post we are going to improve our tests to cover the REST API.

Say Tuned & Happy Coding !

Unit and Integration Tests

$
0
0

Previously in “introduction to vert.x”

Let’s refresh our mind about what we developed so far in the introduction to vert.x series. In the first post, we developed a very simple Vert.x 3 application, and saw how this application can be tested, packaged and executed. In the second post, we saw how this application became configurable and how we can use a random port in test, and use another configurable port in production. Finally, the previous post has shown how to use vertx-web and how to implement a small REST API. However, we forgot an important task. We didn’t test the API. In this post we will increase the confidence we have on this application by implementing unit and integration tests.

The code of this post is available in the post-4 branch of the project. The starting post, however is the code available in the post-3 branch.

Tests, Tests, Tests…

This post is mainly about tests. We distinguish two types of tests: unit tests and integration tests. Both are equally important, but have different focus. Unit tests ensure that one component of your application, generally a class in the Java world, behaves as expected. The application is not tested as a whole, but pieces by pieces. Integration tests are more black box in the sense that the application is started and tested generally externally.

In this post we are going to start with some more unit tests as a warm up session and then focus on integration tests. If you already implemented integration tests, you may be a bit scared, and it makes sense. But don’t worry, with Vert.x there are no hidden surprises.

Warmup: Some more unit tests

Let’s start slowly. Remember in the first post we have implemented a unit test with vertx-unit. The test we did is dead simple:

  1. we started the application before the test
  2. we checks that it replies “Hello”

Just to refresh your mind, let’s have a look at the code

@BeforepublicvoidsetUp(TestContext context)throws IOException {
  vertx = Vertx.vertx();
  ServerSocket socket = new ServerSocket(0);
  port = socket.getLocalPort();
  socket.close();
  DeploymentOptions options = new DeploymentOptions()
      .setConfig(new JsonObject().put("http.port", port)
      );
  vertx.deployVerticle(MyFirstVerticle.class.getName(), options, context.asyncAssertSuccess());
}

The setUp method is invoked before each test (as instructed by the @Before annotation). It, first, creates a new instance of Vert.x. Then, it gets a free port and then deploys our verticle with the right configuration. Thanks to the context.asyncAssertSuccess() it waits until the successful deployment of the verticle.

The tearDown is straightforward and just closes the Vert.x instance. It automatically un-deploys the verticles:

@AfterpublicvoidtearDown(TestContext context){
  vertx.close(context.asyncAssertSuccess());
}

Finally, our single test is:

@TestpublicvoidtestMyApplication(TestContext context){
  final Async async = context.async();
  vertx.createHttpClient().getNow(port, "localhost", "/", response -> {
    response.handler(body -> {
      context.assertTrue(body.toString().contains("Hello"));
      async.complete();
    });
  });
 }
It is only checking that the application replies "Hello" when we emit a HTTP request on `/`. Let's now try to implement some unit tests checkin that our web application and the REST API behave as expected. Let's start by checking that the `index.html` page is correctly served. This test is very similar to the previous one:
@TestpublicvoidcheckThatTheIndexPageIsServed(TestContext context){
  Async async = context.async();
  vertx.createHttpClient().getNow(port, "localhost", "/assets/index.html", response -> {
    context.assertEquals(response.statusCode(), 200);
    context.assertEquals(response.headers().get("content-type"), "text/html");
    response.bodyHandler(body -> {
      context.assertTrue(body.toString().contains("My Whisky Collection"));
      async.complete();
    });
  });
}

We retrieve the index.html page and check:

  1. it’s there (status code 200)
  2. it’s a HTML page (content type set to “text/html”)
  3. it has the right title (“My Whisky Collection”)

Retrieving content
As you can see, we can test the status code and the headers directly on the HTTP response, but ensure that the body is right, we need to retrieve it. This is done with a body handler that receives the complete body as parameter. Once the last check is made, we release the async by calling complete.

Ok, great, but this actually does not test our REST API. Let’s ensure that we can add a bottle to the collection. Unlike the previous tests, this one is using post to post data to the server:

@TestpublicvoidcheckThatWeCanAdd(TestContext context){
  Async async = context.async();
  final String json = Json.encodePrettily(new Whisky("Jameson", "Ireland"));
  final String length = Integer.toString(json.length());
  vertx.createHttpClient().post(port, "localhost", "/api/whiskies")
      .putHeader("content-type", "application/json")
      .putHeader("content-length", length)
      .handler(response -> {
        context.assertEquals(response.statusCode(), 201);
        context.assertTrue(response.headers().get("content-type").contains("application/json"));
        response.bodyHandler(body -> {
          final Whisky whisky = Json.decodeValue(body.toString(), Whisky.class);
          context.assertEquals(whisky.getName(), "Jameson");
          context.assertEquals(whisky.getOrigin(), "Ireland");
          context.assertNotNull(whisky.getId());
          async.complete();
        });
      })
      .write(json)
      .end();
}

First we create the content we want to add. The server consumes JSON data, so we need a JSON string. You can either write your JSON document manually, or use the Vert.x method (Json.encodePrettily) as done here. Once we have the content, we create a post request. We need to configure some headers to be correctly read by the server. First, we say that we are sending JSON data and we also set the content length. We also attach a response handler very close to the checks made in the previous test. Notice that we can rebuild our object from the JSON document send by the server using the JSON.decodeValue method. It’s very convenient as it avoids lots of boilerplate code. At this point the request is not emitted, we need to write the data and call the end() method. This is made using .write(json).end();.

The order of the methods is important. You cannot write data if you don’t have a response handler configured. Finally don’t forget to call end.

So, let’s try this. You can run the test using:

mvn clean test

We could continue writing more unit test like that, but it could become quite complex. Let’s see how we could continue our tests using integration tests.

IT hurts

Well, I think we need to make that clear, integration testing hurts. If you have experience in this area, can you remember how long did it take to setup everything correctly? I get new white hairs by just thinking about it. Why are integration tests more complicated? It’s basically because of the setup:

  1. We must start the application in a close to production way
  2. We must then run the tests (and configure them to hit the right application instance)
  3. We must stop the application

That does not sound unconquerable like that, but if you need Linux, MacOS X and Windows support, it quickly get messy. There are plenty of great frameworks easing this such as Arquillian, but let’s do it without any framework to understand how it works.

We need a battle plan

Before rushing into the complex configuration, let’s think a minute about the tasks:

Step 1 - Reserve a free port We need to get a free port on which the application can listen, and we need to inject this port in our integration tests.

Step 2 - Generate the application configuration Once we have the free port, we need to write a JSON file configuring the application HTTP Port to this port.

Step 3 - Start the application Sounds easy right? Well it’s not that simple as we need to launch our application in a background process.

Step 4 - Execute the integration tests Finally, the central part, run the tests. But before that we should implement some integration tests. Let’s come to that later.

Step 5 - Stop the application Once the tests have been executed, regardless if there are failures or errors in the tests, we need to stop the application.

There are multiple way to implement this plan. We are going to use a generic way. It’s not necessarily the better, but can be applied almost everywhere. The approach is tight to Apache Maven. If you want to propose an alternative using Gradle or a different tool, I will be happy to add your way to the post.

Implement the plan

As said above, this section is Maven-centric, and most of the code goes in the pom.xml file. If you never used the different Maven lifecycle phases, I recommend you to look at the introduction to the Maven lifecycle.

We need to add and configure a couple of plugins. Open the pom.xml file and in the section add:

<plugin><groupId>org.codehaus.mojogroupId><artifactId>build-helper-maven-pluginartifactId><version>1.9.1version><executions><execution><id>reserve-network-portid><goals><goal>reserve-network-portgoal>goals><phase>process-sourcesphase><configuration><portNames><portName>http.portportName>portNames>configuration>execution>executions>plugin>

We use the build-helper-maven-plugin (a plugin to know if you are often using Maven) to pick up a free port. Once found, the plugin assigns the http.port variable to the picked port. We execute this plugin early in the build (during the process-sources phase), so we can use the http.port variable in the other plugin. This was for the first step.

Two actions are required for the second step. First, in the pom.xml file, just below the opening tag, add:

<testResources><testResource><directory>src/test/resourcesdirectory><filtering>truefiltering>testResource>testResources>

This instructs Maven to filter resources from the src/test/resources directory. Filter means replacing placeholders by actual values. That’s exactly what we need as we now have the http.port variable. So create the src/test/resources/my-it-config.json file with the following content:

{
  "http.port": ${http.port}
}

This configuration file is similar to the one we did in previous posts. The only difference is the ${http.port} which is the (default) Maven syntax for filtering. So, when Maven is going to process or file it will replace ${http.port} by the selected port. That’s all for the second step.

The step 3 and 5 are a bit more tricky. We should start and stop the application. We are going to use the maven-antrun-plugin to achieve this. In the pom.xml file, below the build-helper-maven-plugin, add:

<plugin><artifactId>maven-antrun-pluginartifactId><version>1.8version><executions><execution><id>start-vertx-appid><phase>pre-integration-testphase><goals><goal>rungoal>goals><configuration><target><execexecutable="${java.home}/bin/java"dir="${project.build.directory}"spawn="true"><argvalue="-jar"/><argvalue="${project.artifactId}-${project.version}-fat.jar"/><argvalue="-conf"/><argvalue="${project.build.directory}/test-classes/my-it-config.json"/>exec>target>configuration>execution><execution><id>stop-vertx-appid><phase>post-integration-testphase><goals><goal>rungoal>goals><configuration><target><execexecutable="bash"dir="${project.build.directory}"spawn="false"><argvalue="-c"/><argvalue="ps ax | grep -Ei '[\-]DtestPort=${http.port}\s+\-jar\s+${project.artifactId}' | awk 'NR==1{print $1}' | xargs kill -SIGTERM"/>exec>target>configuration>execution>executions>plugin>

That’s a huge piece of XML, isn’t it ? We configure two executions of the plugin. The first one, happening in the pre-integration-test phase, executes a set of bash command to start the application. It basically executes:

java -jar my-first-app-1.0-SNAPSHOT-fat.jar -conf .../my-it-config.json

Is the fatjar created ?
The fat jar embedding our application is created in the package phase, preceding the pre-integration-test, so yes, the fat jar is created.

As mentioned above, we launch the application as we would in a production environment.

Once, the integration tests are executed (step 4 we didn’t look at it yet), we need to stop the application (so in the the post-integration-test phase). To close the application, we are going to invoke some shell magic command to find our process in with the ps command and send the SIGTERM signal. It is equivalent to:

ps
.... -> find your process id
kill your_process_id -SIGTERM

And Windows ?
I mentioned it above, we want Windows to be supported and these commands are not going to work on Windows. Don’t worry, Windows configuration is below….

We should now do the fourth step we (silently) skipped. To execute our integration tests, we use the maven-failsafe-plugin. Add the following plugin configuration to your pom.xml file:

<plugin><groupId>org.apache.maven.pluginsgroupId><artifactId>maven-failsafe-pluginartifactId><version>2.18.1version><executions><execution><goals><goal>integration-testgoal><goal>verifygoal>goals><configuration><systemProperties><http.port>${http.port}http.port>systemProperties>configuration>execution>executions>plugin>

As you can see, we pass the http.port property as a system variable, so our tests are able to connect on the right port.

That’s all! Wow… Let’s try this (for windows users, you will need to be patient or to jump to the last section).

mvn clean verify

We should not use mvn integration-test because the application would still be running. The verify phase is after the post-integration-test phase and will analyse the integration-tests results. Build failures because of integration tests failed assertions are reported in this phase.

Hey, we don’t have integration tests !

And that’s right, we set up everything, but we don’t have a single integration test. To ease the implementation, let’s use two libraries: AssertJ and Rest-Assured.

AssertJ proposes a set of assertions that you can chain and use fluently. Rest Assured is a framework to test REST API.

In the pom.xml file, add the two following dependencies just before :

<dependency><groupId>com.jayway.restassuredgroupId><artifactId>rest-assuredartifactId><version>2.4.0version><scope>testscope>dependency><dependency><groupId>org.assertjgroupId><artifactId>assertj-coreartifactId><version>2.0.0version><scope>testscope>dependency>

Then, create the src/test/java/io/vertx/blog/first/MyRestIT.java file. Unlike unit test, integration test ends with IT. It’s a convention from the Failsafe plugin to distinguish unit (starting or ending with Test) from integration tests (starting or ending with IT). In the created file add:

package io.vertx.blog.first;

import com.jayway.restassured.RestAssured;
import org.junit.AfterClass;
import org.junit.BeforeClass;

publicclassMyRestIT{

  @BeforeClasspublicstaticvoidconfigureRestAssured(){
    RestAssured.baseURI = "http://localhost";
    RestAssured.port = Integer.getInteger("http.port", 8080);
  }

  @AfterClasspublicstaticvoidunconfigureRestAssured(){
    RestAssured.reset();
  }
}

The methods annotated with @BeforeClass and @AfterClass are invoked once before / after all tests of the class. Here, we just retrieve the http port (passed as a system property) and we configure REST Assured.

Am I ready to serve ?
You may need to wait in the configureRestAssured method that the HTTP server has been started. We recommend the awaitility test framework to check that the request can be served. It would fail the test if the server does not start.

It’s now time to implement a real test. Let’s check we can retrieve an individual product:

@TestpublicvoidcheckThatWeCanRetrieveIndividualProduct(){
  // Get the list of bottles, ensure it's a success and extract the first id.finalint id = get("/api/whiskies").then()
      .assertThat()
      .statusCode(200)
      .extract()
      .jsonPath().getInt("find { it.name=='Bowmore 15 Years Laimrig' }.id");
  // Now get the individual resource and check the content
  get("/api/whiskies/" + id).then()
      .assertThat()
      .statusCode(200)
      .body("name", equalTo("Bowmore 15 Years Laimrig"))
      .body("origin", equalTo("Scotland, Islay"))
      .body("id", equalTo(id));
}

Here you can appreciate the power and expressiveness of Rest Assured. We retrieve the list of product, ensure the response is correct, and extract the id of a specific bottle using a JSON (Groovy) Path expression.

Then, we try to retrieve the metadata of this individual product, and check the result.

Let’s now implement a more sophisticated scenario. Let’s add and delete a product:

@TestpublicvoidcheckWeCanAddAndDeleteAProduct(){
  // Create a new bottle and retrieve the result (as a Whisky instance).
  Whisky whisky = given()
      .body("{\"name\":\"Jameson\", \"origin\":\"Ireland\"}").request().post("/api/whiskies").thenReturn().as(Whisky.class);
  assertThat(whisky.getName()).isEqualToIgnoringCase("Jameson");
  assertThat(whisky.getOrigin()).isEqualToIgnoringCase("Ireland");
  assertThat(whisky.getId()).isNotZero();
  // Check that it has created an individual resource, and check the content.
  get("/api/whiskies/" + whisky.getId()).then()
      .assertThat()
      .statusCode(200)
      .body("name", equalTo("Jameson"))
      .body("origin", equalTo("Ireland"))
      .body("id", equalTo(whisky.getId()));
  // Delete the bottle
  delete("/api/whiskies/" + whisky.getId()).then().assertThat().statusCode(204);
  // Check that the resource is not available anymore
  get("/api/whiskies/" + whisky.getId()).then()
      .assertThat()
      .statusCode(404);
}
So, now we have integration tests let's try:
mvn clean verify

Simple no? Well, simple once the setup is done right… You can continue implementing other integration tests to be sure that everything behave as you expect.

Dear Windows users…

This section is the bonus part for Windows user, or people wanting to run their integration tests on Windows machine too. The command we execute to stop the application is not going to work on Windows. Luckily, it’s possible to extend the pom.xml with a profile executed on Windows.

In your pom.xml, just after , add:

<profiles><profile><id>windowsid><activation><os><family>windowsfamily>os>activation><build><plugins><plugin><artifactId>maven-antrun-pluginartifactId><version>1.8version><executions><execution><id>stop-vertx-appid><phase>post-integration-testphase><goals><goal>rungoal>goals><configuration><target><execexecutable="wmic"dir="${project.build.directory}"spawn="false"><argvalue="process"/><argvalue="where"/><argvalue="CommandLine like '%${project.artifactId}%' and not name='wmic.exe'"/><argvalue="delete"/>exec>target>configuration>execution>executions>plugin>plugins>build>profile>profiles>

This profile replaces the actions described above to stop the application with a version working on windows. The profile is automatically enabled on Windows. As on others operating systems, execute with:

mvn clean verify

Conclusion

Wow, what a trip ! We are done… In this post we have seen how we can gain confidence in Vert.x applications by implementing both unit and integration tests. Unit tests, thanks to vert.x unit, are able to check the asynchronous aspect of Vert.x application, but could be complex for large scenarios. Thanks to Rest Assured and AssertJ, integration tests are dead simple to write… but the setup is not straightforward. This post have shown how it can be configured easily. Obviously, you could also use AssertJ and Rest Assured in your unit tests.

In the next post, we replace the in memory backend with a database, and use asynchronous integration with this database.

Stay Tuned & Happy Coding !

Vert.x3 real time web apps

$
0
0

One of the interesting features of Vert.x is the SockJS event bus bridge. This piece of software allows external applications to communicate with Vert.x event bus using Websockets and if your browser does not support it then it gracefully degrades to pooling AJAX calls.

WebSockets bring a new level of interaction to the web, they really bring real time to web applications due to the fact that its communication model is bi-directional in contrast to the traditional HTTP model where a client can initiate a data request to a server but not the other way around.

In this small post I will demonstrate how you can create a simple collaborative drawing app. The idea is simple, all users that open the app will be be presented with a empty canvas and what they draw or is drawn on other canvas is shared in real time on their screen.

For the sake of simplicity and making this post light there is no security involved so, everyone is free to listen to what is being drawn, however the external application has limited read write access to a single address on Vert.x event bus, ensuring that other services running on the cluster will not be exposed.

This is what you should expect to see:

Screencast

Bootstrap a project

If you followed the previous series on Vert.x development, you saw that Java and Maven were the main topic, since Vert.x is polyglot I will focus on JavaScript and NPM as my programming language and package management tool.

With NPM start by creating a package.json, in order to do this we should run:

npm init

This will present a selection of questions and in the end you should have a basic package.json file. This configuration is very basic so you need to add a dependency to Vert.x so you can run the application. You can add it to the dependencies property and it should look more or less like this:

{
  "name": "draw",
  "private": true,
  "dependencies": {
    "vertx3-full": "3.0.0-1"
  },
  "scripts": {
    "start": "vertx run server.js"
  },
  "version": "1.0.0",
  "main": "server.js",
  "devDependencies": {},
  "author": "",
  "license": "ISC",
  "description": "A Real Time Drawing App"
}

If you do not know why there is the dependency on vertx3-full or why the added scripts property please check the older blog post about it.

Project Structure

This post has no preference over project structure, so if you do not agree with the structure used here feel free to use what you feel best. For this example I will keep it to:

├── package.json├── server.js└── webroot
  ├── assets
  │   └── js
  │     ├── script.js│     └── vertxbus.js└── index.html3 directories, 5 files

As you can imagine server.js will be our Vert.x application and everything under webroot will be the client application.

The client application is not really Vert.x specific and could in theory be used by any other framework so I will go lightly over its code.

Client Application

Our application main entry point is as one can expect index.html. In the index file define the following HTML:

<html><head><metacharset="utf-8"/><title>Real time drawing Apptitle>head><body><canvasid="paper"width="1900"height="1000">
  Your browser needs to support canvas for this to work!
canvas><scriptsrc="http://code.jquery.com/jquery-1.8.0.min.js">script><scriptsrc="//cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js">script><scriptsrc='assets/js/vertxbus.js'>script><scriptsrc="assets/js/script.js">script>body>html>

As I previously wrote, the idea is to keep it as simple as possible so it is all about having a canvas element and a application main script script.js. All the rest are files served by CDNs that provide common web application libraries such as jQuery, HTML5 shim for older browsers, SockJS client and vertxbus bridge.

The main code is on script.js file:

$(function(){

  // This demo depends on the canvas elementif (!('getContext'indocument.createElement('canvas'))) {
    alert('Sorry, it looks like your browser does not support canvas!');
    returnfalse;
  }

  var doc = $(document),
    canvas = $('#paper'),
    ctx = canvas[0].getContext('2d');

  // Generate an unique IDvar id = Math.round($.now() * Math.random());

  // A flag for drawing activityvar drawing = false;

  var clients = {};
  // create a event bus bridge to the server that served this filevar eb = new vertx.EventBus(
      window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/eventbus');

  eb.onopen = function(){
    // listen to draw events
    eb.registerHandler('draw', function(data){
      // Is the user drawing?if (data.drawing && clients[data.id]) {

        // Draw a line on the canvas. clients[data.id] holds// the previous position of this user's mouse pointer

        drawLine(clients[data.id].x, clients[data.id].y, data.x, data.y);
      }

      // Saving the current client state
      clients[data.id] = data;
      clients[data.id].updated = $.now();
    });
  };

  var prev = {};

  canvas.on('mousedown', function(e){
    e.preventDefault();
    drawing = true;
    prev.x = e.pageX;
    prev.y = e.pageY;
  });

  doc.bind('mouseup mouseleave', function(){
    drawing = false;
  });

  var lastEmit = $.now();

  doc.on('mousemove', function(e){
    if ($.now() - lastEmit >30) {
      eb.publish('draw', {
        'x': e.pageX,
        'y': e.pageY,
        'drawing': drawing,
        'id': id
      });
      lastEmit = $.now();
    }

    // Draw a line for the current user's movement, as it is// not received in the eventbusif (drawing) {

      drawLine(prev.x, prev.y, e.pageX, e.pageY);

      prev.x = e.pageX;
      prev.y = e.pageY;
    }
  });

  // Remove inactive clients after 10 seconds of inactivity
  setInterval(function(){

    for (var ident in clients) {
      if (clients.hasOwnProperty(ident)) {
        if ($.now() - clients[ident].updated >10000) {
          // Last update was more than 10 seconds ago.// This user has probably closed the pagedelete clients[ident];
        }
      }
    }

  }, 10000);

  functiondrawLine(fromx, fromy, tox, toy){
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke();
  }

});

The most important part in this code is all the code related to eb. The variable eb is our bridge to the event bus, Start by creating a bridge using the vertx.EventBus object and define where to connect, using the details of the current window location.

Then add a onopen listener that will subscribe to the address draw on the event bus so it can listen to all messages regarding drawing and perform the drawing actions. Since listening is not enough I also add a mouse listener to the document so when it moves it publishes events to the draw address.

Note that I am using publish and not send, the reason should be obvious, I want everyone to know this users mouse movements, I am not interested on sending the events to just a single user. You can see now that if you want to have a drawing app in a one on one user basis then instead of publish() you should use send().

Server Application

The server code is quite straight forward, all you need is:

var Router = require("vertx-web-js/router");
var SockJSHandler = require("vertx-web-js/sock_js_handler");
var StaticHandler = require("vertx-web-js/static_handler");

var router = Router.router(vertx);

// Allow outbound traffic to the draw addressvar options = {
  "outboundPermitteds" : [{"address" : "draw"}],
  "inboundPermitteds" :  [{"address" : "draw"}]
};

router.route("/eventbus/*").handler(SockJSHandler.create(vertx).bridge(options).handle);

// Serve the static resources
router.route().handler(StaticHandler.create().handle);

vertx.createHttpServer().requestHandler(router.accept).listen(8080);

We start with the usual imports, we import a reference to the Router object and a couple of helper handlers SockJSHandler and StaticHandler. As their names should tell you one handler will be responsible to handle all SockJS data and the other all HTTP file serving requests.

We then add then to a router and start a HTTP server that will handle all incoming request using the handler accept function. Finally we listen on port 8080 and we are ready.

Note that there is a options object where a couple of properties are defined outbound/inbound permitted addresses. Without this configuration the external application will not be allowed to connect to the vert.x bus, in fact the default configuration of the SockJSHandler is deny all. So you must specify explicitly which address are allowed to receive messages from SockJS and which ones are allowed to send/publish to SockJS.

Now you can start your application, don’t forget to install the dependencies for the first time:

npm install

And then run the application:

npm start

If you now open 2 browser windows you will be able to draw nice pictures and see the drawing showing in “real time” on the other window, if you then draw on the second you should get the mirror effect on the first window.

Have fun!


Writing secure Vert.x Web apps

$
0
0

This is a starting guide for securing vert.x web applications. It is by no means a comprehensive guide on web application security such as OWASP. Standard rules and practices apply to vert.x apps as if they would to any other web framework.

The post will cover the items that always seem to come up on forums.

Don’t run as root

It is a common practise that your devops team member will constantly say, one shall run a service with the least amount of privileges necessary and no more. Although this might sound like folklore to less experienced developers that hit an issue when trying to run on privileged ports 80, 443, running as root solves it quickly but open a door to bigger problems. Lets look at this code:

publicclassAppextendsAbstractVerticle{
  @Overridepublicvoidstart(){

    Router router = Router.router(vertx);

    router.route().handler(StaticHandler.create(""));

    vertx.createHttpServer().requestHandler(router::accept).listen(80);
  }
}

When started with the CWD set to / (java -Dvertx.cwd=/ ...) you just created a simple file server for all your server storage. Now imagine that you want to start this application you will hit the error:

Aug 26, 20152:02:18 PM io.vertx.core.http.impl.HttpServerImpl
SEVERE: java.net.SocketException: Permission denied

So if you do now run as root it will start, however in your browser now try to navigate to: http://localhost/etc/shadow congratulations you just exposed your server loginsandpasswords!

There are several ways to run as a under privileged user, you can use iptables to forward requests to higher ports, use authbind, run behind a proxy like ngnix, etc…

Sessions

Many applications are going to deal with user sessions at some point.

Session cookies should have the SECURE and HTTPOnly flags set. This ensures that they can only be sent over HTTPS (you are using HTTPS right?) and there is no script access to the cookie client side:

Router router = Router.router(vertx);

    router.route().handler(CookieHandler.create());
    router.route().handler(SessionHandler
        .create(LocalSessionStore.create(vertx))
        .setCookieHttpOnlyFlag(true)
        .setCookieSecureFlag(true)
    );

    router.route().handler(routingContext -> {

      Session session = routingContext.session();

      Integer cnt = session.get("hitcount");
      cnt = (cnt == null ? 0 : cnt) + 1;

      session.put("hitcount", cnt);

      routingContext.response().end("Hitcount: " + cnt);
    });

    vertx.createHttpServer().requestHandler(router::accept).listen(8080);

And in this case when inspecting your browser you should see:

nocookie

Of course if you do not do that any script on your browser has the capability of reading, sniffing hijacking or tampering your sessions.

Security Headers

There are plenty of security headers that help improve security with just a couple of lines of code. There is no need to explain them here since there are good articles online that will probably do it better than me.

Here is how one could implement a couple of them:

publicclassAppextendsAbstractVerticle{

  @Overridepublicvoidstart(){

    Router router = Router.router(vertx);
    router.route().handler(ctx -> {
      ctx.response()
          // do not allow proxies to cache the data
          .putHeader("Cache-Control", "no-store, no-cache")
          // prevents Internet Explorer from MIME - sniffing a// response away from the declared content-type
          .putHeader("X-Content-Type-Options", "nosniff")
          // Strict HTTPS (for about ~6Months)
          .putHeader("Strict-Transport-Security", "max-age=" + 15768000)
          // IE8+ do not allow opening of attachments in the context of this resource
          .putHeader("X-Download-Options", "noopen")
          // enable XSS for IE
          .putHeader("X-XSS-Protection", "1; mode=block")
          // deny frames
          .putHeader("X-FRAME-OPTIONS", "DENY");
    });

    vertx.createHttpServer().requestHandler(router::accept).listen(8080);
  }
}

Cross-Site Request Forgery (CSRF) Protection

Vert.x web provides CSRF protection using an included handler. To enable CSRF protections you need to add it to your router as you would add any other handler:

publicclassAppextendsAbstractVerticle{

  @Overridepublicvoidstart(){

    Router router = Router.router(vertx);

    router.route().handler(CookieHandler.create());
    router.route().handler(SessionHandler
        .create(LocalSessionStore.create(vertx))
        .setCookieSecureFlag(true)
    );
    router.route().handler(CSRFHandler.create("not a good secret"));

    router.route().handler(ctx -> {
      ...
    });

The handler adds a CSRF token to requests which mutate state. In order change the state a (XSRF-TOKEN) cookie is set with a unique token, that is expected to be sent back in a (X-XSRF-TOKEN) header.

Limit uploads

When dealing with uploads always define a upper bound, otherwise you will be vulnerable to DDoS attacks. For example lets say that you have the following code:

publicclassAppextendsAbstractVerticle{

  @Overridepublicvoidstart(){

    Router router = Router.router(vertx);

    router.route().handler(BodyHandler.create());

    router.route().handler(ctx -> {
      ...

Now a bad intentioned person could generate a random file with 1GB of trash:

dd if=/dev/urandom of=ddos bs=1G count=1

And then upload it to your server:

curl --data-binary "@ddos" -H "Content-Type: application/octet-stream" -X POST http://localhost:8080/

Your application will happily try to handle this until one of 2 things happens, it will run out of disk space or memory. In order to mitigate these kind of attacks always specify the maximum allowed upload size:

publicclassAppextendsAbstractVerticle{

  privatestaticfinalint KB = 1024;
  privatestaticfinalint MB = 1024 * KB;

  @Overridepublicvoidstart(){

    Router router = Router.router(vertx);
    router.route().handler(BodyHandler.create().setBodyLimit(50 * MB));

Final Words

Although this is just a small list of things you should remember when implementing your application there are more comprehensive checklists to check:

Contract Driven REST Services with Vert.x3

$
0
0

We see a new trend in development where we are shifting from developing applications to develop APIs. More and more we see services being offered as REST APIs that we are allowed to consume and we already see this trend from the big names in the industry, e.g.: Facebook, Wikipedia, Amazon, Twitter, Google and Reddit they all offer APIs.

Of course making an REST API using Vert.x is quite simple, just use Vert.x Web and you can start writing your API in seconds, however an API without documentation is not an API since no developer will know how to use it. However this is one of the most sensitive issues to tackle in software development, nobody likes to write documentation. However, in the REST age where REST-based web-services are ubiquitous, documentation for public web-services is a necessity. There are a lot of tools out there, two of the most popular are without a doubt:

Both frameworks have a large ecosystem of tools and tooling around but they tackle the documentation from two different perspectives. While Swagger is purely a documentation tool it tackles the problem from bottom up and RAML does document top down. They both rely on a document (JSON for Swagger, YAML for RAML).

I’ll now go over building a simple Hello World API, document it and test it. For this example I’ll choose RAML since it feels more natural to the way we code with Vert.x Web.

Define the Hello World API

We need a contract and as with any other development we need some specification, You can learn about RAML in its website and quickly see how easy it is to get started. So we start with the following specification:

#%RAML 0.8title: Hello world REST API
baseUri:http://localhost:8080/version: v1
/hello:  get:    responses:      200:        body:
          application/json:            schema: |
              { "$schema": "http://json-schema.org/schema",
                "type": "object",
                "description": "Hello World Greeting",
                "properties": {
                  "greeting":  { "type": "string" }
                },
                "required": [ "greeting" ]
              }

So if you didn’t understood why I named RAML as a top down documentation tool, I think it becomes clear now. So there are some basic definition on the top of the file like, title, baseUri and version which should be self explanatory.

And then we start with the API documentation, so we specify that at the URL/hello using the HTTP verb GET you are expected to get a response with status code 200 and the body of the response should have content type application/json. This is a very minimal document, one could go over and specify the json schema for the response, input values, etc…, however lets just keep it simple for this example.

IDE ?
if you do not like to write yaml in your editor you can always use the API Designer which gives you instant feedback on your API document and provides a testing platform
.

Implement the API

So you got your contract, time to implement it, this is a very simple API so I’ll jump to the code immediately:

publicclassAppextendsAbstractVerticle{
  @Overridepublicvoidstart(){
    Router router = Router.router(vertx);

    router.get("/hello").handler(rc -> {
      rc.response()
          .putHeader("content-type", "application/json")
          .end(new JsonObject().put("greeting", "Hello World!").encode());
    });

    vertx.createHttpServer().requestHandler(router::accept).listen(8080);
  }
}

As you can see the code resembles the contract document, when there is a GET request to /hello we send to the client a empty JSON document {}.

Are we done?

The answer is NO!!! how can we be sure that our implementation does comply to the contract? We need to test. As I wrote before there is no specific support for Vert.x from RAML or other tools however in this case it is not a problem we can still test our code without having the need to implement a test framework from the ground up.

Testing our contract

The initial step is to setup a test, this should be trivial we are using Java (although we could test any of Vert.x supported languages using the same technique). We create a JUnit unit test.

JUnit ? ! For this example I will be using JUnit instead of Vert.x Test mostly to let you know that Vert.x isn’t an opinionated framework, so you are free to choose the tool that best fits you.
publicclassAPITest{

  @BeforeClasspublicstaticvoidbootApp(){
    Runner.run(App.class);
  }

  @TestpublicvoidtestHelloEndpoint(){
  }
}

So at this moment you have a simple test, I’ll share the code of the runner class (basically it just instantiates a Vertx instance and load the verticle we just implemented above) and has a empty test testHelloEndpoint.

Load the API definition into the test

publicclassAPITest{

  privatestaticfinal RamlDefinition api = RamlLoaders.fromClasspath()
        .load("/api/hello.raml")
        .assumingBaseUri("http://localhost:8080/");

  private CheckingWebTarget checking;

  ...
}

So the first step is to load the API definition into our test and have a reference to a CheckingWebTarget object. The checking object is where you can perform assertions, but to do this we need some client make REST calls in order to test.

Create a REST client

There are many options for this, you could use JAX-RS, RestAssured, RestEasy, etc… so I’ll pick RestEasy for now:

publicclassAPITest{

  privatestaticfinal RamlDefinition api = RamlLoaders.fromClasspath()
      .load("/api/hello.raml")
      .assumingBaseUri("http://localhost:8080/");

  private ResteasyClient client = new ResteasyClientBuilder().build();
  private CheckingWebTarget checking;

  @BeforeClasspublicstaticvoidbootApp(){
    Runner.run(App.class);
  }

  @BeforepublicvoidcreateTarget(){
    checking = api.createWebTarget(client.target("http://localhost:8080"));
  }

  ...
}

Implement the test

All of the boilerplate code is in place and if you look at the previous section you will see that it wasn’t that bad, just a few lines and you loaded the RAML contract, created a REST client and started up your application and all this under ~10 lines of code.

So lets finish and implement the verification of the contract:

publicclassAPITest{
  ...

  @TestpublicvoidtestHelloEndpoint(){
    checking.path("/hello").request().get();
    Assert.assertThat(checking.getLastReport(), RamlMatchers.hasNoViolations());
  }
}

Once you run your tests, you will see:

13:09:28.200 [main] DEBUG o.a.h.i.conn.DefaultClientConnection - Sending request: GET /hello HTTP/1.1
13:09:28.201 [main] DEBUG org.apache.http.wire -  >>"GET /hello HTTP/1.1[\r][\n]"
13:09:28.202 [main] DEBUG org.apache.http.wire -  >>"Accept-Encoding: gzip, deflate[\r][\n]"
13:09:28.202 [main] DEBUG org.apache.http.wire -  >>"Host: localhost:8080[\r][\n]"
13:09:28.202 [main] DEBUG org.apache.http.wire -  >>"Connection: Keep-Alive[\r][\n]"
13:09:28.202 [main] DEBUG org.apache.http.wire -  >>"[\r][\n]"
13:09:28.202 [main] DEBUG org.apache.http.headers - >> GET /hello HTTP/1.1
13:09:28.202 [main] DEBUG org.apache.http.headers - >> Accept-Encoding: gzip, deflate
13:09:28.203 [main] DEBUG org.apache.http.headers - >> Host: localhost:8080
13:09:28.203 [main] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
13:09:28.412 [main] DEBUG org.apache.http.wire -  <<"HTTP/1.1200OK[\r][\n]"13:09:28.413 [main] DEBUGorg.apache.http.wire-<<"content-type:application/json[\r][\n]"13:09:28.413 [main] DEBUGorg.apache.http.wire-<<"Content-Length:2[\r][\n]"13:09:28.413 [main] DEBUGorg.apache.http.wire-<<"[\r][\n]"13:09:28.414 [main] DEBUGo.a.h.i.conn.DefaultClientConnection-Receivingresponse:HTTP/1.1200OK13:09:28.414 [main] DEBUGorg.apache.http.headers-<<HTTP/1.1200OK13:09:28.415 [main] DEBUGorg.apache.http.headers-<<content-type:application/json13:09:28.415 [main] DEBUGorg.apache.http.headers-<<Content-Length:213:09:28.429 [main] DEBUGorg.apache.http.wire-<<"{}"Testsrun:1, Failures:0, Errors:0, Skipped:0, Timeelapsed:1.076secResults:Testsrun:1, Failures:0, Errors:0, Skipped:0

And we are done, we now have a API that follow the contract, you can now keep developing your API and implementation and have a test driven approach to be sure that the contract is not broken.

Next steps

Until now you have learn how to integrate RAML into Vert.x and CI, however the users of your API will not be able to know much about the API yet since its documentation is not publicly available. So lets publish online the documentation of your API, of course if your API is private you do not need to follow these steps.

In order to do this all we need it to include in our application the RAML console, the fastest way to do this is just download a release to src/main/resouces/webroot and in the original application [Vert.x Router] we add a Static Content Handler to serve the console files. Your application source code should look like this:

publicclassAppextendsAbstractVerticle{
  @Overridepublicvoidstart(){
    Router router = Router.router(vertx);

    router.get("/hello").handler(rc -> {
      rc.response()
          .putHeader("content-type", "application/json")
          .end(new JsonObject().put("greeting", "Hello World!").encode());
    });

    // optionally enable the web console so users can play with your API// online from their web browsers
    router.route().handler(StaticHandler.create());

    vertx.createHttpServer().requestHandler(router::accept).listen(8080);
  }
}

Once you start you application open a browser pointing at the console. Once you do that you should be presented with something similar to this:

apiconsole

Article source code

You can get the full source code for this article here.

Vert.x 3.1.0 is released !

$
0
0

I’m pleased to announce the release of Vert.x 3.1!

Some of the highlights of this release include:

  • Vertx-sync is a set of utilities that allow you to perform asynchronous operations and receive events in a synchronous way, but without blocking kernel threads.

  • Vertx-stomp is an implementation of a STOMP server and client. You can use the STOMP server with other clients and use the STOMP client with other servers. The server and the client supports the version 1.0, 1.1 and 1.2 of the STOMP protocol. The STOMP server can also be used as a bridge with the vert.x event bus.

  • Vertx-shell is a command line interface for the Vert.x runtime available from regular terminals using different protocols.

  • Re-implementation of the Starter class and related functionality. And now redeploy is back!

Full release notes can be found here:

https://github.com/vert-x3/wiki/wiki/3.1-Release-Notes

Breaking changes here:

https://github.com/vert-x3/wiki/wiki/3.1.0---Breaking-changes

NPM for the event-bus client here:

https://www.npmjs.com/package/vertx3-eventbus-client

Many thanks to all the committers and community whose contributions made this possible.

A special thanks to the full-time team - Clement, Julien and Paulo who put in a lot of work to get this out :)

Next stop is Vert.x 3.2 which we hope to have out before Christmas.

The artifacts have been deployed to Maven Central and you can get the distribution on Bintray.

Using the asynchronous SQL client

$
0
0

Finally, back… This post is the fifth post of the introduction to vert.x blog series, after a not-that-small break. In this post we are going to see how we can use JDBC in a vert.x application, and this, using the asynchronous API provided by the vertx-jdbc-client.

Previously in the introduction to vert.x series

As it was quite some time since the last post, let’s start by refreshing our mind about the four previous posts:

  1. The first post has described how to build a vert.x application with Maven and execute unit tests.
  2. The second post has described how this application can become configurable.
  3. The third post has introduced vertx-web, and a small collection management application has been developed. This application offers a REST API used by a HTML/JavaScript frontend.
  4. The previous post has presented how you can run integration tests to ensure the behavior of your application.

In this post, back to code. The current application uses an in-memory map to store the products. It’s time to use a database. In this post we are going to use HSQL, but you can use any database providing a JDBC driver. Interactions with the database will be asynchronous and made using the vertx-jdbc-client.

The code of this post are available on this Github project, in the post-5 branch branch.

Asynchronous?

One of the vert.x characteristics is being asynchronous. With an asynchronous API, you don’t wait for a result, but you are notified when this result is ready. Just to illustrate this, let’s take a very simple example.

Let’s imagine an add method. Traditionally, you would use it like this: int r = add(1, 1). This is a synchronous API as you are waiting for the result. An asynchronous version of this API would be: add(1, 1, r -> { /* do something with the result */ }). In this version, you pass a Handler called when the result has been computed. The method does not return anything, and could be implemented as:

publicvoidadd(int a, int b, Handler resultHandler){
    int r = a + b;
    resultHandler.handle(r);
}

Just to avoid misconceptions, asynchronous API are not about threads. As we can see in the add example, there are no threads involved.

JDBC yes, but asynchronous

So, now that we have seen some basics about asynchronous API, let’s have a look to the vertx-jdbc-client. This component lets us interact with a database through a JDBC driver. These interactions are asynchronous, so when you were doing:

String sql ="SELECT * FROM Products";
ResultSet rs = stmt.executeQuery(sql);

it will be:

connection.query("SELECT * FROM Products", result -> {
        // do something with the result
});

This model is more efficient as it avoids waiting for the result. You are notified when the result is available.

Let’s now modify our application to use a database to store our products.

Some maven dependencies

The first things we need to do it to declare two new Maven dependencies in our pom.xml file:

<dependency><groupId>io.vertxgroupId><artifactId>vertx-jdbc-clientartifactId><version>3.1.0version>dependency><dependency><groupId>org.hsqldbgroupId><artifactId>hsqldbartifactId><version>2.3.3version>dependency>

The first dependency provides the vertx-jdbc-client, while the second one provide the HSQL JDBC driver. If you want to use another database, change this dependency. You will also need to change the JDBC url and JDBC driver class name later.

Initializing the JDBC client

Now that we have added these dependencies, it’s time to create our JDBC client:

In the MyFirstVerticle class, declare a new field JDBCClient jdbc;, and add the following line at the beginning of the start method:

jdbc = JDBCClient.createShared(vertx, config(), "My-Whisky-Collection");

This creates an instance of JDBC client, configured with the configuration provided to the verticle. To work correctly this configuration needs to provide:

  • url - the JDBC url such as jdbc:hsqldb:mem:db?shutdown=true
  • _driverclass - the JDBC driver class such as org.hsqldb.jdbcDriver

Ok, we have the client, we need a connection to the database. This is achieved using the jdbc.getConnection that take a Handler> as parameter. Let’s have a deeper look to this type. It’s a Handler, so it is called when the result is ready. This result is an instance of AsyncResult. AsyncResult is a structure provided by vert.x that lets us know if the operation was completed successfully or failed. In case of success, it provides the result, here an instance of SQLConnection.

When you receive an instance of AsyncResult, your code generally looks like:

if (ar.failed()) {
  System.err.println("The operation has failed...: "
      + ar.cause().getMessage());
} else {
  // Use the result:
  result = ar.result();
 }

So, let’s go back to our SQLConnection. We need to retrieve it, and then start the rest of the application. This changes how we start the application, as it will become asynchronous. So, if we divide our startup sequence into small chunks it would be something like:

startBackend(
 (connection) -> createSomeData(connection,
     (nothing) -> startWebApp(
         (http) -> completeStartup(http, fut)
     ), fut
 ), fut);

with:

  1. startBackend - retrieves a SQLConnection and then calls the next step
  2. createSomeData - initializes the database and inserts some data. When done, it calls the next step
  3. startWebApp - starts our web application
  4. completeStartup - finalizes our start sequence

fut is the completion future passed by vert.x that let us report when we are started, or if an issue has been encountered while starting.

Let’s have a look to startBackend:

private void startBackend(Handler<AsyncResult<SQLConnection>> next, Future<Void> fut) {
    jdbc.getConnection(ar -> {
      if (ar.failed()) {
        fut.fail(ar.cause());
      } else {
        next.handle(Future.succeededFuture(ar.result()));
      }
    });
  }

This method retrieves a SQLConnection, check whether this operation succeeded. If so, it calls the next step. In case of failure, it reports it.

The other methods follow the same pattern: 1) check if the last operation has succeeded, 2) do the task, 3) call the next step.

A bit of SQL…

Our client is ready, let’s now write some SQL statements. Let’s start by the createSomeData method that is part of the startup sequence:

private void createSomeData(AsyncResult<SQLConnection>result,
    Handler<AsyncResult<Void>> next, Future<Void> fut) {
    if (result.failed()) {
      fut.fail(result.cause());
    } else {
      SQLConnection connection = result.result();
      connection.execute(
          "CREATE TABLE IF NOT EXISTS Whisky (id INTEGER IDENTITY, name varchar(100), " +
          "origin varchar(100))",
          ar -> {
            if (ar.failed()) {
              fut.fail(ar.cause());
              connection.close();
              return;
            }
            connection.query("SELECT * FROM Whisky", select -> {
              if (select.failed()) {
                fut.fail(ar.cause());
                connection.close();
                return;
              }
              if (select.result().getNumRows() == 0) {
                insert(
                    new Whisky("Bowmore 15 Years Laimrig", "Scotland, Islay"),
                    connection,
                    (v) -> insert(new Whisky("Talisker 57° North", "Scotland, Island"),
                        connection,
                        (r) -> {
                          next.handle(Future.<Void>succeededFuture());
                          connection.close();
                        }));                                                    
              } else {
                next.handle(Future.<Void>succeededFuture());
                connection.close();
              }
            });
          });
    }
  }
This method checks that the `SQLConnection` is available and then start executing some SQL statements. First, it creates the tables if there are not there yet. As you can see, the method called is structured as follows:
connection.execute(
    SQL statement,
    handler called when the statement has been executed
)

The handler receives an AsyncResult, i.e. a notification of the completion without an actual result.

Closing connection
Don’t forget to close the SQL connection when you are done. The connection will be given back to the connection pool and be reused.

In the code of this handler, we check whether or not the statement has been executed correctly, and if so we check to see if the table already contains some data, if not, it inserts data using the insert method:

private void insert(Whisky whisky, SQLConnection connection, Handler<AsyncResult<Whisky>> next) {
  String sql = "INSERT INTO Whisky (name, origin) VALUES ?, ?";
  connection.updateWithParams(sql,
      new JsonArray().add(whisky.getName()).add(whisky.getOrigin()),
      (ar) -> {
        if (ar.failed()) {
          next.handle(Future.failedFuture(ar.cause()));
          return;
        }
        UpdateResultresult = ar.result();
        // Build a new whisky instance with the generated id.
        Whisky w = new Whisky(result.getKeys().getInteger(0), whisky.getName(), whisky.getOrigin());
        next.handle(Future.succeededFuture(w));
      });
}

This method uses the updateWithParams method with an INSERT statement, and pass values. This approach avoids SQL injection. Once the the statement has been executed, we creates a new Whisky object with the created (auto-generated) id.

Some REST with a pinch of SQL

The method described above is part of our start sequence. But what about the method invoked by our REST API. Let’s have a look to the getAll method. This method is called by the web front-end to retrieve all stored products:

private void getAll(RoutingContext routingContext) {
    jdbc.getConnection(ar -> {
      SQLConnection connection = ar.result();
      connection.query("SELECT * FROM Whisky", result -> {
        List<Whisky> whiskies = result.result().getRows().stream().map(Whisky::new).collect(Collectors.toList());
        routingContext.response()
            .putHeader("content-type", "application/json; charset=utf-8")
            .end(Json.encodePrettily(whiskies));
        connection.close(); // Close the connection        
      });
    });
  }

This method gets a SQLConnection, and then issue a query. Once the result has been retrieved it writes the HTTP response as before. The getOne, deleteOne, updateOne and addOne methods follow the same pattern. Notice that the connection can be closed after the response has been written.

Let’s have a look to the result provided to the handler passed to the query method. It gets a ResultSet, which contains the query result. Each row is a JsonObject, so if your data object has a constructor taking a JsonObject as unique argument, creating there objects is straightforward.

Test, test, and test again

We need to slightly update our tests to configure the JDBCClient. In the MyFirstVertilceTest class, change the DeploymentOption object created in the setUp method to be:

DeploymentOptions options = new DeploymentOptions()
        .setConfig(new JsonObject()
            .put("http.port", port)
            .put("url", "jdbc:hsqldb:mem:test?shutdown=true")
            .put("driver_class", "org.hsqldb.jdbcDriver")
        );

In addition to the http.port, we also put the JDBC url and the class of the JDBC driver. We use an in-memory database for tests.

The same modification needs to be done in the src/test/resources/my-it-config.json file:

{
  "http.port": ${http.port},
  "url": "jdbc:hsqldb:mem:it-test?shutdown=true",
  "driver_class": "org.hsqldb.jdbcDriver"
}

The src/main/conf/my-application-conf.json file also needs to be updated, not for the tests, but to run the application:

{
  "http.port" : 8082,
  "url": "jdbc:hsqldb:file:db/whiskies",
  "driver_class": "org.hsqldb.jdbcDriver"}

The JDBC url is a bit different in this last file, as we store the database on the file system.

Show time!

Let’s now build our application:

mvn clean package

As we didn’t change the API (neither the public java one nor the REST), test should run smoothly.

Then launch the application with:

java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar -conf src/main/conf/my-application-conf.json

Open your browser to http://localhost:8082/assets/index.html, and you should see the application using the database. This time the products are stored in a database persisted on the file system. So, if we stop and restart the application, the data is restored.

Conclusion

In this post, we saw how you can use JDBC database with vert.x, and thus without too much burden. You may have been surprised by the asynchronous development model, but once you start using it, it’s hard to come back.

In the next post, we see how the same application can use mongoDB instead of HSQL.

Stay tuned, and happy coding !

Vert.x ES6 back to the future

$
0
0

On October 21th, 2015 we all rejoiced with the return from the past of Marty McFly with his flying car and so on, however in the Vert.x world we were quite sad that the JavaScript support we have was still using a technology released in December 2009. The support for ES5 is not something that we Vert.x team controls but something that is inherited from running on top of Nashorn.

With all these nostalgic thoughts on my mind I’ve decided to bring us back to the future and by future I mean, lets start using a modern JavaScript, or more correctly, lets start using ECMAScript 6.

It turned out to be quite simple to achieve this so I’ll pick the hello world example and write it in ES6 just to show how you can port your code to ES6 and still use the current Vert.x APIs. Note that Vert.x internals still are ES5 and have not been touched or modified to support any of ES6 features.

main

Traditionally your main.js file would reside in the root of your module (this is where NPM will look for it by default); however as we are going to transpile to ES5 you’ll want to put your index file in /src/main.js.

However, because we are transpiling to ES5, your package.json‘s main block should point to the transpiled index.js file in the /lib directory.

{
  "name": "vertx-es6",
  "version": "0.0.1",
  "private": true,

  "main": "lib/main.js",

  "scripts": {
    "build": "rm -Rf lib && ./node_modules/.bin/babel --out-dir lib src",
    "start": "./node_modules/.bin/vertx run lib/main.js"},

  "dependencies": {
    "vertx3-full": "3.1.0",
    "babel-cli": "6.2.0",
    "babel-preset-es2015": "6.1.18"}
}

As you can see, the main idea is to invoke the transpiler (Babel) when we are building our project, and run it using the generated files. This is slightly equivalent to a compilation process you would have using compiled language.

.npmignore

If you’re planning to deploy your package to npm either local or private you should be aware that npm will exclude anything listed on your .gitignore since we should ignore the generated code from git it need to inform npm to ignore that rule and keep the lib directory. The .gitignore should be something like:

/lib
/node_modules

And the .npmignore:

/.gitignore

Hello fat arrows and let keywords

So all the heavy work has been done, in order to create our hello world we just need to code some ES6 in our src/main.js file:

var Router = require("vertx-web-js/router");
var server = vertx.createHttpServer();

var router = Router.router(vertx);

router.get("/").handler((ctx) => {

    let response = ctx.response();
    response.putHeader("content-type", "text/plain");

    response.end("Hello ES6 World!");
});

server.requestHandler(router.accept).listen(8080);

As you can see we’re using fat arrows instead of writing a function closure and scoped variables using let keyword. If you now compile your project:

npm run build

And then start it:

npm start

You have your first back to the future ES6 verticle!

Combine vert.x and mongo to build a giant

$
0
0

This blog post is part of the introduction to vert.x series. Last time, we have seen how we can use the vertx-jdbc-client to connect to a database using a JDBC driver. In this post, we are going to replace this JDBC client by the vertx-mongo-client, and thus connect to a Mongo database.

You don’t understand the title, check the mongoDB website.

But before going further, let’s recap.

Previously in ‘introduction to vert.x’

  1. The first post has described how to build a vert.x application with Maven and execute unit tests.
  2. The second post has described how this application can become configurable.
  3. The third post has introduced vertx-web, and a small collection management application has been developed. This application offers a REST API used by a HTML/JavaScript frontend.
  4. The fourth post has presented how you can run integration tests to ensure the behavior of your application.
  5. The last post has presented how you can interact with a JDBC database using the vertx-jdbc-client.

This post shows another client that lets you use MongoDB in a vert.x application. This client provides an vert.x API to access asynchronously to the Mongo database. We won’t compare whether or not JDBC is superior to Mongo, they have both pros and cons, and you should use the one that meet your requirements. Vert.x lets you choose, that’s the point.

The vertx-mongo-client documentation is available here.

The code developed in this blog post is available in the branch post-6. Our starting point is the code from the post-5 branch.

Asynchronous data access

One of the vert.x characteristics is being asynchronous. With an asynchronous API, you don’t wait for a result, but you are notified when this result is ready. Thanks to vert.x, this notification happens in the same thread (understand event loop) as the initial request:

Asynchronous data access

Your code (on the left) is going to invoke the mongo client and pass a callback that will be invoked when the result is available. The invocation to the mongo client is non blocking and returns immediately. The client is dealing with the mongo database and when the result has been computed / retrieved, it invokes the callback in the same event loop as the request.

This model is particularly powerful as it avoids the synchronization pitfalls. Indeed, your code is only called by a single thread, no need to synchronize anything.

As with every Maven project….

… we need to update the pom.xml file first.

In the pom.xml file, replace the vertx-jdbc-client by the vertx-mongo-client:

<dependency><groupId>io.vertxgroupId><artifactId>vertx-mongo-clientartifactId><version>3.1.0version>dependency>

Unlike JDBC where we were instantiating a database on the fly, here we need to explicitly starts a MongoDB server. In order to launch a Mongo server in our test, we are going to add another dependency:

<dependency><groupId>de.flapdoodle.embedgroupId><artifactId>de.flapdoodle.embed.mongoartifactId><version>1.50.0version><scope>testscope>dependency>

This dependency will be used in our unit tests, as it lets us start a mongo server programmatically. For our integration tests, we are going to use a Maven plugin starting and stopping the mongo server before and after our integration tests. Add this plugin to the section of your pom.xml file.

<plugin><groupId>com.github.joelittlejohn.embedmongogroupId><artifactId>embedmongo-maven-pluginartifactId><version>0.2.0version><executions><execution><id>startid><goals><goal>startgoal>goals><configuration><port>37017port>configuration>execution><execution><id>stopid><goals><goal>stopgoal>goals>execution>executions>plugin>

Notice the port we use here (37017), we will use this port later.

Enough XML for today

Now that we have updated our pom.xml file, it’s time to change our verticle. The first thing to do is to replace the jdbc client by the mongo client:

mongo = MongoClient.createShared(vertx, config());

This client is configured with the configuration given to the verticle (more on this below).

Once done, we need to change how we start the application. With the mongo client, no need to acquire a connection, it handles this internally. So our startup sequence is a bit more simple:

createSomeData(
        (nothing) -> startWebApp(
            (http) -> completeStartup(http, fut)
        ), fut);

As in the previous post, we need to insert some predefined data if the database is empty:

privatevoidcreateSomeData(Handler> next, Future fut){
    Whisky bowmore = new Whisky("Bowmore 15 Years Laimrig", "Scotland, Islay");
    Whisky talisker = new Whisky("Talisker 57° North", "Scotland, Island");
    System.out.println(bowmore.toJson());
    // Do we have data in the collection ?
    mongo.count(COLLECTION, new JsonObject(), count -> {
      if (count.succeeded()) {
        if (count.result() == 0) {
          // no whiskies, insert data
          mongo.insert(COLLECTION, bowmore.toJson(), ar -> {
            if (ar.failed()) {
              fut.fail(ar.cause());
            } else {
              mongo.insert(COLLECTION, talisker.toJson(), ar2 -> {
                if (ar2.failed()) {
                  fut.failed();
                } else {
                  next.handle(Future.succeededFuture());
                }
              });
            }
          });
        } else {
          next.handle(Future.succeededFuture());
        }
      } else {
        // report the error
        fut.fail(count.cause());
      }
    });
}

To detect whether or not the database already contains some data, we retrieve the number of documents from the whiskies collection. This is done with : mongo.count(COLLECTION, new JsonObject(), count -> {}). The second parameter is the query. In our case, we want to count all documents. This is done using new JsonObject() that would create a query accepting all documents from the collection (it’s equivalent to a SELECT * FROM ...).

Also notice the insert calls. Documents are passed as JSON object, so to insert an object, just serialize it to JSON and use mongo.insert(COLLECTION, json, completion handler).

Mongo-ize the REST handlers

Now that the application boot sequence has been migrated to mongo, it’s time to update the code handling the REST requests.

Let’s start by the getAll method that returns all stored products. To implement this, we use the find method. As we saw for the count method, we pass an empty json object to describe a query accepting all documents:

privatevoidgetAll(RoutingContext routingContext){
    mongo.find(COLLECTION, new JsonObject(), results -> {
      List objects = results.result();
      List whiskies = objects.stream().map(Whisky::new).collect(Collectors.toList());
      routingContext.response()
          .putHeader("content-type", "application/json; charset=utf-8")
          .end(Json.encodePrettily(whiskies));
    });
}

The query results are passed as a list of JSON objects. From this list we can create our product instances, and fill the HTTP response with this set.

To delete a specific document we need to select the document using its id:

privatevoiddeleteOne(RoutingContext routingContext){
    String id = routingContext.request().getParam("id");
    if (id == null) {
      routingContext.response().setStatusCode(400).end();
    } else {
      mongo.removeOne(COLLECTION, new JsonObject().put("_id", id),
          ar -> routingContext.response().setStatusCode(204).end());
    }
}

The new JsonObject().put("_id", id) describes a query selecting a single document (selected by its unique id, so it’s the equivalent to SELECT * WHERE id=...). Notice the _id which is a mongo trick to select a document by id.

Updating a document is a less trivial:

privatevoidupdateOne(RoutingContext routingContext){
    final String id = routingContext.request().getParam("id");
    JsonObject json = routingContext.getBodyAsJson();
    if (id == null || json == null) {
      routingContext.response().setStatusCode(400).end();
    } else {
      mongo.update(COLLECTION,
          new JsonObject().put("_id", id), // Select a unique document// The update syntax: {$set, the json object containing the fields to update}new JsonObject()
              .put("$set", json),
          v -> {
            if (v.failed()) {
              routingContext.response().setStatusCode(404).end();
            } else {
              routingContext.response()
                  .putHeader("content-type", "application/json; charset=utf-8")
                  .end(Json.encodePrettily(
                  new Whisky(id, json.getString("name"),
                    json.getString("origin"))));
            }
          });
    }
}

As we can see, the update method takes two JSON objects as parameter:

  1. The first one denotes the query (here we select a single document using its id).
  2. The second object expresses the change to apply to the selected document. It uses a mongo syntax. In our case, we update the document using the $set operator.

Replace document
In this code we update the document and replace only a set of fields. You can also replace the whole document using mongo.replace(...).

I definitely recommend to have a look to the MongoDB documentation, especially:

Time for configuration

Well, the code is migrated, but we still need to update the configuration. With JDBC we passed the JDBC url and the driver class in the configuration. With mongo, we need to configure the connection_string - the mongo:// url on which the application is connected, and db_name - a name for the data source.

Let’s start by the unit test. Edit the MyFirstVerticleTest file and add the following code:

privatestatic MongodProcess MONGO;
    privatestaticint MONGO_PORT = 12345;
    @BeforeClasspublicstaticvoidinitialize()throws IOException {
      MongodStarter starter = MongodStarter.getDefaultInstance();
      IMongodConfig mongodConfig = new MongodConfigBuilder()
          .version(Version.Main.PRODUCTION)
          .net(new Net(MONGO_PORT, Network.localhostIsIPv6()))
          .build();
      MongodExecutable mongodExecutable =
            starter.prepare(mongodConfig);
     MONGO = mongodExecutable.start();
    }

    @AfterClasspublicstaticvoidshutdown(){  MONGO.stop(); }

Before our tests, we start (programmatically) a mongo database on the port 12345. When all our tests have been executed, we shutdown the database.

So now that the mongo server is managed, we need to to give the right configuration to our verticle. Update the DeploymentOption instance with:

DeploymentOptions options = new DeploymentOptions()
        .setConfig(new JsonObject()
            .put("http.port", port)
            .put("db_name", "whiskies-test")
            .put("connection_string",
                "mongodb://localhost:" + MONGO_PORT)
    );

That’s all for the unit tests.

For the integration-test, we are using an externalized json file. Edit the src/test/resources/my-it-config.json with the following content:

{
      "http.port": ${http.port},
      "db_name": "whiskies-it",
      "connection_string": "mongodb://localhost:37017"
    }

Notice the port we are using for the mongo server. This port was configured in the pom.xml file.

Last but not least, we still have a configuration file to edit: the configuration you use to launch the application in production:

{
      "http.port": 8082,
      "db_name": "whiskies",
      "connection_string": "mongodb://localhost:27017"}

Here you would need to edit the localhost:27017 with the right url for your mongo server.

Some changes in the integration tests
Because mongo document id are String and not integer, we have to slightly change document selection in the integration test.

Time for a run

It’s time to package and run the application and check that everything works as expected. Let’s package the application using:

mvn clean verify

And then to launch it, start your mongo server and launch:

java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar \
  -conf src/main/conf/my-application-conf.json

If you are, like me, using docker / docker-machine for almost everything, edit the configuration file to refer to the right host (localhost for docker, the docker-machine ip if you use docker-machine) and then launch:

docker run -d -p 27017:27017 mongo
java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar \
  -conf src/main/conf/my-application-conf.json
# or
java -jar target/my-first-app-1.0-SNAPSHOT-fat.jar \
  -conf src/main/conf/my-application-conf-docker-machine.json

The application live and running

That’s all folks !

We are reaching the end of this post. We saw how you can use the vert-mongo-client to access asynchronously data stored inside a mongo database as well as inserting/updating this data. Now you have the choice between JDBC or Mongo. In addition, vert.x provides a client for Redis.

Next time, we will see how the verticle class can be split in two verticles in order to better organize your code. The interaction between the two verticles will uses services.

Stay tuned & Happy coding !

Vert.x 3.2.0 is released !

$
0
0

We are pleased to announce the release of Vert.x 3.2.0!

Some of the highlights of this release include:

The release also contains many bug fixes and a ton of improvements. Full release notes can be found here:

https://github.com/vert-x3/wiki/wiki/3.2.0---Release-Notes

Breaking changes are here:

https://github.com/vert-x3/wiki/wiki/3.2.0-Breaking-changes

The event bus client using the SockJS bridge are available from NPM, Bower and as a WebJar:

Dockers images are also available on the Docker Hub The vert.x distribution is also available from SDKMan.

Many thanks to all the committers and community whose contributions made this possible.

Next stop is Vert.x 3.3.0 which we hope to have out in March 2016.

The artifacts have been deployed to Maven Central and you can get the distribution on Bintray.


Automatic redeployment in Eclipse IDE

$
0
0

Vert.x 3.1 has (re-) introduced the redeploy feature. This blog post explains how to use this feature in the Eclipse IDE. However, you can easily adapt the content to your IDE.

How does redeploy work

How is implemented the redeploy is not as you may expect. First, the redeploy does not rely on a build tool, but is integrated in vert.x. However you can plug your build tools with the redeploy feature. This feature is offered by the io.vertx.core.Launcher class. The redeployment process is actually very simple:

  1. the application is launched in redeploy mode.
  2. it listens for file changes
  3. when a matching file is changed, it stops the application
  4. it executes the on-redeploy actions if any
  5. it restarts the application
  6. back to (2)

Initially the application is launched in redeploy mode. The application is actually launched in background, in a separated process. Vert.x listens for file changes. You give it a set of (Ant-style) patterns and every time a matching file changes, Vert.x stops the whole application and restarts it. Optionally you can configure a on-redeploy action to plug in your build tools.

To integrate this process in Eclipse (or in your IDE), you just need to configure the set of listened files, and let the Launcher class starts and stops your application.

Redeploy in Eclipse

The following screencast explains how you configure a vert.x application to be run in Eclipse and how to configure the redeploy:

To summarize the last configuration:

  • it’s a Java application configuration
  • it uses io.vertx.core.Launcher as main class
  • In the Program arguments (Arguments tab), write: run org.acme.verticle.MyMainVerticle --redeploy="src/**/*.java" --launcher-class=io.vertx.core.Launcher

Redeploy with your own Main class

Let’s now imagine that you have your own Main class, starting your application. For instance, it can be something like:

package org.acme.vertx;

import io.vertx.core.Vertx;

publicclassMain{

    publicstaticvoidmain(String[] args){
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(MyMainVerticle.class.getName());
    }

}

The redeploy feature from vert.x lets you use your own Main class:

  1. Create another Run configuration
  2. Set the Main-Class to io.vertx.core.Launcher (yes, the one from vert.x not yours)
  3. In the application parameter add: run --redeploy="src/**/*.java" --launcher-class=org.acme.vertx.Main

With this configuration, the application is launched in background using your own Main class, and will restart the application every time you change your source code (you can even change the source code of your Main class).

ECMAScript 6/7 on the JVM with TypeScript and Vert.x

$
0
0

Following the latest releases of Vert.x 3.2 and vertx-lang-typescript 1.1.0 I figured it would be a good idea to give you a couple of examples how teaming Vert.x and TypeScript helps you use ECMAScript 6 and 7 features on the JVM today.

The vertx-lang-typescript library adds TypeScript support to Vert.x 3. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. It supports the ECMAScript 6 (ECMAScript 2015, ES6) standard and also a few parts of ECMAScript 7 (ES7) already.

The library automatically compiles Vert.x verticles written in TypeScript to JavaScript and executes them on the JVM. vertx-lang-typescript also provides type definitions for the Vert.x JavaScript API. Use them in your favourite TypeScript editor/IDE to get auto-completion, API documentation and meaningful error messages. See the following screencast:

ECMAScript 6/7 and Vert.x

Below you find an example verticle written in TypeScript. Well, I left all the TypeScript-specific parts out. In fact the verticle is valid ECMAScript 6 (except for the last snippet [9] which is ECMAScript 7).

First, follow the vertx-lang-typescript README to install the library and to enable TypeScript in Vert.x. Then extract the type definitions (vertx-lang-typescript-1.1.0-typings.zip) into a new directory. Create a new file named es7verticle.ts in this directory and copy the code below into it. Finally, open your command prompt and execute

vertx run es7verticle.ts

This will run a small HTTP server that listens to requests on port 8080. If you open your browser and go to http://localhost:8080 you will see the following:

So far so good. Now let’s have a look at the code. I numbered the individual ECMAScript features used. Here’s a complete list:

  1. Use an arrow function to create a request handler (ES6)
  2. Block-scoped variables do not pollute your global namespace (ES6)
  3. Specify a default value for a function parameter (ES6)
  4. Use rest parameters to collect multiple parameters in an array (ES6)
  5. Spread the contents of an array to function parameters (ES6)
  6. Iterate over array contents using the for…of loop (ES6)
  7. template strings enable string interpolation and multi-line strings (ES6)
  8. Use classes and inheritance (ES6)
  9. Use the new exponentiation operator as a shortcut for Math.pow() (ES7)

Conclusion

The example demonstrates very well how you can use ECMAScript 6 (and parts of 7) on the JVM today. In fact, there are a lot more cool ES6 features not included in the example such as constants (const), the property shorthand or method properties.

TypeScript is so much more than just ES6. It actually has a very good static type system that allows you to make compile-time type checks. This is makes it much easier to write large Vert.x applications with many verticles. Personally I really like the support that I get from my IDE when programming TypeScript. Since vertx-lang-typescript comes with type definitions for the Vert.x JavaScript API I get auto-completion and access to the documentation right in the editor. I mostly use Sublime by the way, but I have tested it successfully with Visual Studio Code, Eclipse and Atom.

Unfortunately, the only ES7 feature that you can use at the moment with vertx-lang-typescript is the exponentiation operator. TypeScript 1.7 also supports decorators but this feature is disabled at the moment in vertx-lang-typescript because it is experimental and subject to change. I’ll keep you up to date when new features are introduced.

Alternatives

We’ve recently published a post on how to use ECMAScript 6 with Vert.x here on this blog. We used Babel, a compiler that translates ES6 to ES5.

Although this approach works well it is a bit harder to set up and use than the one presented here. First, you need to wrap your Vert.x application in a NPM package. Second, in order to run your application, you need to execute two commands. You have to compile it with npm run build and then then call npm start. With vertx-lang-typescript you only need one command. vertx-lang-typescript also allows you to embed the TypeScript verticle in a larger Vert.x application and also mix multiple languages in one project. This is not possible if you wrap everything in a NPM package.

Finally, the approach based on Babel only supports ECMAScript 6 (2015), although more features from ES7 will surely be introduced in Babel in the future. TypeScript on the other hand gives you much more features such as static typing that you will certainly find useful for any larger project.

Real-time bidding with Websockets and Vert.x

$
0
0

The expectations of users for interactivity with web applications have changed over the past few years. Users during bidding in auction no longer want to press the refresh button to check if the price has changed or the auction is over. This made bidding difficult and less fun. Instead, they expect to see the updates in application in real-time.

In this article I want to show how to create a simple application that provides real-time bidding. We will use WebSockets, SockJS and Vert.x.

We will create a front-end for fast bidding that communicates with a micro-service written in Java and based on Vert.x.

What are Websockets?

WebSocket is asynchronous, bidirectional, full-duplex protocol that provides a communication channel over a single TCP connection. With the WebSocket API it provides bidirectional communication between the website and a remote server.

WebSockets solve many problems which prevented the HTTP protocol from being suitable for use in modern, real-time applications. Workarounds like polling are no longer needed, which simplifies application architecture. WebSockets do not need to open multiple HTTP connections, they provide a reduction of unnecessary network traffic and reduce latency.

Websocket API vs SockJS

Unfortunately, WebSockets are not supported by all web browsers. However, there are libraries that provide a fallback when WebSockets are not available. One such library is SockJS. SockJS starts from trying to use the WebSocket protocol. However, if this is not possible, it uses a variety of browser-specific transport protocols. SockJS is a library designed to work in all modern browsers and in environments that do not support WebSocket protocol, for instance behind restrictive corporate proxy. SockJS provides an API similar to the standard WebSocket API.

Frontend to fast bidding

Auction web page contains the bidding form and some simple JavaScript which loads current price from the service, opens an event bus connection to the SockJS server and offers bidding. HTML source code of sample web page on which we bid might look like this:

<h3>Auction 1h3><divid="error_message">div><form>
    Current price:
    <spanid="current_price">span><div><labelfor="my_bid_value">Your offer:label><inputid="my_bid_value"type="text"><inputtype="button"onclick="bid();"value="Bid">div><div>
        Feed:
        <textareaid="feed"rows="4"cols="50"readonly>textarea>div>form>

We use the vertx-eventbus.js library to create a connection to the event bus. vertx-eventbus.js library is a part of the Vert.x distribution. vertx-eventbus.js internally uses SockJS library to send the data to the SockJS server. In the code snippet below we create an instance of the event bus. The parameter to the constructor is the URI where to connect to the event bus. Then we register the handler listening on address auction.. Each client has a possibility of registering at multiple addresses e.g. when bidding in the auction 1234, they register on the address auction.1234 etc. When data arrives in the handler, we change the current price and the bidding feed on the auction’s web page.

functionregisterHandlerForUpdateCurrentPriceAndFeed(){
    var eventBus = new EventBus('http://localhost:8080/eventbus');
    eventBus.onopen = function(){
        eventBus.registerHandler('auction.' + auction_id, function(error, message){
            document.getElementById('current_price').innerHTML = JSON.parse(message.body).price;
            document.getElementById('feed').value += 'New offer: ' + JSON.parse(message.body).price + '\n';
        });
    }
};

Any user attempt to bid generates a PATCH Ajax request to the service with information about the new offer made at auction (see bid() function). On the server side we publish this information on the event bus to all clients registered to an address. If you receive an HTTP response status code other than 200 (OK), an error message is displayed on the web page.

functionbid(){
    var newPrice = document.getElementById('my_bid_value').value;

    var xmlhttp = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
    xmlhttp.onreadystatechange = function(){
        if (xmlhttp.readyState == 4) {
            if (xmlhttp.status != 200) {
                document.getElementById('error_message').innerHTML = 'Sorry, something went wrong.';
            }
        }
    };
    xmlhttp.open("PATCH", "http://localhost:8080/api/auctions/" + auction_id);
    xmlhttp.setRequestHeader("Content-Type", "application/json");
    xmlhttp.send(JSON.stringify({price: newPrice}));
};

Auction Service

SockJS client requires the server-side part. Now we are going to create a light-weight RESTful auction service. We will send and retrieve data in JSON format. Let’s start by creating a verticle. First we need to inherit from AbstractVerticle and override the start method. Each verticle instance has a member variable called vertx. This provides access to the Vert.x core API. For example, to create an HTTP server you call the createHttpServer method on vertx instance. To tell the server to listen on port 8080 for incoming requests you use the listen method.

We need a router with routes. A router takes an HTTP request and finds the first matching route. The route can have a handler associated with it, which receives the request (e.g. route that matches path /eventbus/* is associated with eventBusHandler).

We can do something with the request, and then, end it or pass it to the next matching handler.

If you have a lot of handlers it makes sense to split them up into multiple routers.

You can do this by mounting a router at a mount point in another router (see auctionApiRouter that corresponds to /api mount point in code snippet below).

Here’s an example verticle:

publicclassAuctionServiceVerticleextendsAbstractVerticle{

    @Overridepublicvoidstart(){
        Router router = Router.router(vertx);

        router.route("/eventbus/*").handler(eventBusHandler());
        router.mountSubRouter("/api", auctionApiRouter());
        router.route().failureHandler(errorHandler());
        router.route().handler(staticHandler());

        vertx.createHttpServer().requestHandler(router::accept).listen(8080);
    }

    //…
}

Now we’ll look at things in more detail. We’ll discuss Vert.x features used in verticle: error handler, SockJS handler, body handler, shared data, static handler and routing based on method, path etc.

Error handler

As well as setting handlers to handle requests you can also set a handler for failures in routing. Failure in routing occurs if a handler throws an exception, or if a handler calls fail method. To render error pages we use error handler provides by Vert.x:

private ErrorHandler errorHandler(){
    return ErrorHandler.create();
}

SockJS handler

Vert.x provides SockJS handler with the event bus bridge which extends the server-side Vert.x event bus into client side JavaScript.

Configuring the bridge to tell it which messages should pass through is easy. You can specify which matches you want to allow for inbound and outbound traffic using the BridgeOptions. If a message is outbound, before sending it from the server to the client side JavaScript, Vert.x will look through any outbound permitted matches. In code snippet below we allow any messages from addresses starting with “auction.” and ending with digits (e.g. auction.1, auction.100 etc).

If you want to be notified when an event occurs on the bridge you can provide a handler when calling the bridge. For example, SOCKET_CREATED event will occur when a new SockJS socket is created. The event is an instance of Future. When you are finished handling the event you can complete the future with “true” to enable further processing.

To start the bridge simply call bridge method on the SockJS handler:

private SockJSHandler eventBusHandler(){
    BridgeOptions options = new BridgeOptions()
            .addOutboundPermitted(new PermittedOptions().setAddressRegex("auction\\.[0-9]+"));
    return SockJSHandler.create(vertx).bridge(options, event -> {
         if (event.type() == BridgeEventType.SOCKET_CREATED) {
            logger.info("A socket was created");
        }
        event.complete(true);
    });
}

Body handler

The BodyHandler allows you to retrieve the request body, limit the body size and to handle the file upload. Body handler should be on a matching route for any requests that require this functionality. We need BodyHandler during the bidding process (PATCH method request /auctions/ contains request body with information about a new offer made at auction). Creating a new body handler is simple:

BodyHandler.create();

If request body is in JSON format, you can get it with getBodyAsJson method.

Shared data

Shared data contains functionality that allows you to safely share the data between different applications in the same Vert.x instance or across a cluster of Vert.x instances. Shared data includes local shared maps, distributed, cluster-wide maps, asynchronous cluster-wide locks and asynchronous cluster-wide counters.

To simplify the application we use the local shared map to save information about auctions. The local shared map allows you to share data between different verticles in the same Vert.x instance. Here’s an example of using a shared local map in an auction service:

publicclassAuctionRepository{

    //…public OptionalgetById(String auctionId){
        LocalMap auctionSharedData = this.sharedData.getLocalMap(auctionId);

        return Optional.of(auctionSharedData)
            .filter(m -> !m.isEmpty())
            .map(this::convertToAuction);
    }

    publicvoidsave(Auction auction){
        LocalMap auctionSharedData = this.sharedData.getLocalMap(auction.getId());

        auctionSharedData.put("id", auction.getId());
        auctionSharedData.put("price", auction.getPrice());
    }

    //…
}

If you want to store auction data in a database, Vert.x provides a few different asynchronous clients for accessing various data storages (MongoDB, Redis or JDBC client).

Auction API

Vert.x lets you route HTTP requests to different handlers based on pattern matching on the request path. It also enables you to extract values from the path and use them as parameters in the request. Corresponding methods exist for each HTTP method. The first matching one will receive the request. This functionality is particularly useful when developing REST-style web applications.

To extract parameters from the path, you can use the colon character to denote the name of a parameter. Regular expressions can also be used to extract more complex matches. Any parameters extracted by pattern matching are added to the map of request parameters.

Consumes describes which MIME types the handler can consume. By using produces you define which MIME types the route produces. In the code below the routes will match any request with content-type header and accept header that matches application/json.

Let’s look at an example of a subrouter mounted on the main router which was created in start method in verticle:

private Router auctionApiRouter(){
    AuctionRepository repository = new AuctionRepository(vertx.sharedData());
    AuctionValidator validator = new AuctionValidator(repository);
    AuctionHandler handler = new AuctionHandler(repository, validator);

    Router router = Router.router(vertx);
    router.route().handler(BodyHandler.create());

    router.route().consumes("application/json");
    router.route().produces("application/json");

    router.get("/auctions/:id").handler(handler::handleGetAuction);
    router.patch("/auctions/:id").handler(handler::handleChangeAuctionPrice);

    return router;
}

The GET request returns auction data, while the PATCH method request allows you to bid up in the auction. Let’s focus on the more interesting method, namely handleChangeAuctionPrice. In the simplest terms, the method might look like this:

publicvoidhandleChangeAuctionPrice(RoutingContext context){
    String auctionId = context.request().getParam("id");
    Auction auction = new Auction(
        auctionId,
        new BigDecimal(context.getBodyAsJson().getString("price"))
    );

    this.repository.save(auction);
    context.vertx().eventBus().publish("auction." + auctionId, context.getBodyAsString());

    context.response()
        .setStatusCode(200)
        .end();
}

PATCH request to /auctions/1 would result in variable auctionId getting the value 1. We save a new offer in the auction and then publish this information on the event bus to all clients registered on the address on the client side JavaScript. After you have finished with the HTTP response you must call the end function on it.

Static handler

Vert.x provides the handler for serving static web resources. The default directory from which static files are served is webroot, but this can be configured. By default the static handler will set cache headers to enable browsers to cache files. Setting cache headers can be disabled with setCachingEnabled method. To serve the auction HTML page, JS files (and other static files) from auction service, you can create a static handler like this:

private StaticHandler staticHandler(){
    return StaticHandler.create()
        .setCachingEnabled(false);
}

Let’s run!

Full application code is available on github.

Clone the repository and run ./gradlew run.

Open one or more browsers and point them to http://localhost:8080. Now you can bid in auction:

Real time bidding in application

Summary

This article presents the outline of a simple application that allows real-time bidding. We created a lightweight, high-performance and scalable micro-service written in Java and based on Vert.x. We discussed what Vert.x offers, among others, a distributed event bus and an elegant API that allows you to create applications in no time.

Using Hamcrest Matchers with Vert.x Unit

$
0
0

Vert.x Unit is a very elegant library to test asynchronous applications developed with vert.x. However because of this asynchronous aspect, reporting test failures is not natural for JUnit users. This is because, the failed assertions need to be reported to the test context, controlling the execution (and so the outcome) of the test. In other words, in a Vert.x Unit test you cannot use the regular Junit assertions and assertion libraries. In this blog post, we propose a way to let you using Hamcrest matchers in Vert.x Unit tests.

Using Vert.x Unit

Vert.x Unit is a test library made to ensure the behavior of vert.x applications. It lets you implement tests checking asynchronous behavior.

Vert.x Unit can be used with Junit. For this, you just need to add the following dependency to your project:

<dependency><groupId>io.vertxgroupId><artifactId>vertx-unitartifactId><version>3.2.0version><scope>testscope>dependency>

If you are using Gradle, the dependency is:

testCompileio.vertx:vertx-unit:3.2.0

If you are using an IDE, just add the vertx-unit jar to your project classpath.

Obviously, you would need to add JUnit too.

Notice that vertx-unit does not need JUnit, and can be used without it. Check the Vert.x Unit documentation for more details.

Vert.x Unit example

Let’s consider this very simple Verticle:

publicclassMyFirstVerticleextendsAbstractVerticle{

  @Overridepublicvoidstart(final Future future)throws Exception {
    vertx.createHttpServer()
        .requestHandler(req -> req.response().end("hello vert.x"))
        .listen(8080, done -> {
          if (done.failed()) {
            future.fail(done.cause());
          } else {
            future.complete();
          }
        });
  }
}

It just creates a new HTTP server and when launched it notifies the future of the completion.

To test this verticle with Vert.x Unit you would write something like:

@RunWith(VertxUnitRunner.class)
publicclassMyFirstVerticleTest{

  private Vertx vertx;

  @BeforepublicvoidsetUp(TestContext context){
    vertx = Vertx.vertx();
    vertx.deployVerticle(MyFirstVerticle.class.getName(),
      context.asyncAssertSuccess());
  }

  @Testpublicvoidtest(TestContext context){
    Async async = context.async();
    vertx.createHttpClient().get(8080, "localhost", "/")
      .handler(response -> {
        context.assertEquals(200, response.statusCode());
        response.bodyHandler(buffer -> {
          context.assertEquals("hello vert.x", buffer.toString("utf-8"));
          async.complete();
        });
      })
      .end();
  }
}

First, the test class is annotated with @RunWith(VertxUnitRunner.class), instructing JUnit to use this special runner. This runner lets you inject a TestContext parameter into every test methods (as well as @Before and @After) to handle the asynchronous aspect of the test.

In the setUp method, it creates a new instance of Vertx and deploy the verticle. Thanks to context.asyncAssertSuccess(), it waits until the successful completion of the verticle deployment. Indeed, the deployment is asynchronous, and we must be sure that the verticle has been deployed and has completed its initialization before starting to test it.

The test() method creates an Async object that will be used to report when the test has been completed. Then it creates an HTTP client to emit a request on the server from our verticle and check that:

  1. the HTTP code is 200 (OK)
  2. the body is hello vert.x

As you can see, to implement the checks, the assertions method are called on the TestContext object, which control the test execution. When everything has been tested, we call async.complete() to end the test. If an assertion failed, the test is obviously stopped. This would not be the case if you would use regular Junit assertions.

Using the Hamcrest Matchers

In the previous example, we used the the assertions available from the TestContext instance. However it provides a limited set of methods. Hamcrest is a library of matchers, which can be combined in to create flexible expressions of intent in tests. It is very convenient when testing complex applications.

Hamcrest cannot be used directly as it would not report the failure on the TestContext. For this purpose we create a VertxMatcherAssert class:

publicclassVertxMatcherAssert{

  publicstaticvoidassertThat(TestContext context, T actual,
    Matcher super T> matcher){
    assertThat(context, "", actual, matcher);
  }

  publicstaticvoidassertThat(TestContext context, String reason,
    T actual, Matcher super T> matcher){
    if (!matcher.matches(actual)) {
      Description description = new StringDescription();
      description.appendText(reason)
          .appendText("\nExpected: ")
          .appendDescriptionOf(matcher)
          .appendText("\n     but: ");
      matcher.describeMismatch(actual, description);
      context.fail(description.toString());
    }
  }

  publicstaticvoidassertThat(TestContext context, String reason,
    boolean assertion){
    if (!assertion) {
      context.fail(reason);
    }
  }
}

This class provides assertThat method that reports error on the given TestContext. The complete code is available here.

With this class, we can re-implement our test as follows:

@TestpublicvoidtestWithHamcrest(TestContext context){
  Async async = context.async();
  vertx.createHttpClient().get(8080, "localhost", "/").handler(response -> {
    assertThat(context, response.statusCode(), is(200));
    response.bodyHandler(buffer -> {
      assertThat(context, buffer.toString("utf-8"), is("hello vert.x"));
      async.complete();
    });
  }).end();
}

To ease the usage, I’ve added two import static:

importstatic io.vertx.unit.example.VertxMatcherAssert.assertThat;
importstatic org.hamcrest.core.Is.is;

You can use any Hamcrest matcher, or even implement your own as soon as you use the assertThat method provided by VertxMatcherAssert.

Conclusion

In this post we have seen how you can combine Hamcrest and Vert.x Unit. So, you are not limited anymore by the set of assert methods provided by Vert.x Unit, and can use the whole expressiveness of Hamcrest Matchers.

Don’t forget that you still can’t use the assert methods from Junit, as they don’t report on the TestContext.

Intro to Vert.x Shell

$
0
0

Vert.x Shell provides an extensible command line for Vert.x, accessible via SSH, Telnet or a nice Web interface. Vert.x Shell comes out of the box with plenty of commands for Vert.x which makes it very handy for doing simple management operations like deploying a Verticle or getting the list of deployed Verticles. One power feature of Vert.x Shell is its extensibility: one can easily augment Vert.x Shell with its own commands. Let’s build an http-client in JavaScript!

Booting the Shell

Vert.x Shell can be started in a couple of lines depending on the connectors you configure. The documentation provides several examples showing the Shell Service configuration. For testing our command, we will use the Telnet protocol because it is easy to configure and use, so we just need to copy the corresponding section in vertx-http-client.js:

var ShellService = require("vertx-shell-js/shell_service");
var service = ShellService.create(vertx, {
  "telnetOptions" : {
    "host" : "localhost",
    "port" : 4000
  }
});
service.start();

We can run it:

Juliens-MacBook-Pro:java julien$ vertx run vertx-http-client.js
Succeededin deploying verticle

And connect to the shell:

Juliens-MacBook-Pro:~ julien$ telnet localhost 4000
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
__      __ ______  _____  _______  __   __
\ \    / /|  ____||  _  \|__   __| \ \ / /
 \ \  / / | |____ | :_) |   | |     \   /
  \ \/ /  |  ____||   __/   | |      > /
   \  /   | |____ | |\ \    | |     / //\
\/    |______||_| \_\   |_| o  /_/ \_\


%

You can now already use the shell, the help command lists the available commands.

Creating a command

For the sake of simplicity we will write a single script that starts the Shell service and deploys our command. In the real world you would probably have the command in one file and the deployment in another.

The documentation explains how to add a new command to Vert.x shell, we can just copy this section and append it to the vertx-http-client.js script:

var CommandBuilder = require("vertx-shell-js/command_builder");
var CommandRegistry = require("vertx-shell-js/command_registry");

var builder = CommandBuilder.command("http-client");
builder.processHandler(function(process){

  // Write a message to the console
  process.write("Implement the client\n");

  // End the process
  process.end();
});

// Register the commandvar registry = CommandRegistry.getShared(vertx);
registry.registerCommand(builder.build(vertx));

Now you can use the command just to see it in action:

% http-client
Implement the client
%

Checking arguments

The http-client requires an url argument, an argument check is performed at the beginning of the process handler:

// Check the url argumentif (process.args().length <1) {
  process.write("Missing URL\n").end();
  return;
}
var url = process.args()[0];

Implementing the command

The final step of this tutorial is the actual implementation of the client logic based on Vert.x HttpClient:

// Create the client requestvar request = client.getAbs(url, function(response){

  // Print the response in the shell console
  response.handler(function(buffer){
    process.write(buffer.toString("UTF-8"));
  });

  // End the command when the response ends
  response.endHandler(function(){
    process.end();
  });
});

// Set a request handler to end the command with error
request.exceptionHandler(function(err){
  process.write("Error: " + err.getMessage());
  process.end();
});

// End the http request
request.end();

And we can test the command in the shell:

% http-client http://vertx.io
http-client http://vertx.io
Vert.x......
/javascripts/sticky_header.js>%

Finally

We have seen how easy it is to extend Vert.x with a shell and create an http-client custom command, you can get the full source code here.

Our command is very simple, it only implements the very minimum, in future posts we will improve the command with support with more HTTP methods, SSL support or header support with the the Vert.x CLI API.

Viewing all 158 articles
Browse latest View live