# Vert.x Core Manual

At the heart of Vert.x is a set of Java APIs that we call Vert.x Core

Repository.

Vert.x core provides functionality for things like:

- Writing TCP clients and servers

- Writing HTTP clients and servers including support for WebSockets

- The Event bus

- Shared data - local maps and clustered distributed maps

- Periodic and delayed actions

- Deploying and undeploying Verticles

- Datagram Sockets

- DNS client

- File system access

- High availability

- Clustering

The functionality in core is fairly low level - you won’t find stuff like database access, authorisation or high level web functionality here - that kind of stuff you’ll find in Vert.x ext (extensions).

Vert.x core is small and lightweight. You just use the parts you want. It’s also entirely embeddable in your existing applications - we don’t force you to structure your applications in a special way just so you can use Vert.x.

You can use core from any of the other languages that Vert.x supports. But here’a a cool bit - we don’t force you to use the Java API directly from, say, JavaScript or Ruby - after all, different languages have different conventions and idioms, and it would be odd to force Java idioms on Ruby developers (for example). Instead, we automatically generate an idiomatic equivalent of the core Java APIs for each language.

From now on we’ll just use the word core to refer to Vert.x core.

Let’s discuss the different concepts and features in core.

## In the beginning there was Vert.x

Note | Much of this is Java specific - need someway of swapping in language specific parts

You can’t do much in Vert.x-land unless you can commune with a `Vertx` object!

It’s the control centre of Vert.x and is how you do pretty much everything, including creating clients and servers, getting a reference to the event bus, setting timers, as well as many other things.

So how do you get an instance?

If you’re embedding Vert.x then you simply create an instance as follows:

    require 'vertx/vertx'
    vertx = Vertx::Vertx.vertx()

If you’re using Verticles

Note | Most applications will only need a single Vert.x instance, but it’s possible to create multiple Vert.x instances if you require, for example, isolation between the event bus or different groups of servers and clients.

### Specifying options when creating a Vertx object

When creating a Vertx object you can also specify options if the defaults aren’t right for you:

    require 'vertx/vertx'
    vertx = Vertx::Vertx.vertx({
      'workerPoolSize' => 40
    })

The `VertxOptions` object has many settings and allows you to configure things like clustering, high availability, pool sizes and various other settings. The Javadoc describes all the settings in detail.

### Creating a clustered Vert.x object

If you’re creating a clustered Vert.x (See the section on the event bus for more information on clustering the event bus), then you will normally use the asynchronous variant to create the Vertx object.

This is because it usually takes some time (maybe a few seconds) for the different Vert.x instances in a cluster to group together. During that time, we don’t want to block the calling thread, so we give the result to you asynchronously.

## Are you fluent?

You may have noticed that in the previous examples a fluent API was used.

A fluent API is where multiple methods calls can be chained together. For example:

    request.response().put_header("Content-Type", "text/plain").write("some text").end()

This is a common pattern throughout Vert.x APIs, so get used to it.

Chaining calls like this allows you to write code that’s a little bit less verbose. Of course, if you don’t like the fluent approach we don’t force you to do it that way, you can happily ignore it if you prefer and write your code like this:

    response = request.response()
    response.put_header("Content-Type", "text/plain")
    response.write("some text")
    response.end()

## Don’t call us, we’ll call you.

The Vert.x APIs are largely event driven. This means that when things happen in Vert.x that you are interested in, Vert.x will call you by sending you events.

Some example events are:

- a timer has fired

- some data has arrived on a socket,

- some data has been read from disk

- an exception has occurred

- an HTTP server has received a request

You handle events by providing handlers to the Vert.x APIs. For example to receive a timer event every second you would do:

    vertx.set_periodic(1000) { |id|
      # This handler will get called every second
      puts "timer fired!"
    }

Or to receive an HTTP request:

    # Respond to each http request with "Hello World"
    server.request_handler() { |request|
      # This handler will be called every time an HTTP request is received at the server
      request.response().end("hello world!")
    }

Some time later when Vert.x has an event to pass to your handler Vert.x will call it asynchronously.

This leads us to some important concepts in Vert.x:

## Don’t block me!

With very few exceptions (i.e. some file system operations ending in 'Sync'), none of the APIs in Vert.x block the calling thread.

If a result can be provided immediately, it will be returned immediately, otherwise you will usually provide a handler to receive events some time later.

Because none of the Vert.x APIs block threads that means you can use Vert.x to handle a lot of concurrency using just a small number of threads.

With a conventional blocking API the calling thread might block when:

- Reading data from a socket

- Writing data to disk

- Sending a message to a recipient and waiting for a reply.

- …​ Many other situations

In all the above cases, when your thread is waiting for a result it can’t do anything else - it’s effectively useless.

This means that if you want a lot of concurrency using blocking APIs then you need a lot of threads to prevent your application grinding to a halt.

Threads have overhead in terms of the memory they require (e.g. for their stack) and in context switching.

For the levels of concurrency required in many modern applications, a blocking approach just doesn’t scale.

## Reactor and Multi-Reactor

We mentioned before that Vert.x APIs are event driven - Vert.x passes events to handlers when they are available.

In most cases Vert.x calls your handlers using a thread called an event loop.

As nothing in Vert.x or your application blocks, the event loop can merrily run around delivering events to different handlers in succession as they arrive.

Because nothing blocks, an event loop can potentially deliver huge amounts of events in a short amount of time. For example a single event loop can handle many thousands of HTTP requests very quickly.

We call this the Reactor Pattern.

You may have heard of this before - for example Node.js implements this pattern.

In a standard reactor implementation there is a single event loop thread which runs around in a loop delivering all events to all handlers as they arrive.

The trouble with a single thread is it can only run on a single core at any one time, so if you want your single threaded reactor application (e.g. your Node.js application) to scale over your multi-core server you have to start up and manage many different processes.

Vert.x works differently here. Instead of a single event loop, each Vertx instance maintains several event loops. By default we choose the number based on the number of available cores on the machine, but this can be overridden.

This means a single Vertx process can scale across your server, unlike Node.js.

We call this pattern the Multi-Reactor Pattern to distinguish it from the single threaded reactor pattern.

Note | Even though a Vertx instance maintains multiple event loops, any particular handler will never be executed concurrently, and in most cases (with the exception of worker verticles) will always be called using the exact same event loop.

## The Golden Rule - Don’t Block the Event Loop

We already know that the Vert.x APIs are non blocking and won’t block the event loop, but that’s not much help if you block the event loop yourself in a handler.

If you do that, then that event loop will not be able to do anything else while it’s blocked. If you block all of the event loops in Vertx instance then your application will grind to a complete halt!

So don’t do it! You have been warned.

Examples of blocking include:

- Thread.sleep()

- Waiting on a lock

- Waiting on a mutex or monitor (e.g. synchronized section)

- Doing a long lived database operation and waiting for a result

- Doing a complex calculation that takes some significant time.

- Spinning in a loop

If any of the above stop the event loop from doing anything else for a significant amount of time then you should go immediately to the naughty step, and await further instructions.

So…​ what is a significant amount of time?

How long is a piece of string? It really depends on your application and the amount of concurrency you require.

If you have a single event loop, and you want to handle 10000 http requests per second, then it’s clear that each request can’t take more than 0.1 ms to process, so you can’t block for any more time than that.

The maths is not hard and shall be left as an exercise for the reader.

If your application is not responsive it might be a sign that you are blocking an event loop somewhere. To help you diagnose such issues, Vert.x will automatically log warnings if it detects an event loop hasn’t returned for some time. If you see warnings like these in your logs, then you should investigate.

    Thread vertx-eventloop-thread-3 has been blocked for 20458 ms

Vert.x will also provide stack traces to pinpoint exactly where the blocking is occurring.

If you want to turn of these warnings or change the settings, you can do that in the `VertxOptions` object before creating the Vertx object.

## Running blocking code

In a perfect world, there will be no war or hunger, all APIs will be written asynchronously and bunny rabbits will skip hand-in-hand with baby lambs across sunny green meadows.

But.. the real world is not like that. (Have you watched the news lately?)

Fact is, many, if not most libraries, especially in the JVM ecosystem have synchronous APIs and many of the methods are likely to block. A good example is the JDBC API - it’s inherently synchronous, and no matter how hard it tries, Vert.x cannot sprinkle magic pixie dust on it to make it asynchronous.

We’re not going to rewrite everything to be asynchronous overnight so we need to provide you a way to use "traditional" blocking APIs safely within a Vert.x application.

As discussed before, you can’t call blocking operations directly from an event loop, as that would prevent it from doing any other useful work. So how can you do this?

It’s done by calling `executeBlocking` specifying both the blocking code to execute and a result handler to be called back asynchronous when the blocking code has been executed.

    @someAPI = Java::ExamplesCoreExamples::BlockingAPI.new()
    vertx.execute_blocking(lambda { |future|
      # Call some blocking API that takes a significant amount of time to return
      result = @someAPI.blocking_method("hello")
      future.complete(result)
    }) { |res_err,res|
      puts "The result is: #{res}"
    }

By default, if executeBlocking is called several times from the same context (e.g. the same verticle instance) then the different executeBlocking are executed serially (i.e. one after another).

If you don’t care about ordering you can call `executeBlocking` specifying `false` as the argument to `ordered`. In this case any executeBlocking may be executed in parallel on the worker pool.

An alternative way to run blocking code is to use a worker verticle

A worker verticle is always executed with a thread from the worker pool.

## Verticles

Vert.x comes with a simple, scalable, actor-like deployment and concurrency model out of the box that you can use to save you writing your own.

This model is entirely optional and Vert.x does not force you to create your applications in this way if you don’t want to..

The model does not claim to be a strict actor-model implementation, but it does share similarities especially with respect to concurrency, scaling and deployment.

To use this model, you write your code as set of verticles.

Verticles are chunks of code that get deployed and run by Vert.x. Verticles can be written in any of the languages that Vert.x supports and a single application can include verticles written in multiple languages.

You can think of a verticle as a bit like an actor in the Actor Model.

An application would typically be composed of many verticle instances running in the same Vert.x instance at the same time. The different verticle instances communicate with each other by sending messages on the event bus.

### Writing Verticles

Ruby verticles are implemented as simple scripts.

Ruby verticles will have the following globals pre-set as a convenience:

- $vertx - A reference to the Vertx object

    # Start a timer
    $vertx.set_periodic(1000) { puts 'Timer has fired' }

When the verticle is deployed the body of the script will be executed.

Any `vertx_start` function function defined during the body execution will be executed after the execution. The `vertx_start` is executed as any other function and does not expect any argument.

Likewise any `vertx_stop` function function defined during the body execution will be executed after the execution. The `vertx_stop` is executed as any other function and does not expect any argument.

    def vertx_stop future
      # Cleanup here
    end

To load a verticle as a Ruby gem, this Ruby gem must deployed

### Asynchronous Verticle start and stop

Sometimes you want to do something in your verticle start-up which takes some time and you don’t want the verticle to be considered deployed until that happens. For example you might want to deploy other verticles in the start method.

You can’t block waiting for the other verticles to deploy in your start method as that would break the Golden Rule.

So how can you do this?

The way to do it is to implement the asynchronous start method. This version of the method takes a Future as a parameter. When the method returns the verticle will not be considered deployed yet. Some time later, after you’ve done everything you need to do (e.g. start other verticles), you can call complete on the Future (or fail) to signal that you’re done.

Here’s an example:

    def vertx_start_async start_future
      # Now deploy some other verticle:

      $vertx.deploy_verticle("other_verticle.rb") do |res|
        if res.succeeded?
          start_future.complete
        else
          start_future.fail
        end
      end
    end

Similarly, there is an asynchronous version of the stop method too. You use this if you want to do some verticle cleanup that takes some time.

    def vertx_stop_async stop_future
      obj.do_something_that_takes_time do |res|
        if res.succeeded?
          stop_future.complete
        else
          stop_future.fail
        end
      end
    end

INFO: You don’t need to manually undeploy child verticles started by a verticle, in the verticle’s stop method. Vert.x will automatically undeploy any child verticles when the parent is undeployed.

### Verticle deployment options

When deploying a Ruby, verticle it is possible to set a specific GEM_PATH variable for this particular verticle:

    DeploymentOptions options = new DeploymentOptions().
        setConfig(new JsonObject().put("GEM_PATH", "/path/to/gems"));
    vertx.deployVerticle("my_verticle.rb", options);

This can be done also possible in Ruby:

    options = { :config => { :GEM_PATH => '/path/to/gems' } }
    $vertx.deploy_verticle('my_verticle.rb', options)

This option can also be specified for the CLI:

    vertx run my_verticle_rb -conf {\"GEM_PATH\":\"/path/to/gems\"}

### Verticle Types

There are three different types of verticles:

Standard Verticles

  These are the most common and useful type - they are always executed using an event loop thread. We’ll discuss this more in the next section.

Worker Verticles

  These run using a thread from the worker pool. An instance is never executed concurrently by more than one thread.

Multi-threaded worker verticles

  These run using a thread from the worker pool. An instance can be executed concurrently by more than one thread.

### Standard verticles

Standard verticles are assigned an event loop thread when they are created and the start method is called with that event loop. When you call any other methods that takes a handler on a core API from an event loop then Vert.x will guarantee that those handlers, when called, will be executed on the same event loop.

This means we can guarantee that all the code in your verticle instance is always executed on the same event loop (as long as you don’t create your own threads and call it!).

This means you can write all the code in your application as single threaded and let Vert.x worrying about the threading and scaling. No more worrying about synchronized and volatile any more, and you also avoid many other cases of race conditions and deadlock so prevalent when doing hand-rolled 'traditional' multi-threaded application development.

### Worker verticles

A worker verticle is just like a standard verticle but it’s executed not using an event loop, but using a thread from the Vert.x worker thread pool.

Worker verticles are designed for calling blocking code, as they won’t block any event loops.

If you don’t want to use a worker verticle to run blocking code, you can also run inline blocking code directly while on an event loop.

If you want to deploy a verticle as a worker verticle you do that with `worker`.

    options = {
      'worker' => true
    }
    vertx.deploy_verticle("com.mycompany.MyOrderProcessorVerticle", options)

Worker verticle instances are never executed concurrently by Vert.x by more than one thread, but can executed by different threads at different times.

#### Multi-threaded worker verticles

A multi-threaded worker verticle is just like a normal worker verticle but it can be executed concurrently by different threads.

Warning | Multi-threaded worker verticles are an advanced feature and most applications will have no need for them. Because of the concurrency in these verticles you have to be very careful to keep the verticle in a consistent state using standard Java techniques for multi-threaded programming.

### Deploying verticles programmatically

You can deploy a verticle using one of the `deployVerticle` method, specifying a verticle name or you can pass in a verticle instance you have already created yourself.

Note | Deploying Verticle instances is Java only.

    myVerticle = Java::ExamplesCoreExamples::MyVerticle.new()
    vertx.deploy_verticle(myVerticle)

You can also deploy verticles by specifying the verticle name.

The verticle name is used to look up the specific `VerticleFactory` that will be used to instantiate the actual verticle instance(s).

Different verticle factories are available for instantiating verticles in different languages and for various other reasons such as loading services and getting verticles from Maven at run-time.

This allows you to deploy verticles written in any language from any other language that Vert.x supports.

Here’s an example of deploying some different types of verticles:

    # Deploy a Java verticle - the name is the fully qualified class name of the verticle class
    vertx.deploy_verticle("com.mycompany.MyOrderProcessorVerticle")

    # Deploy a JavaScript verticle
    vertx.deploy_verticle("verticles/myverticle.js")

    # Deploy a Ruby verticle verticle
    vertx.deploy_verticle("verticles/my_verticle.rb")

### Rules for mapping a verticle name to a verticle factory

When deploying verticle(s) using a name, the name is used to select the actual verticle factory that will instantiate the verticle(s).

Verticle names can have a prefix - which is a string followed by a colon, which if present will be used to look-up the factory, e.g.

    js:foo.js // Use the JavaScript verticle factory
    groovy:com.mycompany.SomeGroovyCompiledVerticle // Use the Groovy verticle factory
    service:com.mycompany:myorderservice // Uses the service verticle factory

If no prefix is present, Vert.x will look for a suffix and use that to lookup the factory, e.g.

    foo.js // Will also use the JavaScript verticle factory
    SomeScript.groovy // Will use the Groovy verticle factory

If no prefix or suffix is present, Vert.x will assume it’s a Java fully qualified class name (FQCN) and try and instantiate that.

### How are Verticle Factories located?

Most Verticle factories are loaded from the classpath and registered at Vert.x startup.

You can also programmatically register and unregister verticle factories using `registerVerticleFactory` and `unregisterVerticleFactory` if you wish.

### Waiting for deployment to complete

Verticle deployment is asynchronous and may complete some time after the call to deploy has returned.

If you want to be notified when deployment is complete you can deploy specifying a completion handler:

    vertx.deploy_verticle("com.mycompany.MyOrderProcessorVerticle") { |res_err,res|
      if (res_err == nil)
        puts "Deployment id is: #{res}"
      else
        puts "Deployment failed!"
      end
    }

The completion handler will be passed a result containing the deployment ID string, if deployment succeeded.

This deployment ID can be used later if you want to undeploy the deployment.

### Undeploying verticle deployments

Deployments can be undeployed with `undeploy`.

Un-deployment is itself asynchronous so if you want to be notified when un-deployment is complete you can deploy specifying a completion handler:

    vertx.undeploy(deploymentID) { |res_err,res|
      if (res_err == nil)
        puts "Undeployed ok"
      else
        puts "Undeploy failed!"
      end
    }

### Specifying number of verticle instances

When deploying a verticle using a verticle name, you can specify the number of verticle instances that you want to deploy:

    options = {
      'instances' => 16
    }
    vertx.deploy_verticle("com.mycompany.MyOrderProcessorVerticle", options)

This is useful for scaling easily across multiple cores. For example you might have a web-server verticle to deploy and multiple cores on your machine, so you want to deploy multiple instances to take utilise all the cores.

### Passing configuration to a verticle

Configuration in the form of JSON can be passed to a verticle at deployment time:

    config = {
     'name' => "tim",
     'directory' => "/blah"
    }
    options = {
     'config' => config
    }
    vertx.deploy_verticle("MyOrderProcessorVerticle.rb", options)

This configuration is then available via the `Context` object.

The configuration is returned as a Hash object so you can retrieve data as follows:

    puts $vertx.get_or_create_context().config()["name"]

### Accessing environment variables in a Verticle

Environment variables and system properties are accessible from a verticle using the Java API:

    puts Java::JavaLang::System.getProperty("foo")
    puts Java::JavaLang::System.getenv("HOME")

### Verticle Isolation Groups

By default, Vert.x has a flat classpath. I.e, when Vert.x deploys verticles it does so with the current classloader - it doesn’t create a new one. In the majority of cases this is the simplest, clearest and sanest thing to do.

However, in some cases you may want to deploy a verticle so the classes of that verticle are isolated from others in your application.

This might be the case, for example, if you want to deploy two different versions of a verticle with the same class name in the same Vert.x instance, or if you have two different verticles which use different versions of the same jar library.

When using an isolation group you provide a list of the class names that you want isolated using `isolatedClasses`- an entry can be a fully qualified classname such as `com.mycompany.myproject.engine.MyClass` or it can be a wildcard which will match any classes in a package and any sub-packages, e.g. `com.mycompany.myproject.*` would match any classes in the package `com.mycompany.myproject` or any sub-packages.

Please note that only the classes that match will be isolated - any other classes will be loaded by the current class loader.

Extra classpath entries can also be provided with `extraClasspath` so if you want to load classes or resources that aren’t already present on the main classpath you can add this.

Warning | Use this feature with caution. Class-loaders can be a can of worms, and can make debugging difficult, amongst other things.

Here’s an example of using an isolation group to isolate a verticle deployment.

    options = {
      'isolationGroup' => "mygroup"
    }
    options['isolatedClasses'] = ["com.mycompany.myverticle.*", "com.mycompany.somepkg.SomeClass", "org.somelibrary.*"]
    vertx.deploy_verticle("com.mycompany.myverticle.VerticleClass", options)

### High Availability

Verticles can be deployed with High Availability (HA) enabled. In that context, when a verticle is deployed on a vert.x instance that dies abruptly, the verticle is redeployed on another vert.x instance from the cluster.

To run an verticle with the high availability enabled, just append the `-ha` switch:

    vertx run my-verticle.js -ha

When enabling high availability, no need to add `-cluster`.

More details about the high availability feature and configuration in the High Availability and Fail-Over section.

### Running Verticles from the command line

You can use Vert.x directly in your Maven or Gradle projects in the normal way by adding a dependency to the Vert.x core library and hacking from there.

However you can also run Vert.x verticles directly from the command line if you wish.

To do this you need to download and install a Vert.x distribution, and add the `bin` directory of the installation to your `PATH` environment variable. Also make sure you have a Java 8 JDK on your `PATH`.

Note | The JDK is required to support on the fly compilation of Java code.

You can now run verticles by using the `vertx run` command. Here are some examples:

    # Run a JavaScript verticle
    vertx run my_verticle.js

    # Run a Ruby verticle
    vertx run a_n_other_verticle.rb

    # Run a Groovy script verticle, clustered
    vertx run FooVerticle.groovy -cluster

You can even run Java source verticles without compiling them first!

    vertx run SomeJavaSourceFile.java

Vert.x will compile the Java source file on the fly before running it. This is really useful for quickly prototyping verticles and great for demos. No need to set-up a Maven or Gradle build first to get going!

For full information on the various options available when executing `vertx` on the command line, type `vertx` at the command line.

### Causing Vert.x to exit

Threads maintained by Vert.x instances are not daemon threads so they will prevent the JVM from exiting.

If you are embedding Vert.x and you have finished with it, you can call `close` to close it down.

This will shut-down all internal thread pools and close other resources, and will allow the JVM to exit.

### The Context object

When Vert.x provides an event to a handler or calls the start or stop methods of a `Verticle`, the execution is associated with a `Context`. Usually a context is an event-loop context and is tied to a specific event loop thread. So executions for that context always occur on that exact same event loop thread. In the case of worker verticles and running inline blocking code a worker context will be associated with the execution which will use a thread from the worker thread pool.

To retrieve the context, use the `getOrCreateContext` method:

    context = vertx.get_or_create_context()

If the current thread has a context associated with it, it reuses the context object. If not a new instance of context is created. You can test the type of context you have retrieved:

    require 'vertx/context'
    context = vertx.get_or_create_context()
    if (context.event_loop_context?())
      puts "Context attached to Event Loop"
    elsif (context.worker_context?())
      puts "Context attached to Worker Thread"
    elsif (context.multi_threaded_worker_context?())
      puts "Context attached to Worker Thread - multi threaded worker"
    elsif (!Vertx::Context.on_vertx_thread?())
      puts "Context not attached to a thread managed by vert.x"
    end

When you have retrieved the context object, you can run code in this context asynchronously. In other words, you submit a task that will be eventually run in the same context, but later:

    vertx.get_or_create_context().run_on_context() { |v|
      puts "This will be executed asynchronously in the same context"
    }

When several handlers run in the same context, they may want to share data. The context object offers methods to store and retrieve data shared in the context. For instance, it lets you pass data to some action run with `runOnContext`:

    context = vertx.get_or_create_context()
    context.put("data", "hello")
    context.run_on_context() { |v|
      hello = context.get("data")
    }

The context object also let you access verticle configuration using the `config` method. Check the Passing configuration to a verticle section for more details about this configuration.

### Executing periodic and delayed actions

It’s very common in Vert.x to want to perform an action after a delay, or periodically.

In standard verticles you can’t just make the thread sleep to introduce a delay, as that will block the event loop thread.

Instead you use Vert.x timers. Timers can be one-shot or periodic. We’ll discuss both

#### One-shot Timers

A one shot timer calls an event handler after a certain delay, expressed in milliseconds.

To set a timer to fire once you use `setTimer` method passing in the delay and a handler

    timerID = vertx.set_timer(1000) { |id|
      puts "And one second later this is printed"
    }

    puts "First this is printed"

The return value is a unique timer id which can later be used to cancel the timer. The handler is also passed the timer id.

#### Periodic Timers

You can also set a timer to fire periodically by using `setPeriodic`.

There will be an initial delay equal to the period.

The return value of `setPeriodic` is a unique timer id (long). This can be later used if the timer needs to be cancelled.

The argument passed into the timer event handler is also the unique timer id:

Keep in mind that the timer will fire on a periodic basis. If your periodic treatment takes a long amount of time to proceed, your timer events could run continuously or even worse : stack up.

In this case, you should consider using `setTimer` instead. Once your treatment has finished, you can set the next timer.

    timerID = vertx.set_periodic(1000) { |id|
      puts "And every second this is printed"
    }

    puts "First this is printed"

#### Cancelling timers

To cancel a periodic timer, call `cancelTimer` specifying the timer id. For example:

    vertx.cancel_timer?(timerID)

#### Automatic clean-up in verticles

If you’re creating timers from inside verticles, those timers will be automatically closed when the verticle is undeployed.

## The Event Bus

The `event bus` is the nervous system of Vert.x.

There is a single event bus instance for every Vert.x instance and it is obtained using the method `eventBus`.

The event bus allows different parts of your application to communicate with each other irrespective of what language they are written in, and whether they’re in the same Vert.x instance, or in a different Vert.x instance.

It can even be bridged to allow client side JavaScript running in a browser to communicate on the same event bus.

The event bus forms a distributed peer-to-peer messaging system spanning multiple server nodes and multiple browsers.

The event bus supports publish/subscribe, point to point, and request-response messaging.

The event bus API is very simple. It basically involves registering handlers, unregistering handlers and sending and publishing messages.

First some theory:

### The Theory

#### Addressing

Messages are sent on the event bus to an address.

Vert.x doesn’t bother with any fancy addressing schemes. In Vert.x an address is simply a string. Any string is valid. However it is wise to use some kind of scheme, e.g. using periods to demarcate a namespace.

Some examples of valid addresses are europe.news.feed1, acme.games.pacman, sausages, and X.

#### Handlers

Messages are received in handlers. You register a handler at an address.

Many different handlers can be registered at the same address.

A single handler can be registered at many different addresses.

#### Publish / subscribe messaging

The event bus supports publishing messages.

Messages are published to an address. Publishing means delivering the message to all handlers that are registered at that address.

This is the familiar publish/subscribe messaging pattern.

#### Point to point and Request-Response messaging

The event bus also supports point to point messaging.

Messages are sent to an address. Vert.x will then route it to just one of the handlers registered at that address.

If there is more than one handler registered at the address, one will be chosen using a non-strict round-robin algorithm.

With point to point messaging, an optional reply handler can be specified when sending the message.

When a message is received by a recipient, and has been handled, the recipient can optionally decide to reply to the message. If they do so the reply handler will be called.

When the reply is received back at the sender, it too can be replied to. This can be repeated ad-infinitum, and allows a dialog to be set-up between two different verticles.

This is a common messaging pattern called the request-response pattern.

#### Best-effort delivery

Vert.x does it’s best to deliver messages and won’t consciously throw them away. This is called best-effort delivery.

However, in case of failure of all or parts of the event bus, there is a possibility messages will be lost.

If your application cares about lost messages, you should code your handlers to be idempotent, and your senders to retry after recovery.

#### Types of messages

Out of the box Vert.x allows any primitive/simple type, String, or `buffers` to be sent as messages.

However it’s a convention and common practice in Vert.x to send messages as JSON

JSON is very easy to create, read and parse in all the languages that Vert.x supports so it has become a kind of lingua franca for Vert.x.

However you are not forced to use JSON if you don’t want to.

The event bus is very flexible and also supports sending arbitrary objects over the event bus. You do this by defining a `codec` for the objects you want to send.

### The Event Bus API

Let’s jump into the API

#### Getting the event bus

You get a reference to the event bus as follows:

    eb = vertx.event_bus()

There is a single instance of the event bus per Vert.x instance.

#### Registering Handlers

This simplest way to register a handler is using `consumer`. Here’s an example:

    eb = vertx.event_bus()

    eb.consumer("news.uk.sport") { |message|
      puts "I have received a message: #{message.body()}"
    }

When a message arrives for your handler, your handler will be called, passing in the `message`.

The object returned from call to consumer() is an instance of `MessageConsumer`

This object can subsequently be used to unregister the handler, or use the handler as a stream.

Alternatively you can use `consumer` to to return a MessageConsumer with no handler set, and then set the handler on that. For example:

    eb = vertx.event_bus()

    consumer = eb.consumer("news.uk.sport")
    consumer.handler() { |message|
      puts "I have received a message: #{message.body()}"
    }

When registering a handler on a clustered event bus, it can take some time for the registration to reach all nodes of the cluster.

If you want to be notified when this has completed, you can register a `completion handler` on the MessageConsumer object.

    consumer.completion_handler() { |res_err,res|
      if (res_err == nil)
        puts "The handler registration has reached all nodes"
      else
        puts "Registration failed!"
      end
    }

#### Un-registering Handlers

To unregister a handler, call `unregister`.

If you are on a clustered event bus, un-registering can take some time to propagate across the nodes, if you want to be notified when this is complete use `unregister`.

    consumer.unregister() { |res_err,res|
      if (res_err == nil)
        puts "The handler un-registration has reached all nodes"
      else
        puts "Un-registration failed!"
      end
    }

#### Publishing messages

Publishing a message is simple. Just use `publish` specifying the address to publish it to.

    eventBus.publish("news.uk.sport", "Yay! Someone kicked a ball")

That message will then be delivered to all handlers registered against the address news.uk.sport.

#### Sending messages

Sending a message will result in only one handler registered at the address receiving the message. This is the point to point messaging pattern. The handler is chosen in a non-strict round-robin fashion.

You can send a message with `send`

    eventBus.send("news.uk.sport", "Yay! Someone kicked a ball")

#### Setting headers on messages

Messages sent over the event bus can also contain headers.

This can be specified by providing a `headers` object inside the `DeliveryOptions` object when sending or publishing:

    options = {
     headers: {
       'some-header' => 'some-value'
     }
    }
    vertx.event_bus().send("news.uk.sport", "Yay! Someone kicked a ball", options)

On the other side, the consumer can retrieve the message header as follows:

    eb = $vertx.event_bus()
    eb.consumer("news.uk.sport") { |message|
     puts message.headers().get("some-header")
    }

#### The Message object

The object you receive in a message handler is a `Message`.

The `body` of the message corresponds to the object that was sent or published.

The headers of the message are available with `headers`.

#### Replying to messages

Sometimes after you send a message you want to receive a reply from the recipient. This is known as the request-response pattern.

To do this you can specify a reply handler when sending the message.

When the receiver receives the message they can reply to it by calling `reply`.

When this happens it causes a reply to be sent back to the sender and the reply handler is invoked with the reply.

An example will make this clear:

The receiver:

    consumer = eventBus.consumer("news.uk.sport")
    consumer.handler() { |message|
      puts "I have received a message: #{message.body()}"
      message.reply("how interesting!")
    }

The sender:

    eventBus.send("news.uk.sport", "Yay! Someone kicked a ball across a patch of grass") { |ar_err,ar|
      if (ar_err == nil)
        puts "Received reply: #{ar.body()}"
      end
    }

The replies themselves can also be replied to so you can create a dialog between two different parties consisting of multiple rounds.

#### Sending with timeouts

When sending a message with a reply handler you can specify a timeout in the `DeliveryOptions`.

If a reply is not received within that time, the reply handler will be called with a failure.

The default timeout is 30 seconds.

#### Send Failures

Message sends can fail for other reasons, including:

- There are no handlers available to send the message to

- The recipient has explicitly failed the message using `fail`

In all cases the reply handler will be called with the specific failure.

#### Message Codecs

Message codecs are available exclusively with the Java api.

#### Clustered Event Bus

The event bus doesn’t just exist in a single Vert.x instance. By clustering different Vert.x instances together on your network they can form a single, distributed, event bus.

#### Clustering programmatically

If you’re creating your Vert.x instance programmatically you get a clustered event bus by configuring the Vert.x instance as clustered;

    require 'vertx/vertx'
    options = {
    }
    Vertx::Vertx.clustered_vertx(options) { |res_err,res|
      if (res_err == nil)
        vertx = res
        eventBus = vertx.event_bus()
        puts "We now have a clustered event bus: #{eventBus}"
      else
        puts "Failed: #{res_err}"
      end
    }

You should also make sure you have a `ClusterManager` implementation on your classpath, for example the default `HazelcastClusterManager`.

#### Clustering on the command line

You can run Vert.x clustered on the command line with

    vertx run my-verticle.js -cluster

### Automatic clean-up in verticles

If you’re registering event bus handlers from inside verticles, those handlers will be automatically unregistered when the verticle is undeployed.

## JSON

Unlike some other languages, Ruby does not have first class support for JSON so we use Array and Hash to make handling JSON in your Vert.x applications a bit easier.

### JSON objects

Ruby hashes represents JSON objects.

A JSON object is basically just a map which has string keys and values can be of one of the JSON supported types (string, number, boolean).

JSON objects also support nil values.

#### Creating JSON objects

Empty JSON objects can be created with the default constructor.

You can create a JSON object from a string JSON representation as follows:

    require 'json'
    object = JSON.parse('"foo":"bar"')

#### Encoding the JSON object to a String

You use `JSON.generate` to encode the object to a String form.

    require 'json'
    json = JSON.generate(object)

### JSON arrays

Ruby arrays represents JSON arrays.

A JSON array is a sequence of values (string, number, boolean).

JSON arrays can also contain null values.

#### Creating JSON arrays

Empty JSON arrays can be created with the default constructor.

You can create a JSON array from a string JSON representation as follows:

    require 'json'
    object = JSON.parse('[1,2,3]')

#### Encoding the JSON array to a String

You use `JSON.generate` to encode the array to a String form.

    require 'json'
    json = JSON.generate(array)

## Buffers

Most data is shuffled around inside Vert.x using buffers.

A buffer is a sequence of zero or more bytes that can read from or written to and which expands automatically as necessary to accommodate any bytes written to it. You can perhaps think of a buffer as smart byte array.

### Creating buffers

Buffers can create by using one of the static `Buffer.buffer` methods.

Buffers can be initialised from strings or byte arrays, or empty buffers can be created.

Here are some examples of creating buffers:

Create a new empty buffer:

    require 'vertx/buffer'
    buff = Vertx::Buffer.buffer()

Create a buffer from a String. The String will be encoded in the buffer using UTF-8.

    require 'vertx/buffer'
    buff = Vertx::Buffer.buffer("some string")

Create a buffer from a String: The String will be encoded using the specified encoding, e.g:

    require 'vertx/buffer'
    buff = Vertx::Buffer.buffer("some string", "UTF-16")

Create a buffer with an initial size hint. If you know your buffer will have a certain amount of data written to it you can create the buffer and specify this size. This makes the buffer initially allocate that much memory and is more efficient than the buffer automatically resizing multiple times as data is written to it.

Note that buffers created this way are empty. It does not create a buffer filled with zeros up to the specified size.

    require 'vertx/buffer'
    buff = Vertx::Buffer.buffer(10000)

### Writing to a Buffer

There are two ways to write to a buffer: appending, and random access. In either case buffers will always expand automatically to encompass the bytes. It’s not possible to get an `IndexOutOfBoundsException` with a buffer.

#### Appending to a Buffer

To append to a buffer, you use the `appendXXX` methods. Append methods exist for appending various different types.

The return value of the `appendXXX` methods is the buffer itself, so these can be chained:

    require 'vertx/buffer'
    buff = Vertx::Buffer.buffer()

    buff.append_int(123).append_string("hello\n")

    socket.write(buff)

#### Random access buffer writes

You can also write into the buffer at a specific index, by using the `setXXX` methods. Set methods exist for various different data types. All the set methods take an index as the first argument - this represents the position in the buffer where to start writing the data.

The buffer will always expand as necessary to accommodate the data.

    require 'vertx/buffer'
    buff = Vertx::Buffer.buffer()

    buff.set_int(1000, 123)
    buff.set_string(0, "hello")

### Reading from a Buffer

Data is read from a buffer using the `getXXX` methods. Get methods exist for various datatypes. The first argument to these methods is an index in the buffer from where to get the data.

    require 'vertx/buffer'
    buff = Vertx::Buffer.buffer()
    i = 0
    while (i < buff.length())
      puts "int value at #{i} is #{buff.get_int(i)}"
      4
    end

### Buffer length

Use `length` to obtain the length of the buffer. The length of a buffer is the index of the byte in the buffer with the largest index + 1.

### Copying buffers

Use `copy` to make a copy of the buffer

### Slicing buffers

A sliced buffer is a new buffer which backs onto the original buffer, i.e. it does not copy the underlying data. Use `slice` to create a sliced buffers

### Buffer re-use

After writing a buffer to a socket or other similar place, they cannot be re-used.

## Writing TCP servers and clients

Vert.x allows you to easily write non blocking TCP clients and servers.

### Creating a TCP server

The simplest way to create a TCP server, using all default options is as follows:

    server = vertx.create_net_server()

### Configuring a TCP server

If you don’t want the default, a server can be configured by passing in a `NetServerOptions` instance when creating it:

    options = {
      'port' => 4321
    }
    server = vertx.create_net_server(options)

### Start the Server Listening

To tell the server to listen for incoming requests you use one of the `listen` alternatives.

To tell the server to listen at the host and port as specified in the options:

    server = vertx.create_net_server()
    server.listen()

Or to specify the host and port in the call to listen, ignoring what is configured in the options:

    server = vertx.create_net_server()
    server.listen(1234, "localhost")

The default host is `0.0.0.0` which means 'listen on all available addresses' and the default port is `0`, which is a special value that instructs the server to find a random unused local port and use that.

The actual bind is asynchronous so the server might not actually be listening until some time after the call to listen has returned.

If you want to be notified when the server is actually listening you can provide a handler to the `listen` call. For example:

    server = vertx.create_net_server()
    server.listen(1234, "localhost") { |res_err,res|
      if (res_err == nil)
        puts "Server is now listening!"
      else
        puts "Failed to bind!"
      end
    }

### Listening on a random port

If `0` is used as the listening port, the server will find an unused random port to listen on.

To find out the real port the server is listening on you can call `actualPort`.

    server = vertx.create_net_server()
    server.listen(0, "localhost") { |res_err,res|
      if (res_err == nil)
        puts "Server is now listening on actual port: #{server.actual_port()}"
      else
        puts "Failed to bind!"
      end
    }

### Getting notified of incoming connections

To be notified when a connection is made you need to set a `connectHandler`:

    server = vertx.create_net_server()
    server.connect_handler() { |socket|
      # Handle the connection in here
    }

When a connection is made the handler will be called with an instance of `NetSocket`.

This is a socket-like interface to the actual connection, and allows you to read and write data as well as do various other things like close the socket.

### Reading data from the socket

To read data from the socket you set the `handler` on the socket.

This handler will be called with an instance of `Buffer` every time data is received on the socket.

    server = vertx.create_net_server()
    server.connect_handler() { |socket|
      socket.handler() { |buffer|
        puts "I received some bytes: #{buffer.length()}"
      }
    }

### Writing data to a socket

You write to a socket using one of `write`.

    require 'vertx/buffer'

    # Write a buffer
    buffer = Vertx::Buffer.buffer().append_float(12.34).append_int(123)
    socket.write(buffer)

    # Write a string in UTF-8 encoding
    socket.write("some data")

    # Write a string using the specified encoding
    socket.write("some data", "UTF-16")

Write operations are asynchronous and may not occur until some time after the call to write has returned.

### Closed handler

If you want to be notified when a socket is closed, you can set a `closeHandler` on it:

    socket.close_handler() { |v|
      puts "The socket has been closed"
    }

### Handling exceptions

You can set an `exceptionHandler` to receive any exceptions that happen on the socket.

### Event bus write handler

Every socket automatically registers a handler on the event bus, and when any buffers are received in this handler, it writes them to itself.

This enables you to write data to a socket which is potentially in a completely different verticle or even in a different Vert.x instance by sending the buffer to the address of that handler.

The address of the handler is given by `writeHandlerID`

### Local and remote addresses

The local address of a `NetSocket` can be retrieved using `localAddress`.

The remote address, (i.e. the address of the other end of the connection) of a `NetSocket` can be retrieved using `remoteAddress`.

### Sending files

Files can be written to the socket directly using `sendFile`. This can be a very efficient way to send files, as it can be handled by the OS kernel directly where supported by the operating system.

    socket.send_file("myfile.dat")

### Streaming sockets

Instances of `NetSocket` are also `ReadStream` and `WriteStream` instances so they can be used to pump data to or from other read and write streams.

See the chapter on streams and pumps for more information.

### Upgrading connections to SSL/TLS

A non SSL/TLS connection can be upgraded to SSL/TLS using `upgradeToSsl`.

The server or client must be configured for SSL/TLS for this to work correctly. Please see the chapter on SSL/TLS for more information.

### Closing a TCP Server

Call `close` to close the server. Closing the server closes any open connections and releases all server resources.

The close is actually asynchronous and might not complete until some time after the call has returned. If you want to be notified when the actual close has completed then you can pass in a handler.

This handler will then be called when the close has fully completed.

    server.close() { |res_err,res|
      if (res_err == nil)
        puts "Server is now closed"
      else
        puts "close failed"
      end
    }

### Automatic clean-up in verticles

If you’re creating TCP servers and clients from inside verticles, those servers and clients will be automatically closed when the verticle is undeployed.

### Scaling - sharing TCP servers

The handlers of any TCP server are always executed on the same event loop thread.

This means that if you are running on a server with a lot of cores, and you only have this one instance deployed then you will have at most one core utilised on your server.

In order to utilise more cores of your server you will need to deploy more instances of the server.

You can instantiate more instances programmatically in your code:

    # Create a few instances so we can utilise cores

    i = 0
    while (i < 10)
      server = vertx.create_net_server()
      server.connect_handler() { |socket|
        socket.handler() { |buffer|
          # Just echo back the data
          socket.write(buffer)
        }
      }
      server.listen(1234, "localhost")
      i+=1
    end

or, if you are using verticles you can simply deploy more instances of your server verticle by using the `-instances` option on the command line:

    vertx run com.mycompany.MyVerticle -instances 10

or when programmatically deploying your verticle

    options = {
      'instances' => 10
    }
    vertx.deploy_verticle("com.mycompany.MyVerticle", options)

Once you do this you will find the echo server works functionally identically to before, but all your cores on your server can be utilised and more work can be handled.

At this point you might be asking yourself 'How can you have more than one server listening on the same host and port? Surely you will get port conflicts as soon as you try and deploy more than one instance?'

Vert.x does a little magic here.*

When you deploy another server on the same host and port as an existing server it doesn’t actually try and create a new server listening on the same host/port.

Instead it internally maintains just a single server, and, as incoming connections arrive it distributes them in a round-robin fashion to any of the connect handlers.

Consequently Vert.x TCP servers can scale over available cores while each instance remains single threaded.

### Creating a TCP client

The simplest way to create a TCP client, using all default options is as follows:

    client = vertx.create_net_client()

### Configuring a TCP client

If you don’t want the default, a client can be configured by passing in a `NetClientOptions` instance when creating it:

    options = {
      'connectTimeout' => 10000
    }
    client = vertx.create_net_client(options)

### Making connections

To make a connection to a server you use `connect`, specifying the port and host of the server and a handler that will be called with a result containing the `NetSocket` when connection is successful or with a failure if connection failed.

    options = {
      'connectTimeout' => 10000
    }
    client = vertx.create_net_client(options)
    client.connect(4321, "localhost") { |res_err,res|
      if (res_err == nil)
        puts "Connected!"
        socket = res
      else
        puts "Failed to connect: #{res_err.get_message()}"
      end
    }

### Configuring connection attempts

A client can be configured to automatically retry connecting to the server in the event that it cannot connect. This is configured with `reconnectInterval` and `reconnectAttempts`.

Note | Currently Vert.x will not attempt to reconnect if a connection fails, reconnect attempts and interval only apply to creating initial connections.

    options = {
    }
    options['reconnectAttempts'] = 10['reconnectInterval'] = 500

    client = vertx.create_net_client(options)

By default, multiple connection attempts are disabled.

### Configuring servers and clients to work with SSL/TLS

TCP clients and servers can be configured to use Transport Layer Security - earlier versions of TLS were known as SSL.

The APIs of the servers and clients are identical whether or not SSL/TLS is used, and it’s enabled by configuring the `NetClientOptions` or `NetServerOptions` instances used to create the servers or clients.

#### Enabling SSL/TLS on the server

SSL/TLS is enabled with `ssl`.

By default it is disabled.

#### Specifying key/certificate for the server

SSL/TLS servers usually provide certificates to clients in order verify their identity to clients.

Certificates/keys can be configured for servers in several ways:

The first method is by specifying the location of a Java key-store which contains the certificate and private key.

Java key stores can be managed with the keytool utility which ships with the JDK.

The password for the key store should also be provided:

    options = {
      'ssl' => true,
      'keyStoreOptions' => {
        'path' => "/path/to/your/server-keystore.jks",
        'password' => "password-of-your-keystore"
      }
    }
    server = vertx.create_net_server(options)

Alternatively you can read the key store yourself as a buffer and provide that directly:

    myKeyStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/server-keystore.jks")
    jksOptions = {
      'value' => myKeyStoreAsABuffer,
      'password' => "password-of-your-keystore"
    }
    options = {
      'ssl' => true,
      'keyStoreOptions' => jksOptions
    }
    server = vertx.create_net_server(options)

Key/certificate in PKCS#12 format (http://en.wikipedia.org/wiki/PKCS_12), usually with the `.pfx` or the `.p12` extension can also be loaded in a similar fashion than JKS key stores:

    options = {
      'ssl' => true,
      'pfxKeyCertOptions' => {
        'path' => "/path/to/your/server-keystore.pfx",
        'password' => "password-of-your-keystore"
      }
    }
    server = vertx.create_net_server(options)

Buffer configuration is also supported:

    myKeyStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/server-keystore.pfx")
    pfxOptions = {
      'value' => myKeyStoreAsABuffer,
      'password' => "password-of-your-keystore"
    }
    options = {
      'ssl' => true,
      'pfxKeyCertOptions' => pfxOptions
    }
    server = vertx.create_net_server(options)

Another way of providing server private key and certificate separately using `.pem` files.

    options = {
      'ssl' => true,
      'pemKeyCertOptions' => {
        'keyPath' => "/path/to/your/server-key.pem",
        'certPath' => "/path/to/your/server-cert.pem"
      }
    }
    server = vertx.create_net_server(options)

Buffer configuration is also supported:

    myKeyAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/server-key.pem")
    myCertAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/server-cert.pem")
    pemOptions = {
      'keyValue' => myKeyAsABuffer,
      'certValue' => myCertAsABuffer
    }
    options = {
      'ssl' => true,
      'pemKeyCertOptions' => pemOptions
    }
    server = vertx.create_net_server(options)

Keep in mind that pem configuration, the private key is not crypted.

#### Specifying trust for the server

SSL/TLS servers can use a certificate authority in order to verify the identity of the clients.

Certificate authorities can be configured for servers in several ways:

Java trust stores can be managed with the keytool utility which ships with the JDK.

The password for the trust store should also be provided:

    options = {
      'ssl' => true,
      'clientAuthRequired' => true,
      'trustStoreOptions' => {
        'path' => "/path/to/your/truststore.jks",
        'password' => "password-of-your-truststore"
      }
    }
    server = vertx.create_net_server(options)

Alternatively you can read the trust store yourself as a buffer and provide that directly:

    myTrustStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/truststore.jks")
    options = {
      'ssl' => true,
      'clientAuthRequired' => true,
      'trustStoreOptions' => {
        'value' => myTrustStoreAsABuffer,
        'password' => "password-of-your-truststore"
      }
    }
    server = vertx.create_net_server(options)

Certificate authority in PKCS#12 format (http://en.wikipedia.org/wiki/PKCS_12), usually with the `.pfx` or the `.p12` extension can also be loaded in a similar fashion than JKS trust stores:

    options = {
      'ssl' => true,
      'clientAuthRequired' => true,
      'pfxTrustOptions' => {
        'path' => "/path/to/your/truststore.pfx",
        'password' => "password-of-your-truststore"
      }
    }
    server = vertx.create_net_server(options)

Buffer configuration is also supported:

    myTrustStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/truststore.pfx")
    options = {
      'ssl' => true,
      'clientAuthRequired' => true,
      'pfxTrustOptions' => {
        'value' => myTrustStoreAsABuffer,
        'password' => "password-of-your-truststore"
      }
    }
    server = vertx.create_net_server(options)

Another way of providing server certificate authority using a list `.pem` files.

    options = {
      'ssl' => true,
      'clientAuthRequired' => true,
      'pemTrustOptions' => {
        'certPaths' => [
          "/path/to/your/server-ca.pem"
        ]
      }
    }
    server = vertx.create_net_server(options)

Buffer configuration is also supported:

    myCaAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/server-ca.pfx")
    options = {
      'ssl' => true,
      'clientAuthRequired' => true,
      'pemTrustOptions' => {
        'certValues' => [
          myCaAsABuffer
        ]
      }
    }
    server = vertx.create_net_server(options)

#### Enabling SSL/TLS on the client

Net Clients can also be easily configured to use SSL. They have the exact same API when using SSL as when using standard sockets.

To enable SSL on a NetClient the function setSSL(true) is called.

#### Client trust configuration

If the `trustALl` is set to true on the client, then the client will trust all server certificates. The connection will still be encrypted but this mode is vulnerable to 'man in the middle' attacks. I.e. you can’t be sure who you are connecting to. Use this with caution. Default value is false.

    options = {
      'ssl' => true,
      'trustAll' => true
    }
    client = vertx.create_net_client(options)

If `trustAll` is not set then a client trust store must be configured and should contain the certificates of the servers that the client trusts.

Likewise server configuration, the client trust can be configured in several ways:

The first method is by specifying the location of a Java trust-store which contains the certificate authority.

It is just a standard Java key store, the same as the key stores on the server side. The client trust store location is set by using the function `path` on the `jks options`. If a server presents a certificate during connection which is not in the client trust store, the connection attempt will not succeed.

    options = {
      'ssl' => true,
      'trustStoreOptions' => {
        'path' => "/path/to/your/truststore.jks",
        'password' => "password-of-your-truststore"
      }
    }
    client = vertx.create_net_client(options)

Buffer configuration is also supported:

    myTrustStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/truststore.jks")
    options = {
      'ssl' => true,
      'trustStoreOptions' => {
        'value' => myTrustStoreAsABuffer,
        'password' => "password-of-your-truststore"
      }
    }
    client = vertx.create_net_client(options)

Certificate authority in PKCS#12 format (http://en.wikipedia.org/wiki/PKCS_12), usually with the `.pfx` or the `.p12` extension can also be loaded in a similar fashion than JKS trust stores:

    options = {
      'ssl' => true,
      'pfxTrustOptions' => {
        'path' => "/path/to/your/truststore.pfx",
        'password' => "password-of-your-truststore"
      }
    }
    client = vertx.create_net_client(options)

Buffer configuration is also supported:

    myTrustStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/truststore.pfx")
    options = {
      'ssl' => true,
      'pfxTrustOptions' => {
        'value' => myTrustStoreAsABuffer,
        'password' => "password-of-your-truststore"
      }
    }
    client = vertx.create_net_client(options)

Another way of providing server certificate authority using a list `.pem` files.

    options = {
      'ssl' => true,
      'pemTrustOptions' => {
        'certPaths' => [
          "/path/to/your/ca-cert.pem"
        ]
      }
    }
    client = vertx.create_net_client(options)

Buffer configuration is also supported:

    myTrustStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/ca-cert.pem")
    options = {
      'ssl' => true,
      'pemTrustOptions' => {
        'certValues' => [
          myTrustStoreAsABuffer
        ]
      }
    }
    client = vertx.create_net_client(options)

#### Specifying key/certificate for the client

If the server requires client authentication then the client must present its own certificate to the server when connecting. The client can be configured in several ways:

The first method is by specifying the location of a Java key-store which contains the key and certificate. Again it’s just a regular Java key store. The client keystore location is set by using the function `path` on the `jks options`.

    options = {
      'ssl' => true,
      'keyStoreOptions' => {
        'path' => "/path/to/your/client-keystore.jks",
        'password' => "password-of-your-keystore"
      }
    }
    client = vertx.create_net_client(options)

Buffer configuration is also supported:

    myKeyStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/client-keystore.jks")
    jksOptions = {
      'value' => myKeyStoreAsABuffer,
      'password' => "password-of-your-keystore"
    }
    options = {
      'ssl' => true,
      'keyStoreOptions' => jksOptions
    }
    client = vertx.create_net_client(options)

Key/certificate in PKCS#12 format (http://en.wikipedia.org/wiki/PKCS_12), usually with the `.pfx` or the `.p12` extension can also be loaded in a similar fashion than JKS key stores:

    options = {
      'ssl' => true,
      'pfxKeyCertOptions' => {
        'path' => "/path/to/your/client-keystore.pfx",
        'password' => "password-of-your-keystore"
      }
    }
    client = vertx.create_net_client(options)

Buffer configuration is also supported:

    myKeyStoreAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/client-keystore.pfx")
    pfxOptions = {
      'value' => myKeyStoreAsABuffer,
      'password' => "password-of-your-keystore"
    }
    options = {
      'ssl' => true,
      'pfxKeyCertOptions' => pfxOptions
    }
    client = vertx.create_net_client(options)

Another way of providing server private key and certificate separately using `.pem` files.

    options = {
      'ssl' => true,
      'pemKeyCertOptions' => {
        'keyPath' => "/path/to/your/client-key.pem",
        'certPath' => "/path/to/your/client-cert.pem"
      }
    }
    client = vertx.create_net_client(options)

Buffer configuration is also supported:

    myKeyAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/client-key.pem")
    myCertAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/client-cert.pem")
    pemOptions = {
      'keyValue' => myKeyAsABuffer,
      'certValue' => myCertAsABuffer
    }
    options = {
      'ssl' => true,
      'pemKeyCertOptions' => pemOptions
    }
    client = vertx.create_net_client(options)

Keep in mind that pem configuration, the private key is not crypted.

#### Revoking certificate authorities

Trust can be configured to use a certificate revocation list (CRL) for revoked certificates that should no longer be trusted. The `crlPath` configures the crl list to use:

    options = {
      'ssl' => true,
      'trustStoreOptions' => trustOptions,
      'crlPaths' => [
        "/path/to/your/crl.pem"
      ]
    }
    client = vertx.create_net_client(options)

Buffer configuration is also supported:

    myCrlAsABuffer = vertx.file_system().read_file_blocking("/path/to/your/crl.pem")
    options = {
      'ssl' => true,
      'trustStoreOptions' => trustOptions,
      'crlValues' => [
        myCrlAsABuffer
      ]
    }
    client = vertx.create_net_client(options)

#### Configuring the Cipher suite

By default, the TLS configuration will uses the Cipher suite of the JVM running Vert.x. This Cipher suite can be configured with a suite of enabled ciphers:

    options = {
      'ssl' => true,
      'keyStoreOptions' => keyStoreOptions,
      'enabledCipherSuites' => [
        "ECDHE-RSA-AES128-GCM-SHA256",
        "ECDHE-ECDSA-AES128-GCM-SHA256",
        "ECDHE-RSA-AES256-GCM-SHA384",
        "CDHE-ECDSA-AES256-GCM-SHA384"
      ]
    }
    server = vertx.create_net_server(options)

Cipher suite can be specified on the `NetServerOptions` or `NetClientOptions` configuration.

## Writing HTTP servers and clients

Vert.x allows you to easily write non blocking HTTP clients and servers.

### Creating an HTTP Server

The simplest way to create an HTTP server, using all default options is as follows:

    server = vertx.create_http_server()

### Configuring an HTTP server

If you don’t want the default, a server can be configured by passing in a `HttpServerOptions` instance when creating it:

    options = {
      'maxWebsocketFrameSize' => 1000000
    }

    server = vertx.create_http_server(options)

### Start the Server Listening

To tell the server to listen for incoming requests you use one of the `listen` alternatives.

To tell the server to listen at the host and port as specified in the options:

    server = vertx.create_http_server()
    server.listen()

Or to specify the host and port in the call to listen, ignoring what is configured in the options:

    server = vertx.create_http_server()
    server.listen(8080, "myhost.com")

The default host is `0.0.0.0` which means 'listen on all available addresses' and the default port is `80`.

The actual bind is asynchronous so the server might not actually be listening until some time after the call to listen has returned.

If you want to be notified when the server is actually listening you can provide a handler to the `listen` call. For example:

    server = vertx.create_http_server()
    server.listen(8080, "myhost.com") { |res_err,res|
      if (res_err == nil)
        puts "Server is now listening!"
      else
        puts "Failed to bind!"
      end
    }

### Getting notified of incoming requests

To be notified when a request arrives you need to set a `requestHandler`:

    server = vertx.create_http_server()
    server.request_handler() { |request|
      # Handle the request in here
    }

### Handling requests

When a request arrives, the request handler is called passing in an instance of `HttpServerRequest`. This object represents the server side HTTP request.

The handler is called when the headers of the request have been fully read.

If the request contains a body, that body will arrive at the server some time after the request handler has been called.

The server request object allows you to retrieve the `uri`, `path`, `params` and `headers`, amongst other things.

Each server request object is associated with one server response object. You use `response` to get a reference to the `HttpServerResponse` object.

Here’s a simple example of a server handling a request and replying with "hello world" to it.

    vertx.create_http_server().request_handler() { |request|
      request.response().end("Hello world")
    }.listen(8080)

#### Request version

The version of HTTP specified in the request can be retrieved with `version`

#### Request method

Use `method` to retrieve the HTTP method of the request. (i.e. whether it’s GET, POST, PUT, DELETE, HEAD, OPTIONS, etc).

#### Request URI

Use `uri` to retrieve the URI of the request.

Note that this is the actual URI as passed in the HTTP request, and it’s almost always a relative URI.

The URI is as defined in Section 5.1.2 of the HTTP specification - Request-URI

#### Request path

Use `path` to return the path part of the URI

For example, if the request URI was:

    a/b/c/page.html?param1=abc&param2=xyz

Then the path would be

    /a/b/c/page.html

#### Request query

Use `query` to return the query part of the URI

For example, if the request URI was:

    a/b/c/page.html?param1=abc&param2=xyz

Then the query would be

    param1=abc&param2=xyz

#### Request headers

Use `headers` to return the headers of the HTTP request.

This returns an instance of `MultiMap` - which is like a normal Map or Hash but allows multiple values for the same key - this is because HTTP allows multiple header values with the same key.

It also has case-insensitive keys, that means you can do the following:

    headers = request.headers()

    # Get the User-Agent:
    puts "User agent is #{headers.get("user-agent")}"

    # You can also do this and get the same result:
    puts "User agent is #{headers.get("User-Agent")}"

#### Request parameters

Use `params` to return the parameters of the HTTP request.

Just like `headers` this returns an instance of `MultiMap` as there can be more than one parameter with the same name.

Request parameters are sent on the request URI, after the path. For example if the URI was:

    /page.html?param1=abc&param2=xyz

Then the parameters would contain the following:

    param1: 'abc'
    param2: 'xyz

Note that these request parameters are retrieved from the URL of the request. If you have form attributes that have been sent as part of the submission of an HTML form submitted in the body of a `multi-part/form-data` request then they will not appear in the params here.

#### Remote address

The address of the sender of the request can be retrieved with `remoteAddress`.

#### Absolute URI

The URI passed in an HTTP request is usually relative. If you wish to retrieve the absolute URI corresponding to the request, you can get it with `absoluteURI`

#### End handler

The `endHandler` of the request is invoked when the entire request, including any body has been fully read.

#### Reading Data from the Request Body

Often an HTTP request contains a body that we want to read. As previously mentioned the request handler is called when just the headers of the request have arrived so the request object does not have a body at that point.

This is because the body may be very large (e.g. a file upload) and we don’t generally want to buffer the entire body in memory before handing it to you, as that could cause the server to exhaust available memory.

To receive the body, you can use the `handler` on the request, this will get called every time a chunk of the request body arrives. Here’s an example:

    request.handler() { |buffer|
      puts "I have received a chunk of the body of length #{buffer.length()}"
    }

The object passed into the handler is a `Buffer`, and the handler can be called multiple times as data arrives from the network, depending on the size of the body.

In some cases (e.g. if the body is small) you will want to aggregate the entire body in memory, so you could do the aggregation yourself as follows:

    require 'vertx/buffer'

    # Create an empty buffer
    totalBuffer = Vertx::Buffer.buffer()

    request.handler() { |buffer|
      puts "I have received a chunk of the body of length #{buffer.length()}"
      totalBuffer.append_buffer(buffer)
    }

    request.end_handler() { |v|
      puts "Full body received, length = #{totalBuffer.length()}"
    }

This is such a common case, that Vert.x provides a `bodyHandler` to do this for you. The body handler is called once when all the body has been received:

    request.body_handler() { |totalBuffer|
      puts "Full body received, length = #{totalBuffer.length()}"
    }

#### Pumping requests

The request object is a `ReadStream` so you can pump the request body to any `WriteStream` instance.

See the chapter on streams and pumps for a detailed explanation.

#### Handling HTML forms

HTML forms can be submitted with either a content type of `application/x-www-form-urlencoded` or `multipart/form-data`.

For url encoded forms, the form attributes are encoded in the url, just like normal query parameters.

For multi-part forms they are encoded in the request body, and as such are not available until the entire body has been read from the wire.

Multi-part forms can also contain file uploads.

If you want to retrieve the attributes of a multi-part form you should tell Vert.x that you expect to receive such a form before any of the body is read by calling `setExpectMultipart` with true, and then you should retrieve the actual attributes using `formAttributes` once the entire body has been read:

    server.request_handler() { |request|
      request.set_expect_multipart(true)
      request.end_handler() { |v|
        # The body has now been fully read, so retrieve the form attributes
        formAttributes = request.form_attributes()
      }
    }

#### Handling form file uploads

Vert.x can also handle file uploads which are encoded in a multi-part request body.

To receive file uploads you tell Vert.x to expect a multi-part form and set an `uploadHandler` on the request.

This handler will be called once for every upload that arrives on the server.

The object passed into the handler is a `HttpServerFileUpload` instance.

    server.request_handler() { |request|
      request.set_expect_multipart(true)
      request.upload_handler() { |upload|
        puts "Got a file upload #{upload.name()}"
      }
    }

File uploads can be large we don’t provide the entire upload in a single buffer as that might result in memory exhaustion, instead, the upload data is received in chunks:

    request.upload_handler() { |upload|
      upload.handler() { |chunk|
        puts "Received a chunk of the upload of length #{chunk.length()}"
      }
    }

The upload object is a `ReadStream` so you can pump the request body to any `WriteStream` instance. See the chapter on streams and pumps for a detailed explanation.

If you just want to upload the file to disk somewhere you can use `streamToFileSystem`:

    request.upload_handler() { |upload|
      upload.stream_to_file_system("myuploads_directory/#{upload.filename()}")
    }

Warning | Make sure you check the filename in a production system to avoid malicious clients uploading files to arbitrary places on your filesystem. See security notes for more information.

### Sending back responses

The server response object is an instance of `HttpServerResponse` and is obtained from the request with `response`.

You use the response object to write a response back to the HTTP client.

#### Setting status code and message

The default HTTP status code for a response is `200`, representing `OK`.

Use `setStatusCode` to set a different code.

You can also specify a custom status message with `setStatusMessage`.

If you don’t specify a status message, the default one corresponding to the status code will be used.

#### Writing HTTP responses

To write data to an HTTP response, you use one the `write` operations.

These can be invoked multiple times before the response is ended. They can be invoked in a few ways:

With a single buffer:

    response = request.response()
    response.write(buffer)

With a string. In this case the string will encoded using UTF-8 and the result written to the wire.

    response = request.response()
    response.write("hello world!")

With a string and an encoding. In this case the string will encoded using the specified encoding and the result written to the wire.

    response = request.response()
    response.write("hello world!", "UTF-16")

Writing to a response is asynchronous and always returns immediately after the write has been queued.

If you are just writing a single string or buffer to the HTTP response you can write it and end the response in a single call to the `end`

The first call to write results in the response header being being written to the response. Consequently, if you are not using HTTP chunking then you must set the `Content-Length` header before writing to the response, since it will be too late otherwise. If you are using HTTP chunking you do not have to worry.

#### Ending HTTP responses

Once you have finished with the HTTP response you should `end` it.

This can be done in several ways:

With no arguments, the response is simply ended.

    response = request.response()
    response.write("hello world!")
    response.end()

It can also be called with a string or buffer in the same way `write` is called. In this case it’s just the same as calling write with a string or buffer followed by calling end with no arguments. For example:

    response = request.response()
    response.end("hello world!")

#### Closing the underlying connection

You can close the underlying TCP connection with `close`.

Non keep-alive connections will be automatically closed by Vert.x when the response is ended.

Keep-alive connections are not automatically closed by Vert.x by default. If you want keep-alive connections to be closed after an idle time, then you configure `idleTimeout`.

#### Setting response headers

HTTP response headers can be added to the response by adding them directly to the `headers`:

    response = request.response()
    headers = response.headers()
    headers.set("content-type", "text/html")
    headers.set("other-header", "wibble")

Or you can use `putHeader`

    response = request.response()
    response.put_header("content-type", "text/html").put_header("other-header", "wibble")

Headers must all be added before any parts of the response body are written.

#### Chunked HTTP responses and trailers

Vert.x supports HTTP Chunked Transfer Encoding.

This allows the HTTP response body to be written in chunks, and is normally used when a large response body is being streamed to a client and the total size is not known in advance.

You put the HTTP response into chunked mode as follows:

    response = request.response()
    response.set_chunked(true)

Default is non-chunked. When in chunked mode, each call to one of the `write` methods will result in a new HTTP chunk being written out.

When in chunked mode you can also write HTTP response trailers to the response. These are actually written in the final chunk of the response.

To add trailers to the response, add them directly to the `trailers`.

    response = request.response()
    response.set_chunked(true)
    trailers = response.trailers()
    trailers.set("X-wibble", "woobble").set("X-quux", "flooble")

Or use `putTrailer`.

    response = request.response()
    response.set_chunked(true)
    response.put_trailer("X-wibble", "woobble").put_trailer("X-quux", "flooble")

#### Serving files directly from disk

If you were writing a web server, one way to serve a file from disk would be to open it as an `AsyncFile` and pump it to the HTTP response.

Or you could load it it one go using `readFile` and write it straight to the response.

Alternatively, Vert.x provides a method which allows you to serve a file from disk to an HTTP response in one operation. Where supported by the underlying operating system this may result in the OS directly transferring bytes from the file to the socket without being copied through user-space at all.

This is done by using `sendFile`, and is usually more efficient for large files, but may be slower for small files.

Here’s a very simple web server that serves files from the file system using sendFile:

    vertx.create_http_server().request_handler() { |request|
      file = ""
      if (request.path().==("/"))
        file = "index.html"
      elsif (!request.path().contains?(".."))
        file = request.path()
      end
      request.response().send_file("web/#{file}")
    }.listen(8080)

Sending a file is asynchronous and may not complete until some time after the call has returned. If you want to be notified when the file has been writen you can use `sendFile`

Note | If you use `sendFile` while using HTTPS it will copy through user-space, since if the kernel is copying data directly from disk to socket it doesn’t give us an opportunity to apply any encryption.

Warning | If you’re going to write web servers directly using Vert.x be careful that users cannot exploit the path to access files outside the directory from which you want to serve them. It may be safer instead to use Vert.x Web.

#### Pumping responses

The server response is a `WriteStream` instance so you can pump to it from any `ReadStream`, e.g. `AsyncFile`, `NetSocket`, `WebSocket` or `HttpServerRequest`.

Here’s an example which echoes the request body back in the response for any PUT methods. It uses a pump for the body, so it will work even if the HTTP request body is much larger than can fit in memory at any one time:

    require 'vertx/pump'
    vertx.create_http_server().request_handler() { |request|
      response = request.response()
      if (request.method() == :PUT)
        response.set_chunked(true)
        Vertx::Pump.pump(request, response).start()
        request.end_handler() { |v|
          response.end()
        }
      else
        response.set_status_code(400).end()
      end
    }.listen(8080)

### HTTP Compression

Vert.x comes with support for HTTP Compression out of the box.

This means you are able to automatically compress the body of the responses before they are sent back to the client.

If the client does not support HTTP compression the responses are sent back without compressing the body.

This allows to handle Client that support HTTP Compression and those that not support it at the same time.

To enable compression use can configure it with `compressionSupported`.

By default compression is not enabled.

When HTTP compression is enabled the server will check if the client incldes an `Accept-Encoding` header which includes the supported compressions. Commonly used are deflate and gzip. Both are supported by Vert.x.

If such a header is found the server will automatically compress the body of the response with one of the supported compressions and send it back to the client.

Be aware that compression may be able to reduce network traffic but is more CPU-intensive.

### Creating an HTTP client

You create an `HttpClient` instance with default options as follows:

    client = vertx.create_http_client()

If you want to configure options for the client, you create it as follows:

    options = {
      'keepAlive' => false
    }
    client = vertx.create_http_client(options)

### Making requests

The http client is very flexible and there are various ways you can make requests with it.

Often you want to make many requests to the same host/port with an http client. To avoid you repeating the host/port every time you make a request you can configure the client with a default host/port:

    # Set the default host
    options = {
      'defaultHost' => "wibble.com"
    }
    # Can also set default port if you want...
    client = vertx.create_http_client(options)
    client.get_now("/some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }

Alternatively if you find yourself making lots of requests to different host/ports with the same client you can simply specify the host/port when doing the request.

    client = vertx.create_http_client()

    # Specify both port and host name
    client.get_now(8080, "myserver.mycompany.com", "/some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }

    # This time use the default port 80 but specify the host name
    client.get_now("foo.othercompany.com", "/other-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }

Both methods of specifying host/port are supported for all the different ways of making requests with the client.

#### Simple requests with no request body

Often, you’ll want to make HTTP requests with no request body. This is usually the case with HTTP GET, OPTIONS and HEAD requests.

The simplest way to do this with the Vert.x http client is using the methods prefixed with `Now`. For example `getNow`.

These methods create the http request and send it in a single method call and allow you to provide a handler that will be called with the http response when it comes back.

    client = vertx.create_http_client()

    # Send a GET request
    client.get_now("/some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }

    # Send a GET request
    client.head_now("/other-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }

#### Writing general requests

At other times you don’t know the request method you want to send until run-time. For that use case we provide general purpose request methods such as `request` which allow you to specify the HTTP method at run-time:

    client = vertx.create_http_client()

    client.request(:GET, "some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }.end()

    client.request(:POST, "foo-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }.end("some-data")

#### Writing request bodies

Sometimes you’ll want to write requests which have a body, or perhaps you want to write headers to a request before sending it.

To do this you can call one of the specific request methods such as `post` or one of the general purpose request methods such as `request`.

These methods don’t send the request immediately, but instead return an instance of `HttpClientRequest` which can be used to write to the request body or write headers.

Here are some examples of writing a POST request with a body: m

    client = vertx.create_http_client()

    request = client.post("some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }

    # Now do stuff with the request
    request.put_header("content-length", "1000")
    request.put_header("content-type", "text/plain")
    request.write(body)

    # Make sure the request is ended when you're done with it
    request.end()

    # Or fluently:

    client.post("some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }.put_header("content-length", "1000").put_header("content-type", "text/plain").write(body).end()

    # Or event more simply:

    client.post("some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }.put_header("content-type", "text/plain").end(body)

Methods exist to write strings in UTF-8 encoding and in any specific encoding and to write buffers:

    require 'vertx/buffer'

    # Write string encoded in UTF-8
    request.write("some data")

    # Write string encoded in specific encoding
    request.write("some other data", "UTF-16")

    # Write a buffer
    buffer = Vertx::Buffer.buffer()
    buffer.append_int(123).append_long(245)
    request.write(buffer)

If you are just writing a single string or buffer to the HTTP request you can write it and end the request in a single call to the `end` function.

    require 'vertx/buffer'

    # Write string and end the request (send it) in a single call
    request.end("some simple data")

    # Write buffer and end the request (send it) in a single call
    buffer = Vertx::Buffer.buffer().append_double(12.34).append_long(432)
    request.end(buffer)

When you’re writing to a request, the first call to `write` will result in the request headers being written out to the wire.

The actual write is asynchronous and might not occur until some time after the call has returned.

Non-chunked HTTP requests with a request body require a `Content-Length` header to be provided.

Consequently, if you are not using chunked HTTP then you must set the `Content-Length` header before writing to the request, as it will be too late otherwise.

If you are calling one of the `end` methods that take a string or buffer then Vert.x will automatically calculate and set the `Content-Length` header before writing the request body.

If you are using HTTP chunking a a `Content-Length` header is not required, so you do not have to calculate the size up-front.

#### Writing request headers

You can write headers to a request using the `headers` multi-map as follows:

    # Write some headers using the headers() multimap

    headers = request.headers()
    headers.set("content-type", "application/json").set("other-header", "foo")

The headers are an instance of `MultiMap` which provides operations for adding, setting and removing entries. Http headers allow more than one value for a specific key.

You can also write headers using `putHeader`

    # Write some headers using the putHeader method

    request.put_header("content-type", "application/json").put_header("other-header", "foo")

If you wish to write headers to the request you must do so before any part of the request body is written.

#### Ending HTTP requests

Once you have finished with the HTTP request you must end it with one of the `end` operations.

Ending a request causes any headers to be written, if they have not already been written and the request to be marked as complete.

Requests can be ended in several ways. With no arguments the request is simply ended:

    request.end()

Or a string or buffer can be provided in the call to `end`. This is like calling `write` with the string or buffer before calling `end` with no arguments

    require 'vertx/buffer'
    # End the request with a string
    request.end("some-data")

    # End it with a buffer
    buffer = Vertx::Buffer.buffer().append_float(12.3).append_int(321)
    request.end(buffer)

#### Chunked HTTP requests

Vert.x supports HTTP Chunked Transfer Encoding for requests.

This allows the HTTP request body to be written in chunks, and is normally used when a large request body is being streamed to the server, whose size is not known in advance.

You put the HTTP request into chunked mode using `setChunked`.

In chunked mode each call to write will cause a new chunk to be written to the wire. In chunked mode there is no need to set the `Content-Length` of the request up-front.

    request.set_chunked(true)

    # Write some chunks
    i = 0
    while (i < 10)
      request.write("this-is-chunk-#{i}")
      i+=1
    end

    request.end()

#### Request timeouts

You can set a timeout for a specific http request using `setTimeout`.

If the request does not return any data within the timeout period an exception will be passed to the exception handler (if provided) and the request will be closed.

#### Handling exceptions

You can handle exceptions corresponding to a request by setting an exception handler on the `HttpClientRequest` instance:

    request = client.post("some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }
    request.exception_handler() { |e|
      puts "Received exception: #{e.get_message()}"
      e.print_stack_trace()
    }

This does not handle non 2xx response that need to be handled in the `HttpClientResponse` code:

    request = client.post("some-uri") { |response|
      if (response.status_code() == 200)
        puts "Everything fine"
        return
      end
      if (response.status_code() == 500)
        puts "Unexpected behavior on the server side"
        return
      end
    }
    request.end()

Important | `XXXNow` methods cannot receive an exception handler.

#### Specifying a handler on the client request

Instead of providing a response handler in the call to create the client request object, alternatively, you can not provide a handler when the request is created and set it later on the request object itself, using `handler`, for example:

    request = client.post("some-uri")
    request.handler() { |response|
      puts "Received response with status code #{response.status_code()}"
    }

#### Using the request as a stream

The `HttpClientRequest` instance is also a `WriteStream` which means you can pump to it from any `ReadStream` instance.

For, example, you could pump a file on disk to a http request body as follows:

    require 'vertx/pump'

    request.set_chunked(true)
    pump = Vertx::Pump.pump(file, request)
    file.end_handler() { |v|
      request.end()
    }
    pump.start()

### Handling http responses

You receive an instance of `HttpClientResponse` into the handler that you specify in of the request methods or by setting a handler directly on the `HttpClientRequest` object.

You can query the status code and the status message of the response with `statusCode` and `statusMessage`.

    client.get_now("some-uri") { |response|
      # the status code - e.g. 200 or 404
      puts "Status code is #{response.status_code()}"

      # the status message e.g. "OK" or "Not Found".
      puts "Status message is #{response.status_message()}"
    }

#### Using the response as a stream

The `HttpClientResponse` instance is also a `ReadStream` which means you can pump it to any `WriteStream` instance.

#### Response headers and trailers

Http responses can contain headers. Use `headers` to get the headers.

The object returned is a `MultiMap` as HTTP headers can contain multiple values for single keys.

    contentType = response.headers().get("content-type")
    contentLength = response.headers().get("content-lengh")

Chunked HTTP responses can also contain trailers - these are sent in the last chunk of the response body.

You use `trailers` to get the trailers. Trailers are also a `MultiMap`.

#### Reading the request body

The response handler is called when the headers of the response have been read from the wire.

If the response has a body this might arrive in several pieces some time after the headers have been read. We don’t wait for all the body to arrive before calling the response handler as the response could be very large and we might be waiting a long time, or run out of memory for large responses.

As parts of the response body arrive, the `handler` is called with a `Buffer` representing the piece of the body:

    client.get_now("some-uri") { |response|

      response.handler() { |buffer|
        puts "Received a part of the response body: #{buffer}"
      }
    }

If you know the response body is not very large and want to aggregate it all in memory before handling it, you can either aggregate it yourself:

    require 'vertx/buffer'

    client.get_now("some-uri") { |response|

      # Create an empty buffer
      totalBuffer = Vertx::Buffer.buffer()

      response.handler() { |buffer|
        puts "Received a part of the response body: #{buffer.length()}"

        totalBuffer.append_buffer(buffer)
      }

      response.end_handler() { |v|
        # Now all the body has been read
        puts "Total response body length is #{totalBuffer.length()}"
      }
    }

Or you can use the convenience `bodyHandler` which is called with the entire body when the response has been fully read:

    client.get_now("some-uri") { |response|

      response.body_handler() { |totalBuffer|
        # Now all the body has been read
        puts "Total response body length is #{totalBuffer.length()}"
      }
    }

#### Response end handler

The response `endHandler` is called when the entire response body has been read or immediately after the headers have been read and the response handler has been called if there is no body.

#### Reading cookies from the response

You can retrieve the list of cookies from a response using `cookies`.

Alternatively you can just parse the `Set-Cookie` headers yourself in the response.

#### 100-Continue handling

According to the HTTP 1.1 specification a client can set a header `Expect: 100-Continue` and send the request header before sending the rest of the request body.

The server can then respond with an interim response status `Status: 100 (Continue)` to signify to the client that it is ok to send the rest of the body.

The idea here is it allows the server to authorise and accept/reject the request before large amounts of data are sent. Sending large amounts of data if the request might not be accepted is a waste of bandwidth and ties up the server in reading data that it will just discard.

Vert.x allows you to set a `continueHandler` on the client request object

This will be called if the server sends back a `Status: 100 (Continue)` response to signify that it is ok to send the rest of the request.

This is used in conjunction with `sendHead`to send the head of the request.

Here’s an example:

    request = client.put("some-uri") { |response|
      puts "Received response with status code #{response.status_code()}"
    }

    request.put_header("Expect", "100-Continue")

    request.continue_handler() { |v|
      # OK to send rest of body
      request.write("Some data")
      request.write("Some more data")
      request.end()
    }

### Enabling compression on the client

The http client comes with support for HTTP Compression out of the box.

This means the client can let the remote http server know that it supports compression, and will be able to handle compressed response bodies.

An http server is free to either compress with one of the supported compression algorithms or to send the body back without compressing it at all. So this is only a hint for the Http server which it may ignore at will.

To tell the http server which compression is supported by the client it will include an `Accept-Encoding` header with the supported compression algorithm as value. Multiple compression algorithms are supported. In case of Vert.x this will result in the following header added:

    Accept-Encoding: gzip, deflate

The server will choose then from one of these. You can detect if a server ompressed the body by checking for the `Content-Encoding` header in the response sent back from it.

If the body of the response was compressed via gzip it will include for example the following header:

    Content-Encoding: gzip

To enable compression set `tryUseCompression` on the options used when creating the client.

By default compression is disabled.

### Pooling and keep alive

Http keep alive allows http connections to be used for more than one request. This can be a more efficient use of connections when you’re making multiple requests to the same server.

The http client supports pooling of connections, allowing you to reuse connections between requests.

For pooling to work, keep alive must be true using `keepAlive` on the options used when configuring the client. The default value is true.

When keep alive is enabled. Vert.x will add a `Connection: Keep-Alive` header to each HTTP request sent.

The maximum number of connections to pool for each server is configured using `maxPoolSize`

When making a request with pooling enabled, Vert.x will create a new connection if there are less than the maximum number of connections already created for that server, otherwise it will add the request to a queue.

When a response returns, if there are pending requests for the server, then the connection will be reused, otherwise it will be closed.

This gives the benefits of keep alive when the client is loaded but means we don’t keep connections hanging around unnecessarily when there would be no benefits anyway.

### Pipe-lining

The client also supports pipe-lining of requests on a connection.

Pipe-lining means another request is sent on the same connection before the response from the preceding one has returned. Pipe-lining is not appropriate for all requests.

To enable pipe-lining, it must be enabled using `pipelining`. By default pipe-lining is disabled.

When pipe-lining is enabled requests will be written to connections without waiting for previous responses to return.

When pipe-line responses return at the client, the connection will be automatically closed when all in-flight responses have returned and there are no outstanding pending requests to write.

### Server sharing

When several HTTP servers listen on the same port, vert.x orchestrates the request handling using a round-robin strategy.

Let’s take a verticle creating a HTTP server such as:

io.vertx.examples.http.sharing.HttpServerVerticle

    vertx.create_http_server().request_handler() { |request|
      request.response().end("Hello from server #{self}")
    }.listen(8080)

This service is listening on the port 8080. So, when this verticle is instantiated multiple times as with: `vertx run io.vertx.examples.http.sharing.HttpServerVerticle -instances 2`, what’s happening ? If both verticles would bind to the same port, you would receive a socket exception. Fortunately, vert.x is handling this case for you. When you deploy another server on the same host and port as an existing server it doesn’t actually try and create a new server listening on the same host/port. It binds only once to the socket. When receiving a request it calls the server handlers following a round robin strategy.

Let’s now imagine a client such as:

    vertx.set_periodic(100) { |l|
      vertx.create_http_client().get_now(8080, "localhost", "/") { |resp|
        resp.body_handler() { |body|
          puts body.to_string("ISO-8859-1")
        }
      }
    }

Vert.x delegates the requests to one of the server sequentially:

    Hello from i.v.e.h.s.HttpServerVerticle@1
    Hello from i.v.e.h.s.HttpServerVerticle@2
    Hello from i.v.e.h.s.HttpServerVerticle@1
    Hello from i.v.e.h.s.HttpServerVerticle@2
    ...

Consequently the servers can scale over available cores while each Vert.x verticle instance remains strictly single threaded, and you don’t have to do any special tricks like writing load-balancers in order to scale your server on your multi-core machine.

### Using HTTPS with Vert.x

Vert.x http servers and clients can be configured to use HTTPS in exactly the same way as net servers.

Please see configuring net servers to use SSL for more information.

### WebSockets

WebSockets are a web technology that allows a full duplex socket-like connection between HTTP servers and HTTP clients (typically browsers).

Vert.x supports WebSockets on both the client and server-side.

#### WebSockets on the server

There are two ways of handling WebSockets on the server side.

##### WebSocket handler

The first way involves providing a `websocketHandler` on the server instance.

When a WebSocket connection is made to the server, the handler will be called, passing in an instance of `ServerWebSocket`.

    server.websocket_handler() { |websocket|
      puts "Connected!"
    }

You can choose to reject the WebSocket by calling `reject`.

    server.websocket_handler() { |websocket|
      if (websocket.path().==("/myapi"))
        websocket.reject()
      else
        # Do something
      end
    }

##### Upgrading to WebSocket

The second way of handling WebSockets is to handle the HTTP Upgrade request that was sent from the client, and call `upgrade` on the server request.

    server.request_handler() { |request|
      if (request.path().==("/myapi"))

        websocket = request.upgrade()
        # Do something

      else
        # Reject
        request.response().set_status_code(400).end()
      end
    }

##### The server WebSocket

The `ServerWebSocket` instance enables you to retrieve the `headers`, `path` path}, `query` and `uri` URI} of the HTTP request of the WebSocket handshake.

#### WebSockets on the client

The Vert.x `HttpClient` supports WebSockets.

You can connect a WebSocket to a server using one of the `websocket` operations and providing a handler.

The handler will be called with an instance of `WebSocket` when the connection has been made:

    client.websocket("/some-uri") { |websocket|
      puts "Connected!"
    }

#### Writing messages to WebSockets

If you wish to write a single binary WebSocket message to the WebSocket you can do this with `writeBinaryMessage`:

    require 'vertx/buffer'
    # Write a simple message
    buffer = Vertx::Buffer.buffer().append_int(123).append_float(1.23)

    websocket.write_binary_message(buffer)

If the WebSocket message is larger than the maximum websocket frame size as configured with `maxWebsocketFrameSize` then Vert.x will split it into multiple WebSocket frames before sending it on the wire.

#### Writing frames to WebSockets

A WebSocket message can be composed of multiple frames. In this case the first frame is either a binary or text frame followed by zero or more continuation frames.

The last frame in the message is marked as final.

To send a message consisting of multiple frames you create frames using `WebSocketFrame.binaryFrame` , `WebSocketFrame.textFrame` or `WebSocketFrame.continuationFrame` and write them to the WebSocket using `writeFrame`.

Here’s an example for binary frames:

    require 'vertx/web_socket_frame'

    frame1 = Vertx::WebSocketFrame.binary_frame(buffer1, false)
    websocket.write_frame(frame1)

    frame2 = Vertx::WebSocketFrame.continuation_frame(buffer2, false)
    websocket.write_frame(frame2)

    # Write the final frame
    frame3 = Vertx::WebSocketFrame.continuation_frame(buffer2, true)
    websocket.write_frame(frame3)

In many cases you just want to send a websocket message that consists of a single final frame, so we provide a couple of shortcut methods to do that with `writeFinalBinaryFrame` and `writeFinalTextFrame`.

Here’s an example:

    require 'vertx/buffer'

    # Send a websocket messages consisting of a single final text frame:

    websocket.write_final_text_frame("Geronimo!")

    # Send a websocket messages consisting of a single final binary frame:

    buff = Vertx::Buffer.buffer().append_int(12).append_string("foo")

    websocket.write_final_binary_frame(buff)

#### Reading frames from WebSockets

To read frames from a WebSocket you use the `frameHandler`.

The frame handler will be called with instances of `WebSocketFrame` when a frame arrives, for example:

    websocket.frame_handler() { |frame|
      puts "Received a frame of size!"
    }

#### Closing WebSockets

Use `close` to close the WebSocket connection when you have finished with it.

#### Streaming WebSockets

The `WebSocket` instance is also a `ReadStream` and a `WriteStream` so it can be used with pumps.

When using a WebSocket as a write stream or a read stream it can only be used with WebSockets connections that are used with binary frames that are no split over multiple frames.

### Automatic clean-up in verticles

If you’re creating http servers and clients from inside verticles, those servers and clients will be automatically closed when the verticle is undeployed.

## Using Shared Data with Vert.x

Shared data contains functionality that allows you to safely share data between different parts of your application, or 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.

### Local shared maps

`Local shared maps` allow you to share data safely between different event loops (e.g. different verticles) in the same Vert.x instance.

Local shared maps only allow certain data types to be used as keys and values. Those types must either be immutable, or certain other types that can be copied like `Buffer`. In the latter case the key/value will be copied before putting it in the map.

This way we can ensure there is no shared access to mutable state between different threads in your Vert.x application so you don’t have to worry about protecting that state by synchronising access to it.

Here’s an example of using a shared local map:

    require 'vertx/buffer'

    sd = vertx.shared_data()

    map1 = sd.get_local_map("mymap1")

    map1.put("foo", "bar")

    map2 = sd.get_local_map("mymap2")

    map2.put("eek", Vertx::Buffer.buffer().append_int(123))

    # Then... in another part of your application:

    map1 = sd.get_local_map("mymap1")

    val = map1.get("foo")

    map2 = sd.get_local_map("mymap2")

    buff = map2.get("eek")

### Cluster-wide asynchronous maps

Cluster-wide asynchronous maps allow data to be put in the map from any node of the cluster and retrieved from any other node.

This makes them really useful for things like storing session state in a farm of servers hosting a Vert.x web application.

You get an instance of `AsyncMap` with `getClusterWideMap`.

Getting the map is asynchronous and the result is returned to you in the handler that you specify. Here’s an example:

    sd = vertx.shared_data()

    sd.get_cluster_wide_map("mymap") { |res_err,res|
      if (res_err == nil)
        map = res
      else
        # Something went wrong!
      end
    }

#### Putting data in a map

You put data in a map with `put`.

The actual put is asynchronous and the handler is notified once it is complete:

    map.put("foo", "bar") { |resPut_err,resPut|
      if (resPut_err == nil)
        # Successfully put the value
      else
        # Something went wrong!
      end
    }

#### Getting data from a map

You get data from a map with `get`.

The actual get is asynchronous and the handler is notified with the result some time later

    map.get("foo") { |resGet_err,resGet|
      if (resGet_err == nil)
        # Successfully got the value
        val = resGet
      else
        # Something went wrong!
      end
    }

##### Other map operations

You can also remove entries from an asynchronous map, clear them and get the size.

See the `API docs` for more information.

### Cluster-wide locks

`Cluster wide locks` allow you to obtain exclusive locks across the cluster - this is useful when you want to do something or access a resource on only one node of a cluster at any one time.

Cluster wide locks have an asynchronous API unlike most lock APIs which block the calling thread until the lock is obtained.

To obtain a lock use `getLock`.

This won’t block, but when the lock is available, the handler will be called with an instance of `Lock`, signifying that you now own the lock.

While you own the lock no other caller, anywhere on the cluster will be able to obtain the lock.

When you’ve finished with the lock, you call `release` to release it, so another caller can obtain it.

    sd.get_lock("mylock") { |res_err,res|
      if (res_err == nil)
        # Got the lock!
        lock = res

        # 5 seconds later we release the lock so someone else can get it

        vertx.set_timer(5000) { |tid|
          lock.release()
        }

      else
        # Something went wrong
      end
    }

You can also get a lock with a timeout. If it fails to obtain the lock within the timeout the handler will be called with a failure:

    sd.get_lock_with_timeout("mylock", 10000) { |res_err,res|
      if (res_err == nil)
        # Got the lock!
        lock = res

      else
        # Failed to get lock
      end
    }

### Cluster-wide counters

It’s often useful to maintain an atomic counter across the different nodes of your application.

You can do this with `Counter`.

You obtain an instance with `getCounter`:

    sd.get_counter("mycounter") { |res_err,res|
      if (res_err == nil)
        counter = res
      else
        # Something went wrong!
      end
    }

Once you have an instance you can retrieve the current count, atomically increment it, decrement and add a value to it using the various methods.

See the `API docs` for more information.

## Using the file system with Vert.x

The Vert.x `FileSystem` object provides many operations for manipulating the file system.

There is one file system object per Vert.x instance, and you obtain it with `fileSystem`.

A blocking and a non blocking version of each operation is provided. The non blocking versions take a handler which is called when the operation completes or an error occurs.

Here’s an example of an asynchronous copy of a file:

    fs = vertx.file_system()

    # Copy file from foo.txt to bar.txt
    fs.copy("foo.txt", "bar.txt") { |res_err,res|
      if (res_err == nil)
        # Copied ok!
      else
        # Something went wrong
      end
    }

The blocking versions are named `xxxBlocking` and return the results or throw exceptions directly. In many cases, depending on the operating system and file system, some of the potentially blocking operations can return quickly, which is why we provide them, but it’s highly recommended that you test how long they take to return in your particular application before using them from an event loop, so as not to break the Golden Rule.

Here’s the copy using the blocking API:

    fs = vertx.file_system()

    # Copy file from foo.txt to bar.txt synchronously
    fs.copy_blocking("foo.txt", "bar.txt")

Many operations exist to copy, move, truncate, chmod and many other file operations. We won’t list them all here, please consult the `API docs` for the full list.

Let’s see a couple of examples using asynchronous methods:

    require 'vertx/vertx'
    require 'vertx/buffer'
    vertx = Vertx::Vertx.vertx()

    # Read a file
    vertx.file_system().read_file("target/classes/readme.txt") { |result_err,result|
      if (result_err == nil)
        puts result
      else
        STDERR.puts "Oh oh ...#{result_err}"
      end
    }

    # Copy a file
    vertx.file_system().copy("target/classes/readme.txt", "target/classes/readme2.txt") { |result_err,result|
      if (result_err == nil)
        puts "File copied"
      else
        STDERR.puts "Oh oh ...#{result_err}"
      end
    }

    # Write a file
    vertx.file_system().write_file("target/classes/hello.txt", Vertx::Buffer.buffer("Hello")) { |result_err,result|
      if (result_err == nil)
        puts "File written"
      else
        STDERR.puts "Oh oh ...#{result_err}"
      end
    }

    # Check existence and delete
    vertx.file_system().exists("target/classes/junk.txt") { |result_err,result|
      if (result_err == nil && result)
        vertx.file_system().delete("target/classes/junk.txt") { |r_err,r|
          puts "File deleted"
        }
      else
        STDERR.puts "Oh oh ... - cannot delete the file: #{result_err}"
      end
    }

### Asynchronous files

Vert.x provides an asynchronous file abstraction that allows you to manipulate a file on the file system.

You open an `AsyncFile` as follows:

    options = {
    }
    fileSystem.open("myfile.txt", options) { |res_err,res|
      if (res_err == nil)
        file = res
      else
        # Something went wrong!
      end
    }

`AsyncFile` implements `ReadStream` and `WriteStream` so you can pump files to and from other stream objects such as net sockets, http requests and responses, and WebSockets.

They also allow you to read and write directly to them.

#### Random access writes

To use an `AsyncFile` for random access writing you use the `write` method.

The parameters to the method are:

- `buffer`: the buffer to write.

- `position`: an integer position in the file where to write the buffer. If the position is greater or equal to the size of the file, the file will be enlarged to accommodate the offset.

- `handler`: the result handler

Here is an example of random access writes:

    require 'vertx/vertx'
    require 'vertx/buffer'
    vertx = Vertx::Vertx.vertx()
    vertx.file_system().open("target/classes/hello.txt", {
    }) { |result_err,result|
      if (result_err == nil)
        file = result
        buff = Vertx::Buffer.buffer("foo")
        i = 0
        while (i < 5)
          file.write(buff, buff.length() * i) { |ar_err,ar|
            if (ar_err == nil)
              puts "Written ok!"
              # etc
            else
              STDERR.puts "Failed to write: #{ar_err}"
            end
          }
          i+=1
        end
      else
        STDERR.puts "Cannot open file #{result_err}"
      end
    }

#### Random access reads

To use an `AsyncFile` for random access reads you use the `read` method.

The parameters to the method are:

- `buffer`: the buffer into which the data will be read.

- `offset`: an integer offset into the buffer where the read data will be placed.

- `position`: the position in the file where to read data from.

- `length`: the number of bytes of data to read

- `handler`: the result handler

Here’s an example of random access reads:

    require 'vertx/vertx'
    require 'vertx/buffer'
    vertx = Vertx::Vertx.vertx()
    vertx.file_system().open("target/classes/les_miserables.txt", {
    }) { |result_err,result|
      if (result_err == nil)
        file = result
        buff = Vertx::Buffer.buffer(1000)
        i = 0
        while (i < 10)
          file.read(buff, i * 100, i * 100, 100) { |ar_err,ar|
            if (ar_err == nil)
              puts "Read ok!"
            else
              STDERR.puts "Failed to write: #{ar_err}"
            end
          }
          i+=1
        end
      else
        STDERR.puts "Cannot open file #{result_err}"
      end
    }

#### Opening Options

When opening an `AsyncFile`, you pass an `OpenOptions` instance. These options describe the behavior of the file access. For instance, you can configure the file permissions with the `read`, `write` and `perms` methods.

You can also configure the behavior if the open file already exists with `createNew` and `truncateExisting`.

You can also mark the file to be deleted on close or when the JVM is shutdown with `deleteOnClose`.

#### Flushing data to underlying storage.

In the `OpenOptions`, you can enable/disable the automatic synchronisation of the content on every write using `DSync`. In that case, you can manually flush any writes from the OS cache by calling the `flush` method.

This method can also be called with an handler which will be called when the flush is complete.

#### Using AsyncFile as ReadStream and WriteStream

`AsyncFile` implements `ReadStream` and `WriteStream`. You can then use them with a pump to pump data to and from other read and write streams. For example, this would copy the content to another `AsyncFile`:

    require 'vertx/vertx'
    require 'vertx/pump'
    vertx = Vertx::Vertx.vertx()
    output = vertx.file_system().open_blocking("target/classes/plagiary.txt", {
    })

    vertx.file_system().open("target/classes/les_miserables.txt", {
    }) { |result_err,result|
      if (result_err == nil)
        file = result
        Vertx::Pump.pump(file, output).start()
        file.end_handler() { |r|
          puts "Copy done"
        }
      else
        STDERR.puts "Cannot open file #{result_err}"
      end
    }

You can also use the pump to write file content into HTTP responses, or more generally in any `WriteStream`.

#### Closing an AsyncFile

To close an `AsyncFile` call the `close` method. Closing is asynchronous and if you want to be notified when the close has been completed you can specify a handler function as an argument.

## Datagram sockets (UDP)

Using User Datagram Protocol (UDP) with Vert.x is a piece of cake.

UDP is a connection-less transport which basically means you have no persistent connection to a remote peer.

Instead you can send and receive packages and the remote address is contained in each of them.

Beside this UDP is not as safe as TCP to use, which means there are no guarantees that a send Datagram packet will receive it’s endpoint at all.

The only guarantee is that it will either receive complete or not at all.

Also you usually can’t send data which is bigger then the MTU size of your network interface, this is because each packet will be send as one packet.

But be aware even if the packet size is smaller then the MTU it may still fail.

At which size it will fail depends on the Operating System etc. So rule of thumb is to try to send small packets.

Because of the nature of UDP it is best fit for Applications where you are allowed to drop packets (like for example a monitoring application).

The benefits are that it has a lot less overhead compared to TCP, which can be handled by the NetServer and NetClient (see above).

### Creating a DatagramSocket

To use UDP you first need t create a `DatagramSocket`. It does not matter here if you only want to send data or send and receive.

    socket = vertx.create_datagram_socket({
    })

The returned `DatagramSocket` will not be bound to a specific port. This is not a problem if you only want to send data (like a client), but more on this in the next section.

### Sending Datagram packets

As mentioned before, User Datagram Protocol (UDP) sends data in packets to remote peers but is not connected to them in a persistent fashion.

This means each packet can be sent to a different remote peer.

Sending packets is as easy as shown here:

    require 'vertx/buffer'
    socket = vertx.create_datagram_socket({
    })
    buffer = Vertx::Buffer.buffer("content")
    # Send a Buffer
    socket.send(buffer, 1234, "10.0.0.1") { |asyncResult_err,asyncResult|
      puts "Send succeeded? #{asyncResult_err == nil}"
    }
    # Send a String
    socket.send("A string used as content", 1234, "10.0.0.1") { |asyncResult_err,asyncResult|
      puts "Send succeeded? #{asyncResult_err == nil}"
    }

### Receiving Datagram packets

If you want to receive packets you need to bind the `DatagramSocket` by calling `listen(…​)}` on it.

This way you will be able to receive `DatagramPacket`s that were sent to the address and port on which the `DatagramSocket` listens.

Beside this you also want to set a `Handler` which will be called for each received `DatagramPacket`.

The `DatagramPacket` has the following methods:

- `sender`: The InetSocketAddress which represent the sender of the packet

- `data`: The Buffer which holds the data which was received.

So to listen on a specific address and port you would do something like shown here:

    socket = vertx.create_datagram_socket({
    })
    socket.listen(1234, "0.0.0.0") { |asyncResult_err,asyncResult|
      if (asyncResult_err == nil)
        socket.handler() { |packet|
          # Do something with the packet
        }
      else
        puts "Listen failed#{asyncResult_err}"
      end
    }

Be aware that even if the {code AsyncResult} is successed it only means it might be written on the network stack, but gives no guarantee that it ever reached or will reach the remote peer at all.

If you need such a guarantee then you want to use TCP with some handshaking logic build on top.

### Multicast

#### Sending Multicast packets

Multicast allows multiple sockets to receive the same packets. This works by have same join a multicast group to which you can send packets.

We will look at how you can joint a Multicast Group and so receive packets in the next section.

For now let us focus on how to send those. Sending multicast packets is not different to send normal Datagram Packets.

The only difference is that you would pass in a multicast group address to the send method.

This is show here:

    require 'vertx/buffer'
    socket = vertx.create_datagram_socket({
    })
    buffer = Vertx::Buffer.buffer("content")
    # Send a Buffer to a multicast address
    socket.send(buffer, 1234, "230.0.0.1") { |asyncResult_err,asyncResult|
      puts "Send succeeded? #{asyncResult_err == nil}"
    }

All sockets that have joined the multicast group 230.0.0.1 will receive the packet.

##### Receiving Multicast packets

If you want to receive packets for specific Multicast group you need to bind the `DatagramSocket` by calling `listen(…​)` on it and join the Multicast group.

This way you will be able to receive DatagramPackets that were sent to the address and port on which the `DatagramSocket` listens and also to those sent to the Multicast group.

Beside this you also want to set a Handler which will be called for each received DatagramPacket.

The `DatagramPacket` has the following methods:

- `sender()`: The InetSocketAddress which represent the sender of the packet

- `data()`: The Buffer which holds the data which was received.

So to listen on a specific address and port and also receive packets for the Multicast group 230.0.0.1 you would do something like shown here:

    socket = vertx.create_datagram_socket({
    })
    socket.listen(1234, "0.0.0.0") { |asyncResult_err,asyncResult|
      if (asyncResult_err == nil)
        socket.handler() { |packet|
          # Do something with the packet
        }

        # join the multicast group
        socket.listen_multicast_group("230.0.0.1") { |asyncResult2_err,asyncResult2|
          puts "Listen succeeded? #{asyncResult2_err == nil}"
        }
      else
        puts "Listen failed#{asyncResult_err}"
      end
    }

##### Unlisten / leave a Multicast group

There are sometimes situations where you want to receive packets for a Multicast group for a limited time.

In this situations you can first start to listen for them and then later unlisten.

This is shown here:

    socket = vertx.create_datagram_socket({
    })
    socket.listen(1234, "0.0.0.0") { |asyncResult_err,asyncResult|
      if (asyncResult_err == nil)
        socket.handler() { |packet|
          # Do something with the packet
        }

        # join the multicast group
        socket.listen_multicast_group("230.0.0.1") { |asyncResult2_err,asyncResult2|
          if (asyncResult2_err == nil)
            # will now receive packets for group

            # do some work

            socket.unlisten_multicast_group("230.0.0.1") { |asyncResult3_err,asyncResult3|
              puts "Unlisten succeeded? #{asyncResult3_err == nil}"
            }
          else
            puts "Listen failed#{asyncResult2_err}"
          end
        }
      else
        puts "Listen failed#{asyncResult_err}"
      end
    }

##### Blocking multicast

Beside unlisten a Multicast address it’s also possible to just block multicast for a specific sender address.

Be aware this only work on some Operating Systems and kernel versions. So please check the Operating System documentation if it’s supported.

This an expert feature.

To block multicast from a specific address you can call `blockMulticastGroup(…​)` on the DatagramSocket like shown here:

    socket = vertx.create_datagram_socket({
    })

    # Some code

    # This would block packets which are send from 10.0.0.2
    socket.block_multicast_group("230.0.0.1", "10.0.0.2") { |asyncResult_err,asyncResult|
      puts "block succeeded? #{asyncResult_err == nil}"
    }

#### DatagramSocket properties

When creating a `DatagramSocket` there are multiple properties you can set to change it’s behaviour with the `DatagramSocketOptions` object. Those are listed here:

- `sendBufferSize` Sets the send buffer size in bytes.

- `receiveBufferSize` Sets the TCP receive buffer size in bytes.

- `reuseAddress` If true then addresses in TIME_WAIT state can be reused after they have been closed.

- `trafficClass`

- `broadcast` Sets or clears the SO_BROADCAST socket option. When this option is set, Datagram (UDP) packets may be sent to a local interface’s broadcast address.

- `multicastNetworkInterface` Sets or clears the IP_MULTICAST_LOOP socket option. When this option is set, multicast packets will also be received on the local interface.

- `multicastTimeToLive` Sets the IP_MULTICAST_TTL socket option. TTL stands for "Time to Live," but in this context it specifies the number of IP hops that a packet is allowed to go through, specifically for multicast traffic. Each router or gateway that forwards a packet decrements the TTL. If the TTL is decremented to 0 by a router, it will not be forwarded.

#### DatagramSocket Local Address

You can find out the local address of the socket (i.e. the address of this side of the UDP Socket) by calling `localAddress`. This will only return an `InetSocketAddress` if you bound the `DatagramSocket` with `listen(…​)` before, otherwise it will return null.

#### Closing a DatagramSocket

You can close a socket by invoking the `close` method. This will close the socket and release all resources

## DNS client

Often you will find yourself in situations where you need to obtain DNS informations in an asynchronous fashion.

Unfortunally this is not possible with the API that is shipped with the Java Virtual Machine itself. Because of this Vert.x offers it’s own API for DNS resolution which is fully asynchronous.

To obtain a DnsClient instance you will create a new via the Vertx instance.

    client = vertx.create_dns_client(53, "10.0.0.1")

Be aware that you can pass in a varargs of InetSocketAddress arguments to specifiy more then one DNS Server to try to query for DNS resolution. The DNS Servers will be queried in the same order as specified here. Where the next will be used once the first produce an error while be used.

### lookup

Try to lookup the A (ipv4) or AAAA (ipv6) record for a given name. The first which is returned will be used, so it behaves the same way as you may be used from when using "nslookup" on your operation system.

To lookup the A / AAAA record for "vertx.io" you would typically use it like:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.lookup("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        puts ar
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### lookup4

Try to lookup the A (ipv4) record for a given name. The first which is returned will be used, so it behaves the same way as you may be used from when using "nslookup" on your operation system.

To lookup the A record for "vertx.io" you would typically use it like:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.lookup4("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        puts ar
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### lookup6

Try to lookup the AAAA (ipv6) record for a given name. The first which is returned will be used, so it behaves the same way as you may be used from when using "nslookup" on your operation system.

To lookup the A record for "vertx.io" you would typically use it like:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.lookup6("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        puts ar
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### resolveA

Try to resolve all A (ipv4) records for a given name. This is quite similar to using "dig" on unix like operation systems.

To lookup all the A records for "vertx.io" you would typically do:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_a("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        records = ar
        records.each do |record|
          puts record
        end
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### resolveAAAA

Try to resolve all AAAA (ipv6) records for a given name. This is quite similar to using "dig" on unix like operation systems.

To lookup all the AAAAA records for "vertx.io" you would typically do:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_aaaa("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        records = ar
        records.each do |record|
          puts record
        end
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### resolveCNAME

Try to resolve all CNAME records for a given name. This is quite similar to using "dig" on unix like operation systems.

To lookup all the CNAME records for "vertx.io" you would typically do:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_cname("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        records = ar
        records.each do |record|
          puts record
        end
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### resolveMX

Try to resolve all MX records for a given name. The MX records are used to define which Mail-Server accepts emails for a given domain.

To lookup all the MX records for "vertx.io" you would typically do:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_mx("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        records = ar
        records.each do |record|
          puts record
        end
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

Be aware that the List will contain the `MxRecord` sorted by the priority of them, which means MX records with smaller priority coming first in the List.

The `MxRecord` allows you to access the priority and the name of the MX record by offer methods for it like:

    record.priority()
    record.name()

### resolveTXT

Try to resolve all TXT records for a given name. TXT records are often used to define extra informations for a domain.

To resolve all the TXT records for "vertx.io" you could use something along these lines:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_txt("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        records = ar
        records.each do |record|
          puts record
        end
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### resolveNS

Try to resolve all NS records for a given name. The NS records specify which DNS Server hosts the DNS informations for a given domain.

To resolve all the NS records for "vertx.io" you could use something along these lines:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_ns("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        records = ar
        records.each do |record|
          puts record
        end
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### resolveSRV

Try to resolve all SRV records for a given name. The SRV records are used to define extra informations like port and hostname of services. Some protocols need this extra informations.

To lookup all the SRV records for "vertx.io" you would typically do:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_srv("vertx.io") { |ar_err,ar|
      if (ar_err == nil)
        records = ar
        records.each do |record|
          puts record
        end
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

Be aware that the List will contain the SrvRecords sorted by the priority of them, which means SrvRecords with smaller priority coming first in the List.

The `SrvRecord` allows you to access all informations contained in the SRV record itself:

    record.priority()
    record.name()
    record.weight()
    record.port()
    record.protocol()
    record.service()
    record.target()

Please refer to the API docs for the exact details.

### resolvePTR

Try to resolve the PTR record for a given name. The PTR record maps an ipaddress to a name.

To resolve the PTR record for the ipaddress 10.0.0.1 you would use the PTR notion of "1.0.0.10.in-addr.arpa"

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.resolve_ptr("1.0.0.10.in-addr.arpa") { |ar_err,ar|
      if (ar_err == nil)
        record = ar
        puts record
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

### reverseLookup

Try to do a reverse lookup for an ipaddress. This is basically the same as resolve a PTR record, but allows you to just pass in the ipaddress and not a valid PTR query string.

To do a reverse lookup for the ipaddress 10.0.0.1 do something similar like this:

    client = vertx.create_dns_client(53, "10.0.0.1")
    client.reverse_lookup("10.0.0.1") { |ar_err,ar|
      if (ar_err == nil)
        record = ar
        puts record
      else
        puts "Failed to resolve entry#{ar_err}"
      end
    }

## Streams

There are several objects in Vert.x that allow items to be read from and written.

In previous versions the streams.adoc package was manipulating `Buffer` objects exclusively. From now, streams are not anymore coupled to buffers and work with any kind of objects.

In Vert.x, calls to write item return immediately and writes are internally queued.

It’s not hard to see that if you write to an object faster than it can actually write the data to its underlying resource then the write queue could grow without bound - eventually resulting in exhausting available memory.

To solve this problem a simple flow control capability is provided by some objects in the Vert.x API.

Any flow control aware object that can be written-to implements `ReadStream`, and any flow control object that can be read-from is said to implement `WriteStream`.

Let’s take an example where we want to read from a `ReadStream` and write the data to a `WriteStream`.

A very simple example would be reading from a `NetSocket` on a server and writing back to the same `NetSocket` - since `NetSocket` implements both `ReadStream` and `WriteStream`, but you can do this between any `ReadStream` and any `WriteStream`, including HTTP requests and response, async files, WebSockets, etc.

A naive way to do this would be to directly take the data that’s been read and immediately write it to the `NetSocket`, for example:

    server = vertx.create_net_server({
      'port' => 1234,
      'host' => "localhost"
    })
    server.connect_handler() { |sock|
      sock.handler() { |buffer|
        # Write the data straight back
        sock.write(buffer)
      }
    }.listen()

There’s a problem with the above example: If data is read from the socket faster than it can be written back to the socket, it will build up in the write queue of the `NetSocket`, eventually running out of RAM. This might happen, for example if the client at the other end of the socket wasn’t reading very fast, effectively putting back-pressure on the connection.

Since `NetSocket` implements `WriteStream`, we can check if the `WriteStream` is full before writing to it:

    server = vertx.create_net_server({
      'port' => 1234,
      'host' => "localhost"
    })
    server.connect_handler() { |sock|
      sock.handler() { |buffer|
        if (!sock.write_queue_full?())
          sock.write(buffer)
        end
      }

    }.listen()

This example won’t run out of RAM but we’ll end up losing data if the write queue gets full. What we really want to do is pause the `NetSocket` when the write queue is full. Let’s do that:

    server = vertx.create_net_server({
      'port' => 1234,
      'host' => "localhost"
    })
    server.connect_handler() { |sock|
      sock.handler() { |buffer|
        sock.write(buffer)
        if (sock.write_queue_full?())
          sock.pause()
        end
      }
    }.listen()

We’re almost there, but not quite. The `NetSocket` now gets paused when the file is full, but we also need to unpause it when the write queue has processed its backlog:

    server = vertx.create_net_server({
      'port' => 1234,
      'host' => "localhost"
    })
    server.connect_handler() { |sock|
      sock.handler() { |buffer|
        sock.write(buffer)
        if (sock.write_queue_full?())
          sock.pause()
          sock.drain_handler() { |done|
            sock.resume()
          }
        end
      }
    }.listen()

And there we have it. The `drainHandler` event handler will get called when the write queue is ready to accept more data, this resumes the `NetSocket` which allows it to read more data.

It’s very common to want to do this when writing Vert.x applications, so we provide a helper class called `Pump` which does all this hard work for you. You just feed it the `ReadStream` and the `WriteStream` and it tell it to start:

    require 'vertx/pump'
    server = vertx.create_net_server({
      'port' => 1234,
      'host' => "localhost"
    })
    server.connect_handler() { |sock|
      Vertx::Pump.pump(sock, sock).start()
    }.listen()

Which does exactly the same thing as the more verbose example.

Let’s look at the methods on `ReadStream` and `WriteStream` in more detail:

### ReadStream

`ReadStream` is implemented by `HttpClientResponse`, `DatagramSocket`, `HttpClientRequest`, `HttpServerFileUpload`, `HttpServerRequest`, `HttpServerRequestStream`, `MessageConsumer`, `NetSocket`, `NetSocketStream`, `WebSocket`, `WebSocketStream`, `TimeoutStream`, `AsyncFile`.

Functions:

- `handler`: set a handler which will receive items from the ReadStream.

- `pause`: pause the handler. When paused no items will be received in the handler.

- `resume`: resume the handler. The handler will be called if any item arrives.

- `exceptionHandler`: Will be called if an exception occurs on the ReadStream.

- `endHandler`: Will be called when end of stream is reached. This might be when EOF is reached if the ReadStream represents a file, or when end of request is reached if it’s an HTTP request, or when the connection is closed if it’s a TCP socket.

### WriteStream

`WriteStream` is implemented by `HttpClientRequest`, `HttpServerResponse` `WebSocket`, `NetSocket`, `AsyncFile`, `PacketWritestream` and `MessageProducer`

Functions:

- `write`: write an object to the WriteStream. This method will never block. Writes are queued internally and asynchronously written to the underlying resource.

- `setWriteQueueMaxSize`: set the number of object at which the write queue is considered full, and the method `writeQueueFull` returns `true`. Note that, when the write queue is considered full, if write is called the data will still be accepted and queued. The actual number depends on the stream implementation, for `Buffer` the size represents the actual number of bytes written and not the number of buffers.

- `writeQueueFull`: returns `true` if the write queue is considered full.

- `exceptionHandler`: Will be called if an exception occurs on the `WriteStream`.

- `drainHandler`: The handler will be called if the `WriteStream` is considered no longer full.

### Pump

Instances of Pump have the following methods:

- `start`: Start the pump.

- `stop`: Stops the pump. When the pump starts it is in stopped mode.

- `setWriteQueueMaxSize`: This has the same meaning as `setWriteQueueMaxSize` on the `WriteStream`.

A pump can be started and stopped multiple times.

When a pump is first created it is not started. You need to call the `start()` method to start it.

## Record Parser

The record parser allows you to easily parse protocols which are delimited by a sequence of bytes, or fixed size records.

It transforms an sequence of input buffer to a sequence of buffer structured as configured (either fixed size or separated records).

For example, if you have a simple ASCII text protocol delimited by '\n' and the input is the following:

    buffer1:HELLO\nHOW ARE Y
    buffer2:OU?\nI AM
    buffer3: DOING OK
    buffer4:\n

The record parser would produce

    buffer1:HELLO
    buffer2:HOW ARE YOU?
    buffer3:I AM DOING OK

Let’s see the associated code:

    require 'vertx/record_parser'
    require 'vertx/buffer'
    parser = Vertx::RecordParser.new_delimited("\n") { |h|
      puts h.to_string()
    }

    parser.handle(Vertx::Buffer.buffer("HELLO\nHOW ARE Y"))
    parser.handle(Vertx::Buffer.buffer("OU?\nI AM"))
    parser.handle(Vertx::Buffer.buffer("DOING OK"))
    parser.handle(Vertx::Buffer.buffer("\n"))

You can also produce fixed sized chunks as follows:

    require 'vertx/record_parser'
    Vertx::RecordParser.new_fixed(4) { |h|
      puts h.to_string()
    }

For more details, check out the `RecordParser` class.

## Thread safety

Most Vert.x objects are safe to access from different threads. However performance is optimised when they are accessed from the same context they were created from.

For example if you have deployed a verticle which creates a `NetServer` which provides `NetSocket` instances in it’s handler, then it’s best to always access that socket instance from the event loop of the verticle.

If you stick to the standard Vert.x verticle deployment model and avoid sharing objects between verticles then this should be the case without you having to think about it.

## Metrics SPI

By default Vert.x does not record any metrics. Instead it provides an SPI for others to implement which can be added to the classpath. The metrics SPI is an advanced feature which allows implementers to capture events from Vert.x in order to gather metrics. For more information on this, please consult the `API Documentation`.

## OSGi

Vert.x Core is packaged as an OSGi bundle, so can be used in any OSGi R4.2+ environment such as Apache Felix or Eclipse Equinox. The bundle exports `io.vertx.core*`.

However, the bundle has some dependencies on Jackson and Netty. To get the vert.x core bundle resolved deploy:

- Jackson Annotation [2.5.0,3)

- Jackson Core [2.5.0,3)

- Jackson Databind [2.5.0,3)

- Netty Buffer [4.0.27,5)

- Netty Codec [4.0.27,5)

- Netty Codec/Socks [4.0.27,5)

- Netty Codec/Common [4.0.27,5)

- Netty Codec/Handler [4.0.27,5)

- Netty Codec/Transport [4.0.27,5)

Here is a working deployment on Apache Felix 4.6.1:

      14|Active     |    1|Jackson-annotations (2.5.3)
      15|Active     |    1|Jackson-core (2.5.3)
      16|Active     |    1|jackson-databind (2.5.3)
      17|Active     |    1|Netty/Buffer (4.0.27.Final)
      18|Active     |    1|Netty/Codec (4.0.27.Final)
      19|Active     |    1|Netty/Codec/HTTP (4.0.27.Final)
      20|Active     |    1|Netty/Codec/Socks (4.0.27.Final)
      21|Active     |    1|Netty/Common (4.0.27.Final)
      22|Active     |    1|Netty/Handler (4.0.27.Final)
      23|Active     |    1|Netty/Transport (4.0.27.Final)
      25|Active     |    1|Vert.x Core (3.0.0.SNAPSHOT)

## The 'vertx' command line

The `vertx` command is used to interact with Vert.x from the command line. It’s main use is to run Vert.x verticles. To do this you need to download and install a Vert.x distribution, and add the `bin` directory of the installation to your `PATH` environment variable. Also make sure you have a Java 8 JDK on your `PATH`.

Note | The JDK is required to support on the fly compilation of Java code.

### Run verticles

You can run raw Vert.x verticles directly from the command line using `vertx run`. Here is a couple of examples:

    vertx run my-verticle.js                                 (1)
    vertx run my-verticle.groovy                             (2)
    vertx run my-verticle.rb                                 (3)

    vertx run io.vertx.example.MyVerticle                    (4)
    vertx run io.vertx.example.MVerticle -cp my-verticle.jar (5)

    vertx run MyVerticle.java                                (6)

1. Deploys a JavaScript verticle

2. Deploys a Groovy verticle

3. Deploys a Ruby verticle

4. Deploys an already compiled Java verticle. Classpath root is the current directory

5. Deploys a verticle packaged in a Jar, the jar need to be in the classpath

6. Compiles the Java source and deploys it

As you can see in the case of Java, the name can either be the fully qualified class name of the verticle, or you can specify the Java Source file directly and Vert.x compiles it for you.

You can also prefix the verticle with the name of the language implementation to use. For example if the verticle is a compiled Groovy class, you prefix it with `groovy:` so that Vert.x knows it’s a Groovy class not a Java class.

    vertx run groovy:io.vertx.example.MyGroovyVerticle

The `vertx run` command can take a few optional parameters, they are:

- `-conf <config_file>` - Provides some configuration to the verticle. `config_file` is the name of a text file containing a JSON object that represents the configuration for the verticle. This is optional.

- `-cp <path>` - The path on which to search for the verticle and any other resources used by the verticle. This defaults to `.` (current directory). If your verticle references other scripts, classes or other resources (e.g. jar files) then make sure these are on this path. The path can contain multiple path entries separated by `:` (colon) or `;` (semi-colon) depending on the operating system. Each path entry can be an absolute or relative path to a directory containing scripts, or absolute or relative filenames for jar or zip files. An example path might be `-cp classes:lib/otherscripts:jars/myjar.jar:jars/otherjar.jar`. Always use the path to reference any resources that your verticle requires. Do not put them on the system classpath as this can cause isolation issues between deployed verticles.

- `-instances <instances>` - The number of instances of the verticle to instantiate. Each verticle instance is strictly single threaded so to scale your application across available cores you might want to deploy more than one instance. If omitted a single instance will be deployed.

- `-worker` - This option determines whether the verticle is a worker verticle or not.

- `-cluster` - This option determines whether the Vert.x instance will attempt to form a cluster with other Vert.x instances on the network. Clustering Vert.x instances allows Vert.x to form a distributed event bus with other nodes. Default is `false` (not clustered).

- `-cluster-port` - If the cluster option has also been specified then this determines which port will be used for cluster communication with other Vert.x instances. Default is `0` - which means 'choose a free random port'. You don’t usually need to specify this parameter unless you really need to bind to a specific port.

- `-cluster-host` - If the cluster option has also been specified then this determines which host address will be used for cluster communication with other Vert.x instances. By default it will try and pick one from the available interfaces. If you have more than one interface and you want to use a specific one, specify it here.

- `-ha` - if specified the verticle will be deployed as high availability (HA) deployment. See related section for more details

- `-quorum` - used in conjunction with `-ha`. It specifies the minimum number of nodes in the cluster for any HA deploymentIDs to be active. Defaults to 0.

- `-hagroup` - used in conjunction with `-ha`. It specifies the HA group this node will join. There can be multiple HA groups in a cluster. Nodes will only failover to other nodes in the same group. The default value is ` __DEFAULT__`

Here are some more examples:

Run a JavaScript verticle server.js with default settings

    vertx run server.js

Run 10 instances of a pre-compiled Java verticle specifying classpath

    vertx run com.acme.MyVerticle -cp "classes:lib/myjar.jar" -instances 10

Run 10 instances of a Java verticle by source file

    vertx run MyVerticle.java -instances 10

Run 20 instances of a ruby worker verticle

    vertx run order_worker.rb -instances 20 -worker

Run two JavaScript verticles on the same machine and let them cluster together with each other and any other servers on the network

    vertx run handler.js -cluster
    vertx run sender.js -cluster

Run a Ruby verticle passing it some config

    vertx run my_verticle.rb -conf my_verticle.conf

Where `my_verticle.conf` might contain something like:

    {
     "name": "foo",
     "num_widgets": 46
    }

The config will be available inside the verticle via the core API.

When using the high-availability feature of vert.x you may want to create a bare instance of vert.x. This instance does not deploy any verticles when launched, but will receive a verticle if another node of the cluster dies. To create a bare instance, launch:

    vertx -ha

Depending on your cluster configuration, you may have to append the `cluster-host` and `cluster-port` parameters.

### Executing verticles packaged as a fat jar

A fat jar is an executable jar embedding its dependencies. This means you don’t have to have Vert.x pre-installed on the machine on which you execute the jar. A verticle packaged as a fat jar can just be launched using:

    java -jar my-verticle-fat.jar

The fat jar must have a manifest with:

- `Main-Class` set to `io.vertx.core.Starter`

- `Main-Verticle` specifying the main verticle (fully qualified name)

You can also provide the usual command line arguments that you would pass to `vertx run`:

    java -jar my-verticle-fat.jar -cluster -conf myconf.json
    java -jar my-verticle-fat.jar -cluster -conf myconf.json -cp path/to/dir/conf/cluster_xml

Note | fat jar can be built using Gradle build or the Maven plugin. Check the vertx examples for instructions.

### Displaying version of Vert.x

To display the vert.x version, just launch:

    vertx -version

## Cluster Managers

In Vert.x a cluster manager is used for various functions including:

- Discovery and group membership of Vert.x nodes in a cluster

- Maintaining cluster wide topic subscriber lists (so we know which nodes are interested in which event bus addresses)

- Distributed Map support

- Distributed Locks

- Distributed Counters

Cluster managers do not handle the event bus inter-node transport, this is done directly by Vert.x with TCP connections.

The default cluster manager used in the Vert.x distributions is one that uses Hazelcast but this can be easily replaced by a different implementation as Vert.x cluster managers are pluggable.

A cluster manager must implement the interface `ClusterManager`. Vert.x locates cluster managers at run-time by using the Java Service Loader functionality to locate instances of `ClusterManager` on the classpath.

If you are using Vert.x at the command line and you want to use clustering you should make sure the `lib` directory of the Vert.x installation contains your cluster manager jar.

If you are using Vert.x from a Maven or Gradle project just add the cluster manager jar as a dependency of your project.

You can also specify cluster managers programmatically if embedding Vert.x using `clusterManager`.

## Logging

Vert.x logs using it’s in-built logging API. The default implementation uses the JDK (JUL) logging so no extra logging dependencies are needed.

### Configuring JUL logging

A JUL logging configuration file can be specified in the normal JUL way by providing a system property called: `java.util.logging.config.file` with the value being your configuration file. For more information on this and the structure of a JUL config file please consult the JUL logging documentation.

Vert.x also provides a slightly more convenient way to specify a configuration file without having to set a system property. Just provide a JUL config file with the name `vertx-default-jul-logging.properties` on your classpath (e.g. inside your fatjar) and Vert.x will use that to configure JUL.

### Using another logging framework

If you don’t want Vert.x to use JUL for it’s own logging you can configure it to use another logging framework, e.g. Log4J or SLF4J.

To do this 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`. We provide pre-built implementations for Log4J and SLF4J with the class names `io.vertx.core.logging.Log4jLogDelegateFactory` and `io.vertx.core.logging.SLF4JLogDelegateFactory` respectively. If you want to use these implementations you should also make sure the relevant Log4J or SLF4J jars are on your classpath.

### Logging from your application

Vert.x itself is just a library and you can use whatever logging library you prefer to log from your own application, using that logging library’s API.

However, if you prefer you can use the Vert.x logging facility as described above to provide logging for your application too.

To do that you use `LoggerFactory` to get an instance of `Logger` which you then use for logging, e.g.

    # Note -these classes are Java only

    # You would normally maintain one static instance of Logger per Java class:

    logger = Java::IoVertxCoreLogging::LoggerFactory.get_logger(className)

    logger.info("something happened")
    logger.error("oops!", exception)

## High Availability and Fail-Over

Vert.x allows you to run your verticles with high availability (HA) support. In that case, when a vert.x instance running a verticle dies abruptly, the verticle is migrated to another vertx instance. The vert.x instances must be in the same cluster.

### Automatic failover

When vert.x runs with HA enabled, if a vert.x instance where a verticle runs fails or dies, the verticle is redeployed automatically on another vert.x instance of the cluster. We call this verticle fail-over.

To run vert.x with the HA enabled, just add the `-ha` flag to the command line:

    vertx run my-verticle.js -ha

Now for HA to work, you need more than one Vert.x instances in the cluster, so let’s say you have another Vert.x instance that you have already started, for example:

    vertx run my-other-verticle.js -ha

If the Vert.x instance that is running `my-verticle.js` now dies (you can test this by killing the process with `kill -9`), the Vert.x instance that is running `my-other-verticle.js` will automatic deploy `my-verticle .js` so now that Vert.x instance is running both verticles.

Note | the migration is only possible if the second vert.x instance has access to the verticle file (here `my-verticle.js`).

Important | Please note that cleanly closing a Vert.x instance will not cause failover to occur, e.g. `CTRL-C` or `kill -SIGINT`

You can also start bare Vert.x instances - i.e. instances that are not initially running any verticles, they will also failover for nodes in the cluster. To start a bare instance you simply do:

    vertx run -ha

When using the `-ha` switch you do not need to provide the `-cluster` switch, as a cluster is assumed if you want HA.

Note | depending on your cluster configuration, you may need to customize the cluster manager configuration (Hazelcast by default), and/or add the `cluster-host` and `cluster-port` parameters.

### HA groups

When running a Vert.x instance with HA you can also optional specify a HA group. A HA group denotes a logical group of nodes in the cluster. Only nodes with the same HA group will failover onto one another. If you don’t specify a HA group the default group `__DEFAULT__` is used.

To specify an HA group you use the `-hagroup` switch when running the verticle, e.g.

    vertx run my-verticle.js -ha -ha-group my-group

Let’s look at an example:

In a first terminal:

    vertx run my-verticle.js -ha -hagroup g1

In a second terminal, let’s run another verticle using the same group:

    vertx run my-other-verticle.js -ha -hagroup g1

Finally, in a third terminal, launch another verticle using a different group:

    vertx run yet-another-verticle.js -ha -hagroup g2

If we kill the instance in terminal 1, it will fail over to the instance in terminal 2, not the instance in terminal 3 as that has a different group.

If we kill the instance in terminal 3, it won’t get failed over as there is no other vert.x instance in that group.

### Dealing with network partitions - Quora

The HA implementation also supports quora. A quorum is the minimum number of votes that a distributed transaction has to obtain in order to be allowed to perform an operation in a distributed system.

When starting a Vert.x instance you can instruct it that it requires a `quorum` before any HA deployments will be deployed. In this context, a quorum is a minimum number of nodes for a particular group in the cluster. Typically you chose your quorum size to `Q = 1 + N/2` where `N` is the number of nodes in the group. If there are less than `Q` nodes in the cluster the HA deployments will undeploy. They will redeploy again if/when a quorum is re-attained. By doing this you can prevent against network partitions, a.k.a. split brain.

There is more information on quora here.

To run vert.x instances with a quorum you specify `-quorum` on the command line, e.g.

In a first terminal:

    vertx run my-verticle.js -ha -quorum 3

At this point the Vert.x instance will start but not deploy the module (yet) because there is only one node in the cluster, not 3.

In a second terminal:

    vertx run my-other-verticle.js -ha -quorum 3

At this point the Vert.x instance will start but not deploy the module (yet) because there are only two nodes in the cluster, not 3.

In a third console, you can start another instance of vert.x:

    vertx run yet-another-verticle.js -ha -quorum 3

Yay! - we have three nodes, that’s a quorum. At this point the modules will automatically deploy on all instances.

If we now close or kill one of the nodes the modules will automatically undeploy on the other nodes, as there is no longer a quorum.

Quora can also be used in conjunction with ha groups. In that case, quora are resolved for each particular group.

## Security notes

Vert.x is a toolkit, not an opinionated framework where we force you to do things in a certain way. This gives you great power as a developer but with that comes great responsibility.

As with any toolkit, it’s possible to write insecure applications, so you should always be careful when developing your application especially if it’s exposed to the public (e.g. over the internet).

### Web applications

If writing a web application it’s highly recommended that you use Vert.x-Web instead of Vert.x core directly for serving resources and handling file uploads.

Vert.x-Web normalises the path in requests to prevent malicious clients from crafting URLs to access resources outside of the web root.

Similarly for file uploads Vert.x-Web provides functionality for uploading to a known place on disk and does not rely on the filename provided by the client in the upload which could be crafted to upload to a different place on disk.

Vert.x core itself does not provide such checks so it would be up to you as a developer to implement them yourself.

### Clustered event bus traffic

When clustering the event bus between different Vert.x nodes on a network, the traffic is sent un-encrypted across the wire, so do not use this if you have confidential data to send and your Vert.x nodes are not on a trusted network.

### Standard security best practices

Any service can have potentially vulnerabilities whether it’s written using Vert.x or any other toolkit so always follow security best practice, especially if your service is public facing.

For example you should always run them in a DMZ and with an user account that has limited rights in order to limit the extent of damage in case the service was compromised.