diff --git a/.github/workflows/ci-4.x.yml b/.github/workflows/ci-4.x.yml
index 8e9a77c5e67..654ba579c3e 100644
--- a/.github/workflows/ci-4.x.yml
+++ b/.github/workflows/ci-4.x.yml
@@ -17,7 +17,7 @@ jobs:
jdk: 8
profile: '-PtestDomainSockets'
- os: ubuntu-latest
- jdk: 17
+ jdk: 21
profile: ''
- os: windows-latest
jdk: 8
diff --git a/.github/workflows/ci-5.x.yml b/.github/workflows/ci-5.x.yml
index d4f535707e8..c1950f65ea3 100644
--- a/.github/workflows/ci-5.x.yml
+++ b/.github/workflows/ci-5.x.yml
@@ -23,7 +23,7 @@ jobs:
jdk: 11
profile: '-PtestDomainSockets'
- os: ubuntu-latest
- jdk: 17
+ jdk: 21
profile: ''
- os: windows-latest
jdk: 11
diff --git a/README.md b/README.md
index 98395fbe0ba..6ef9878f702 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,12 @@ Runs the tests
> mvn test
```
+Tests can be run with specified HTTP port and/or HTTPS port.
+
+```
+> mvn test -Dvertx.httpPort=8888 -Dvertx.httpsPort=4044
+```
+
Vert.x supports native transport on BSD and Linux, to run the tests with native transport
```
diff --git a/pom.xml b/pom.xml
index 2cc0444a3cf..c4d58b5e9fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -195,7 +195,7 @@
com.aayushatharva.brotli4jbrotli4j
- 1.8.0
+ 1.12.0test
@@ -416,7 +416,7 @@
org.apache.maven.pluginsmaven-failsafe-plugin
- 2.19.1
+ 3.2.5ssl-engine:default
@@ -479,6 +479,10 @@
io/vertx/it/SLF4JLogDelegateTest.java
+
+ System.out
+ false
+
@@ -567,6 +571,29 @@
+
+ no-recycler-pool-jackson
+
+ integration-test
+ verify
+
+
+
+ io/vertx/it/NoRecyclerPoolJacksonTest.java
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.15.1
+
+
+
+ com.fasterxml.jackson.core:jackson-core
+ com.fasterxml.jackson.core:jackson-databind
+
+
+ no-jackson-databind
diff --git a/src/main/asciidoc/buffers.adoc b/src/main/asciidoc/buffers.adoc
index 109c84d4674..9422eb9fb74 100644
--- a/src/main/asciidoc/buffers.adoc
+++ b/src/main/asciidoc/buffers.adoc
@@ -35,7 +35,12 @@ Create a buffer from a String: The String will be encoded using the specified en
{@link examples.BufferExamples#example3}
----
-include::override/buffer_from_bytes.adoc[]
+Create a buffer from a byte[]
+
+[source,java]
+----
+{@link examples.BufferExamples#example4}
+----
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
diff --git a/src/main/asciidoc/cli-for-java.adoc b/src/main/asciidoc/cli-for-java.adoc
deleted file mode 100644
index 8d3f8811423..00000000000
--- a/src/main/asciidoc/cli-for-java.adoc
+++ /dev/null
@@ -1,81 +0,0 @@
-=== Typed options and arguments
-
-The described {@link io.vertx.core.cli.Option} and {@link io.vertx.core.cli.Argument} classes are _untyped_,
-meaning that the only get String values.
-{@link io.vertx.core.cli.TypedOption} and {@link io.vertx.core.cli.TypedArgument} let you specify a _type_, so the
-(String) raw value is converted to the specified type.
-
-Instead of
-{@link io.vertx.core.cli.Option} and {@link io.vertx.core.cli.Argument}, use {@link io.vertx.core.cli.TypedOption}
-and {@link io.vertx.core.cli.TypedArgument} in the {@link io.vertx.core.cli.CLI} definition:
-
-[source,java]
-----
-{@link examples.cli.TypedCLIExamples#example1}
-----
-
-Then you can retrieve the converted values as follows:
-
-[source,java]
-----
-{@link examples.cli.TypedCLIExamples#example2}
-----
-
-The vert.x CLI is able to convert to classes:
-
-* having a constructor with a single
-{@link java.lang.String} argument, such as {@link java.io.File} or {@link io.vertx.core.json.JsonObject}
-* with a static `from` or `fromString` method
-* with a static `valueOf` method, such as primitive types and enumeration
-
-In addition, you can implement your own {@link io.vertx.core.cli.converters.Converter} and instruct the CLI to use
-this converter:
-
-[source,java]
-----
-{@link examples.cli.TypedCLIExamples#example3}
-----
-
-For booleans, the boolean values are evaluated to `true`: `on`, `yes`, `1`, `true`.
-
-If one of your option has an `enum` as type, it computes the set of choices automatically.
-
-=== Using annotations
-
-You can also define your CLI using annotations. Definition is done using annotation on the class and on _setter_
-methods:
-
-[source, java]
-----
-@Name("some-name")
-@Summary("some short summary.")
-@Description("some long description")
-public class AnnotatedCli {
-
- private boolean flag;
- private String name;
- private String arg;
-
- @Option(shortName = "f", flag = true)
- public void setFlag(boolean flag) {
- this.flag = flag;
- }
-
- @Option(longName = "name")
- public void setName(String name) {
- this.name = name;
- }
-
- @Argument(index = 0)
- public void setArg(String arg) {
- this.arg = arg;
- }
-}
-----
-
-Once annotated, you can define the {@link io.vertx.core.cli.CLI} and inject the values using:
-
-[source,java]
-----
-{@link examples.cli.TypedCLIExamples#example4}
-----
diff --git a/src/main/asciidoc/cli.adoc b/src/main/asciidoc/cli.adoc
deleted file mode 100644
index c2036876423..00000000000
--- a/src/main/asciidoc/cli.adoc
+++ /dev/null
@@ -1,180 +0,0 @@
-Vert.x Core provides an API for parsing command line arguments passed to programs. It's also able to print help
-messages detailing the options available for a command line tool. Even if such features are far from
-the Vert.x core topics, this API is used in the {@link io.vertx.core.Launcher} class that you can use in _fat-jar_
-and in the `vertx` command line tools. In addition, it's polyglot (can be used from any supported language) and is
-used in Vert.x Shell.
-
-Vert.x CLI provides a model to describe your command line interface, but also a parser. This parser supports
-different types of syntax:
-
-* POSIX like options (ie. `tar -zxvf foo.tar.gz`)
-* GNU like long options (ie. `du --human-readable --max-depth=1`)
-* Java like properties (ie. `java -Djava.awt.headless=true -Djava.net.useSystemProxies=true Foo`)
-* Short options with value attached (ie. `gcc -O2 foo.c`)
-* Long options with single hyphen (ie. `ant -projecthelp`)
-
-Using the CLI api is a 3-steps process:
-
-1. The definition of the command line interface
-2. The parsing of the user command line
-3. The query / interrogation
-
-=== Definition Stage
-
-Each command line interface must define the set of options and arguments that will be used. It also requires a
-name. The CLI API uses the {@link io.vertx.core.cli.Option} and {@link io.vertx.core.cli.Argument} classes to
-describe options and arguments:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example1}
-----
-
-As you can see, you can create a new {@link io.vertx.core.cli.CLI} using
-{@link io.vertx.core.cli.CLI#create(java.lang.String)}. The passed string is the name of the CLI. Once created you
-can set the summary and description. The summary is intended to be short (one line), while the description can
-contain more details. Each option and argument are also added on the `CLI` object using the
-{@link io.vertx.core.cli.CLI#addArgument(io.vertx.core.cli.Argument)} and
-{@link io.vertx.core.cli.CLI#addOption(io.vertx.core.cli.Option)} methods.
-
-==== Options
-
-An {@link io.vertx.core.cli.Option} is a command line parameter identified by a _key_ present in the user command
-line. Options must have at least a long name or a short name. Long name are generally used using a `--` prefix,
-while short names are used with a single `-`. Names are case-sensitive; however, case-insensitive name matching
-will be used during the <> if no exact match is found.
-Options can get a description displayed in the usage (see below). Options can receive 0, 1 or several values. An
-option receiving 0 values is a `flag`, and must be declared using
-{@link io.vertx.core.cli.Option#setFlag(boolean)}. By default, options receive a single value, however, you can
-configure the option to receive several values using {@link io.vertx.core.cli.Option#setMultiValued(boolean)}:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example2}
-----
-
-Options can be marked as mandatory. A mandatory option not set in the user command line throws an exception during
-the parsing:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example3}
-----
-
-Non-mandatory options can have a _default value_. This value would be used if the user does not set the option in
-the command line:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example4}
-----
-
-An option can be _hidden_ using the {@link io.vertx.core.cli.Option#setHidden(boolean)} method. Hidden option are
-not listed in the usage, but can still be used in the user command line (for power-users).
-
-If the option value is constrained to a fixed set, you can set the different acceptable choices:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example41}
-----
-
-Options can also be instantiated from their JSON form.
-
-==== Arguments
-
-Unlike options, arguments do not have a _key_ and are identified by their _index_. For example, in
-`java com.acme.Foo`, `com.acme.Foo` is an argument.
-
-Arguments do not have a name, there are identified using a 0-based index. The first parameter has the
-index `0`:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example5}
-----
-
-If you don't set the argument indexes, it computes it automatically by using the declaration order.
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example51}
-----
-
-The `argName` is optional and used in the usage message.
-
-As options, {@link io.vertx.core.cli.Argument} can:
-
-* be hidden using {@link io.vertx.core.cli.Argument#setHidden(boolean)}
-* be mandatory using {@link io.vertx.core.cli.Argument#setRequired(boolean)}
-* have a default value using {@link io.vertx.core.cli.Argument#setDefaultValue(java.lang.String)}
-* receive several values using {@link io.vertx.core.cli.Argument#setMultiValued(boolean)} - only the last argument
-can be multi-valued.
-
-Arguments can also be instantiated from their JSON form.
-
-==== Usage generation
-
-Once your {@link io.vertx.core.cli.CLI} instance is configured, you can generate the _usage_ message:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example6}
-----
-
-It generates a usage message like this one:
-
-[source]
-----
-Usage: copy [-R] source target
-
-A command line interface to copy files.
-
- -R,--directory enables directory support
-----
-
-If you need to tune the usage message, check the {@link io.vertx.core.cli.UsageMessageFormatter} class.
-
-=== Parsing Stage
-
-Once your {@link io.vertx.core.cli.CLI} instance is configured, you can parse the user command line to evaluate
-each option and argument:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example7}
-----
-
-The {@link io.vertx.core.cli.CLI#parse(java.util.List)} method returns a {@link io.vertx.core.cli.CommandLine}
-object containing the values. By default, it validates the user command line and checks that each mandatory options
-and arguments have been set as well as the number of values received by each option. You can disable the
-validation by passing `false` as second parameter of {@link io.vertx.core.cli.CLI#parse(java.util.List,boolean)}.
-This is useful if you want to check an argument or option is present even if the parsed command line is invalid.
-
-You can check whether or not the
-{@link io.vertx.core.cli.CommandLine} is valid using {@link io.vertx.core.cli.CommandLine#isValid()}.
-
-[[query_interrogation_stage]]
-=== Query / Interrogation Stage
-
-Once parsed, you can retrieve the values of the options and arguments from the
-{@link io.vertx.core.cli.CommandLine} object returned by the {@link io.vertx.core.cli.CLI#parse(java.util.List)}
-method:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example8}
-----
-
-One of your options can be marked as "help". If a user command line enabled a "help" option, the validation
-won't fail, but you have the opportunity to check if the user asks for help:
-
-[source,$lang]
-----
-{@link examples.cli.CLIExamples#example9}
-----
-
-[language,java]
-----
-include::cli-for-java.adoc[]
-----
diff --git a/src/main/asciidoc/datagrams.adoc b/src/main/asciidoc/datagrams.adoc
index b7418fe0b75..7c1285d4cb3 100644
--- a/src/main/asciidoc/datagrams.adoc
+++ b/src/main/asciidoc/datagrams.adoc
@@ -26,7 +26,7 @@ and NetClient (see above).
=== Creating a DatagramSocket
-To use UDP you first need t create a {@link io.vertx.core.datagram.DatagramSocket}. It does not matter here if you only want to send data or send
+To use UDP you first need to create a {@link io.vertx.core.datagram.DatagramSocket}. It does not matter here if you only want to send data or send
and receive.
[source,$lang]
@@ -54,7 +54,7 @@ Sending packets is as easy as shown here:
=== Receiving Datagram packets
If you want to receive packets you need to bind the {@link io.vertx.core.datagram.DatagramSocket} by calling
-`listen(...)}` on it.
+`listen(...)` on it.
This way you will be able to receive {@link io.vertx.core.datagram.DatagramPacket}s that were sent to the address and port on
which the {@link io.vertx.core.datagram.DatagramSocket} listens.
diff --git a/src/main/asciidoc/dns.adoc b/src/main/asciidoc/dns.adoc
index ae3791b309a..7e507ebaa9b 100644
--- a/src/main/asciidoc/dns.adoc
+++ b/src/main/asciidoc/dns.adoc
@@ -26,6 +26,8 @@ for non blocking address resolution.
{@link examples.DNSExamples#example1__}
----
+A client uses a single event loop for querying purposes, it can safely be used from any thread, including non Vert.x thread.
+
=== lookup
Try to lookup the A (ipv4) or AAAA (ipv6) record for a given name. The first which is returned will be used,
@@ -190,4 +192,35 @@ To do a reverse lookup for the ipaddress 10.0.0.1 do something similar like this
{@link examples.DNSExamples#example15}
----
-include::override/dns.adoc[]
+=== Error handling
+
+As you saw in previous sections the DnsClient allows you to pass in a Handler which will be notified with an
+AsyncResult once the query was complete. In case of an error it will be notified with a DnsException which will
+hole a {@link io.vertx.core.dns.DnsResponseCode} that indicate why the resolution failed. This DnsResponseCode
+can be used to inspect the cause in more detail.
+
+Possible DnsResponseCodes are:
+
+- {@link io.vertx.core.dns.DnsResponseCode#NOERROR} No record was found for a given query
+- {@link io.vertx.core.dns.DnsResponseCode#FORMERROR} Format error
+- {@link io.vertx.core.dns.DnsResponseCode#SERVFAIL} Server failure
+- {@link io.vertx.core.dns.DnsResponseCode#NXDOMAIN} Name error
+- {@link io.vertx.core.dns.DnsResponseCode#NOTIMPL} Not implemented by DNS Server
+- {@link io.vertx.core.dns.DnsResponseCode#REFUSED} DNS Server refused the query
+- {@link io.vertx.core.dns.DnsResponseCode#YXDOMAIN} Domain name should not exist
+- {@link io.vertx.core.dns.DnsResponseCode#YXRRSET} Resource record should not exist
+- {@link io.vertx.core.dns.DnsResponseCode#NXRRSET} RRSET does not exist
+- {@link io.vertx.core.dns.DnsResponseCode#NOTZONE} Name not in zone
+- {@link io.vertx.core.dns.DnsResponseCode#BADVERS} Bad extension mechanism for version
+- {@link io.vertx.core.dns.DnsResponseCode#BADSIG} Bad signature
+- {@link io.vertx.core.dns.DnsResponseCode#BADKEY} Bad key
+- {@link io.vertx.core.dns.DnsResponseCode#BADTIME} Bad timestamp
+
+All of those errors are "generated" by the DNS Server itself.
+
+You can obtain the DnsResponseCode from the DnsException like:
+
+[source,java]
+----
+{@link examples.DNSExamples#example16}
+----
diff --git a/src/main/asciidoc/eventbus.adoc b/src/main/asciidoc/eventbus.adoc
index c94ab27b483..1dd62b18f41 100644
--- a/src/main/asciidoc/eventbus.adoc
+++ b/src/main/asciidoc/eventbus.adoc
@@ -175,7 +175,15 @@ You can send a message with {@link io.vertx.core.eventbus.EventBus#send}.
{@link examples.EventBusExamples#example6}
----
-include::override/eventbus_headers.adoc[]
+==== Setting headers on messages
+
+Messages sent over the event bus can also contain headers. This can be specified by providing a
+{@link io.vertx.core.eventbus.DeliveryOptions} when sending or publishing:
+
+[source,$lang]
+----
+{@link examples.EventBusExamples#headers(io.vertx.core.eventbus.EventBus)}
+----
==== Message ordering
@@ -249,33 +257,62 @@ Message sends can fail for other reasons, including:
In all cases, the reply handler will be called with the specific failure.
-include::override/eventbus.adoc[]
+==== Message Codecs
-==== Clustered Event Bus
+You can send any object you like across the event bus if you define and register a {@link io.vertx.core.eventbus.MessageCodec message codec} for it.
-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.
+Message codecs have a name and you specify that name in the {@link io.vertx.core.eventbus.DeliveryOptions}
+when sending or publishing the message:
-==== Clustering programmatically
+[source,java]
+----
+{@link examples.EventBusExamples#example10}
+----
-If you're creating your Vert.x instance programmatically you get a clustered event bus by configuring the Vert.x
-instance as clustered;
+If you always want the same codec to be used for a particular type then you can register a default codec for it, then
+you don't have to specify the codec on each send in the delivery options:
-[source,$lang]
+[source,java]
----
-{@link examples.EventBusExamples#example12}
+{@link examples.EventBusExamples#example11}
----
-You should also make sure you have a {@link io.vertx.core.spi.cluster.ClusterManager} implementation on your classpath, for example the Hazelcast cluster manager.
+You unregister a message codec with {@link io.vertx.core.eventbus.EventBus#unregisterCodec}.
+
+Message codecs don't always have to encode and decode as the same type. For example you can write a codec that
+allows a MyPOJO class to be sent, but when that message is sent to a handler it arrives as a MyOtherPOJO class.
+
+Vert.x has built-in codecs for certain data types:
+
+- basic types (string, byte array, byte, int, long, double, boolean, short, char), or
+- some Vert.x data types (buffers, JSON array, JSON objects), or
+- types implementing the {@link io.vertx.core.shareddata.ClusterSerializable} interface, or
+- types implementing the `java.io.Serializable` interface.
+
+[IMPORTANT]
+====
+In clustered mode, {@link io.vertx.core.shareddata.ClusterSerializable} and `java.io.Serializable` objects are rejected by default, for security reasons.
+
+You can define which classes are allowed for encoding and decoding by providing functions which inspect the name of the class:
+
+- {@link io.vertx.core.eventbus.EventBus#clusterSerializableChecker EventBus.clusterSerializableChecker()}, and
+- {@link io.vertx.core.eventbus.EventBus#serializableChecker EventBus.serializableChecker()}.
+====
+
+==== Clustered Event Bus
-==== Clustering on the command line
+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.
-You can run Vert.x clustered on the command line with
+If you're creating your Vert.x instance programmatically, you get a clustered event bus by configuring the Vert.x instance as clustered:
+[source,$lang]
----
-vertx run my-verticle.js -cluster
+{@link examples.EventBusExamples#example12}
----
+You should also make sure you have one of the link:/docs/#clustering[{@link io.vertx.core.spi.cluster.ClusterManager} implementations] on your classpath.
+
=== Automatic clean-up in verticles
If you're registering event bus handlers from inside verticles, those handlers will be automatically unregistered
@@ -283,4 +320,27 @@ when the verticle is undeployed.
== Configuring the event bus
-include::override/configuring-eventbus.adoc[]
+The event bus can be configured.It is particularly useful when the event bus is clustered.
+Under the hood the event bus uses TCP connections to send and receive messages, so the {@link io.vertx.core.eventbus.EventBusOptions} let you configure all aspects of these TCP connections.
+As the event bus acts as a server and client, the configuration is close to {@link io.vertx.core.net.NetClientOptions} and {@link io.vertx.core.net.NetServerOptions}.
+
+[source,$lang]
+----
+{@link examples.EventBusExamples#example13}
+----
+
+The previous snippet depicts how you can use SSL connections for the event bus, instead of plain TCP connections.
+
+WARNING: To enforce the security in clustered mode, you **must** configure the cluster manager to use encryption or enforce security.
+Refer to the documentation of the cluster manager for further details.
+
+The event bus configuration needs to be consistent in all the cluster nodes.
+
+The {@link io.vertx.core.eventbus.EventBusOptions} also lets you specify whether the event bus is clustered, the port and host.
+
+When used in containers, you can also configure the public host and port:
+
+[source,$lang]
+----
+{@link examples.EventBusExamples#example14}
+----
diff --git a/src/main/asciidoc/http.adoc b/src/main/asciidoc/http.adoc
index 0091400f385..6a09ec1dcf3 100644
--- a/src/main/asciidoc/http.adoc
+++ b/src/main/asciidoc/http.adoc
@@ -59,6 +59,24 @@ The settings define how the client can use the connection, the default initial s
- {@link io.vertx.core.http.Http2Settings#getMaxConcurrentStreams}: `100` as recommended by the HTTP/2 RFC
- the default HTTP/2 settings values for the others
+=== Configuring server supported HTTP versions
+
+Default supported HTTP versions depends on the server configuration.
+
+- when TLS is disabled
+ - HTTP/1.1, HTTP/1.0
+ - HTTP/2 when {@link io.vertx.core.http.HttpServerOptions#isHttp2ClearTextEnabled} is `true`
+- when TLS is enabled and ALPN disabled
+ - HTTP/1.1 and HTTP/1.0
+- when TLS is enabled and ALPN enabled
+ - the protocols defined by {@link io.vertx.core.http.HttpServerOptions#getAlpnVersions}: by default HTTP/1.1 and HTTP/2
+
+If you want to disable HTTP/2 on the server
+- when TLS is disabled, set {@link io.vertx.core.http.HttpServerOptions#setHttp2ClearTextEnabled} to `false`
+- when TLS is enabled
+ - set ({@link io.vertx.core.http.HttpServerOptions#isUseAlpn}) to `false`
+ - _or_ remove HTTP/2 from the {@link io.vertx.core.http.HttpServerOptions#getAlpnVersions} list
+
=== Logging network server activity
For debugging purposes, network activity can be logged.
@@ -182,9 +200,9 @@ It also has case-insensitive keys, that means you can do the following:
{@link examples.HTTPExamples#example8}
----
-==== Request host
+==== Request authority
-Use {@link io.vertx.core.http.HttpServerRequest#host} to return the host of the HTTP request.
+Use {@link io.vertx.core.http.HttpServerRequest#authority} to return the authority of the HTTP request.
For HTTP/1.x requests the `host` header is returned, for HTTP/1 requests the `:authority` pseudo header is returned.
@@ -491,9 +509,9 @@ calling write with a string or buffer followed by calling end with no arguments.
{@link examples.HTTPExamples#example20}
----
-==== Closing the underlying connection
+==== Closing the underlying TCP connection
-You can close the underlying TCP connection with {@link io.vertx.core.http.HttpServerResponse#close}.
+You can close the underlying TCP connection with {@link io.vertx.core.http.HttpConnection#close}.
Non keep-alive connections will be automatically closed by Vert.x when the response is ended.
@@ -562,7 +580,7 @@ Or use {@link io.vertx.core.http.HttpServerResponse#putTrailer}.
If you were writing a web server, one way to serve a file from disk would be to open it as an {@link io.vertx.core.file.AsyncFile}
and pipe it to the HTTP response.
-Or you could load it it one go using {@link io.vertx.core.file.FileSystem#readFile} and write it straight to the response.
+Or you could load it in one go using {@link io.vertx.core.file.FileSystem#readFile} and write it straight to the response.
Alternatively, Vert.x provides a method which allows you to serve a file from disk or the filesystem to an HTTP response
in one operation.
@@ -580,7 +598,7 @@ Here's a very simple web server that serves files from the file system using sen
----
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 written you can use {@link io.vertx.core.http.HttpServerResponse#sendFile(String)}
+be notified when the file has been written you can use {@link io.vertx.core.http.HttpServerResponse#sendFile(String)}.
Please see the chapter about <> for restrictions about the classpath resolution or disabling it.
@@ -850,6 +868,26 @@ When a clients connects to an HTTP/2 server, it sends to the server its {@link i
The settings define how the server can use the connection, the default initial settings for a client are the default
values defined by the HTTP/2 RFC.
+=== Pool configuration
+
+ For performance purpose, the client uses connection pooling when interacting with HTTP/1.1 servers. The pool creates up
+ to 5 connections per server. You can override the pool configuration like this:
+
+ [source,$lang]
+ ----
+ {@link examples.HTTPExamples#examplePoolConfiguration}
+ ----
+
+ You can configure various pool {@link io.vertx.core.http.PoolOptions options} as follows
+
+- {@link io.vertx.core.http.PoolOptions options#setHttp1MaxSize} the maximum number of opened per HTTP/1.x server (5 by default)
+- {@link io.vertx.core.http.PoolOptions options#setHttp2MaxSize} the maximum number of opened per HTTP/2 server (1 by default), you *should* not change this value since a single HTTP/2 connection is capable of delivering the same performance level than multiple HTTP/1.x connections
+- {@link io.vertx.core.http.PoolOptions options#setCleanerPeriod} the period in milliseconds at which the pool checks expired connections (1 second by default)
+- {@link io.vertx.core.http.PoolOptions options#setEventLoopSize} sets the number of event loops the pool use (0 by default)
+- a value of 0 configures the pool to use the event loop of the caller
+- a positive value configures the pool load balance the creation of connection over a list of event loops determined by the value
+- {@link io.vertx.core.http.PoolOptions options#setMaxWaitQueueSize} the maximum number of HTTP requests waiting until a connection is available, when the queue is full, the request is rejected
+
=== Logging network client activity
For debugging purposes, network activity can be logged.
@@ -861,6 +899,23 @@ For debugging purposes, network activity can be logged.
See the chapter on <> for a detailed explanation.
+=== Advanced HTTP client creation
+
+You can pass options {@link io.vertx.core.Vertx#createHttpClient} methods to configure the HTTP client.
+
+Alternatively you can build a client with the builder {@link io.vertx.core.http.HttpClientBuilder API} :
+
+[source,$lang]
+----
+{@link examples.HTTPExamples#exampleClientBuilder01}
+----
+
+In addition to {@link io.vertx.core.http.HttpClientOptions} and {@link io.vertx.core.http.PoolOptions}, you
+can set
+
+- a connection event handler notified when the client <<_client_connections,connects>> to a server
+- a redirection handler to implement an alternative HTTP <<_30x_redirection_handling,redirect>> behavior
+
=== Making requests
The http client is very flexible and there are various ways you can make requests with it.
@@ -1020,7 +1075,7 @@ An {@link io.vertx.core.http.HttpClientRequest} instance is also a {@link io.ver
You can pipe to it from any {@link io.vertx.core.streams.ReadStream} instance.
-For, example, you could pipe a file on disk to a http request body as follows:
+For, example, you could pipe a file on disk to an http request body as follows:
[source,$lang]
----
@@ -1046,11 +1101,28 @@ no need to set the `Content-Length` of the request up-front.
==== Request timeouts
-You can set a timeout for a specific http request using {@link io.vertx.core.http.RequestOptions#setTimeout(long)} or
-{@link io.vertx.core.http.HttpClientRequest#setTimeout(long)}.
+You can set an idle timeout to prevent your application from unresponsive servers using {@link io.vertx.core.http.RequestOptions#setIdleTimeout(long)} or {@link io.vertx.core.http.HttpClientRequest#idleTimeout(long)}. When the request does not return any data within the timeout period an exception will fail the result and the request will be reset.
+
+[source,$lang]
+----
+{@link examples.HTTPExamples#clientIdleTimeout}
+----
+
+NOTE: the timeout starts when the {@link io.vertx.core.http.HttpClientRequest} is available, implying a connection was
+obtained from the pool.
+
+You can set a connect timeout to prevent your application from unresponsive busy client connection pool. The
+`Future` is failed when a connection is not obtained before the timeout delay.
+
+The connect timeout option is not related to the TCP {@link io.vertx.core.http.HttpClientOptions#setConnectTimeout(int)} option, when a request is made against a pooled HTTP client, the timeout applies to the duration to obtain a connection from the pool to serve the request,
+the timeout might fire because the server does not respond in time or the pool is too busy to serve a request.
-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.
+You can configure both timeout using {@link io.vertx.core.http.RequestOptions#setTimeout(long)}
+
+[source,$lang]
+----
+{@link examples.HTTPExamples#clientTimeout}
+----
==== Writing HTTP/2 frames
@@ -1093,6 +1165,14 @@ The request handler are notified of stream reset events with the {@link io.vertx
{@link examples.HTTP2Examples#example12}
----
+=== HTTP/2 RST flood protection
+
+An HTTP/2 server is protected against RST flood DDOS attacks (https://github.com/netty/netty/security/advisories/GHSA-xpw8-rcwv-8f8p[CVE-2023-44487]): there is an upper bound to the number of `RST`
+frames a server can receive in a time window. The default configuration sets the upper bound to `200` for a duration of
+`30` seconds.
+
+You can use {@link io.vertx.core.http.HttpServerOptions#setHttp2RstFloodMaxRstFramePerWindow} and {@link io.vertx.core.http.HttpServerOptions#setHttp2RstFloodWindowDuration} to override these settings.
+
=== Handling HTTP responses
You receive an instance of {@link io.vertx.core.http.HttpClientResponse} into the handler that you specify in of
@@ -1229,7 +1309,7 @@ Alternatively you can just parse the `Set-Cookie` headers yourself in the respon
The client can be configured to follow HTTP redirections provided by the `Location` response header when the client receives:
-* a `301`, `302`, `307` or `308` status code along with a HTTP GET or HEAD method
+* a `301`, `302`, `307` or `308` status code along with an HTTP GET or HEAD method
* a `303` status code, in addition the directed request perform an HTTP GET method
Here's an example:
@@ -1394,11 +1474,22 @@ If the body of the response was compressed via gzip it will include for example
Content-Encoding: gzip
-To enable compression set {@link io.vertx.core.http.HttpClientOptions#setTryUseCompression(boolean)} on the options
+To enable compression set {@link io.vertx.core.http.HttpClientOptions#setDecompressionSupported(boolean)} on the options
used when creating the client.
By default compression is disabled.
+=== Client side load balancing
+
+By default, when the client resolves a hostname to a list of several IP addresses, the client uses the first returned IP address.
+
+The http client can be configured to perform client side load balancing instead
+
+[source,$lang]
+----
+{@link examples.HTTPExamples#httpClientSideLoadBalancing}
+----
+
=== HTTP/1.x 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
@@ -1413,7 +1504,7 @@ When keep alive is enabled. Vert.x will add a `Connection: Keep-Alive` header to
When keep alive is disabled. Vert.x will add a `Connection: Close` header to each HTTP/1.1 request sent to signal
that the connection will be closed after completion of the response.
-The maximum number of connections to pool *for each server* is configured using {@link io.vertx.core.http.HttpClientOptions#setMaxPoolSize(int)}
+The maximum number of connections to pool *for each server* is configured using {@link io.vertx.core.http.PoolOptions#setHttp1MaxSize(int)}
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.
@@ -1449,7 +1540,7 @@ fairness of the distribution of the client requests over the connections to the
HTTP/2 advocates to use a single connection to a server, by default the http client uses a single
connection for each server, all the streams to the same server are multiplexed over the same connection.
-When the clients needs to use more than a single connection and use pooling, the {@link io.vertx.core.http.HttpClientOptions#setHttp2MaxPoolSize(int)}
+When the clients needs to use more than a single connection and use pooling, the {@link io.vertx.core.http.PoolOptions#setHttp2MaxSize(int)}
shall be used.
When it is desirable to limit the number of multiplexed streams per connection and use a connection
@@ -1507,7 +1598,7 @@ The {@link io.vertx.core.http.HttpClientRequest#connection()} method returns the
{@link examples.HTTP2Examples#example18}
----
-A connection handler can be set on the client to be notified when a connection has been established happens:
+A connection handler can be set on a client builder to be notified when a connection has been established happens:
[source,$lang]
----
@@ -1621,7 +1712,7 @@ NOTE: this only applies to the HTTP/2 protocol
Connection {@link io.vertx.core.http.HttpConnection#close} closes the connection:
- it closes the socket for HTTP/1.x
-- a shutdown with no delay for HTTP/2, the {@literal GOAWAY} frame will still be sent before the connection is closed. *
+- a shutdown with no delay for HTTP/2, the {@literal GOAWAY} frame will still be sent before the connection is closed.
The {@link io.vertx.core.http.HttpConnection#closeHandler} notifies when a connection is closed.
@@ -1660,7 +1751,7 @@ You can assign a number of event loop a client will use independently of the cli
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:
+Let's take a verticle creating an HTTP server such as:
.io.vertx.examples.http.sharing.HttpServerVerticle
[source,$lang]
@@ -1668,14 +1759,17 @@ Let's take a verticle creating a HTTP server such as:
{@link examples.HTTPExamples#serversharing(io.vertx.core.Vertx)}
----
-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.
+This service is listening on the port 8080.
+
+So, when this verticle is instantiated multiple times as with: `deploymentOptions.setInstances(2)`, what's happening ?
+If both verticles bound 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:
+
[source,$lang]
----
{@link examples.HTTPExamples#serversharingclient(io.vertx.core.Vertx)}
@@ -1795,18 +1889,24 @@ The {@link io.vertx.core.http.ServerWebSocket} instance enables you to retrieve
==== WebSockets on the client
-The Vert.x {@link io.vertx.core.http.HttpClient} supports WebSockets.
-
-You can connect a WebSocket to a server using one of the {@link io.vertx.core.http.HttpClient#webSocket} operations and
-providing a handler.
+e Vert.x {@link io.vertx.core.http.WebSocketClient} supports WebSockets.
-The handler will be called with an instance of {@link io.vertx.core.http.WebSocket} when the connection has been made:
+ You can connect a WebSocket to a server using one of the {@link io.vertx.core.http.WebSocketClient#connect} operations.
+ The returned future will be completed with an instance of {@link io.vertx.core.http.WebSocket} when the connection has been made:
[source,$lang]
----
{@link examples.HTTPExamples#example54}
----
+en connecting from a non Vert.x thread, you can create a {@link io.vertx.core.http.ClientWebSocket}, configure its handlers and
+then connect to the server:
+
+ [source,$lang]
+ ----
+ {@link examples.HTTPExamples#example54_bis}
+ ----
+
By default, the client sets the `origin` header to the server host, e.g http://www.example.com. Some servers will refuse
such request, you can configure the client to not set this header.
@@ -1836,7 +1936,7 @@ If you wish to write a single WebSocket message to the WebSocket you can do this
----
If the WebSocket message is larger than the maximum WebSocket frame size as configured with
-{@link io.vertx.core.http.HttpClientOptions#setMaxWebSocketFrameSize(int)}
+{@link io.vertx.core.http.WebSocketClientOptions#setMaxFrameSize(int)}
then Vert.x will split it into multiple WebSocket frames before sending it on the wire.
==== Writing frames to WebSockets
@@ -1909,7 +2009,7 @@ The addresses of the handlers are given by {@link io.vertx.core.http.WebSocket#b
=== Using a proxy for HTTP/HTTPS connections
-The http client supports accessing http/https URLs via a HTTP proxy (e.g. Squid) or _SOCKS4a_ or _SOCKS5_ proxy.
+The http client supports accessing http/https URLs via an HTTP proxy (e.g. Squid) or _SOCKS4a_ or _SOCKS5_ proxy.
The CONNECT protocol uses HTTP/1.x but can connect to HTTP/1.x and HTTP/2 servers.
Connecting to h2c (unencrypted HTTP/2 servers) is likely not supported by http proxies since they will support
diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc
index 317f360c805..b093c2a46a4 100644
--- a/src/main/asciidoc/index.adoc
+++ b/src/main/asciidoc/index.adoc
@@ -16,6 +16,7 @@ Vert.x core provides functionality for things like:
* Datagram Sockets
* DNS client
* File system access
+* Virtual threads
* High availability
* Native transports
* Clustering
@@ -34,11 +35,68 @@ Instead, we automatically generate an *idiomatic* equivalent of the core Java AP
From now on we'll just use the word *core* to refer to Vert.x core.
-include::override/dependencies.adoc[]
+If you are using Maven or Gradle, add the following dependency to the _dependencies_ section of your
+project descriptor to access the Vert.x Core API:
+
+* Maven (in your `pom.xml`):
+
+[source,xml,subs="+attributes"]
+----
+
+ io.vertx
+ vertx-core
+ ${maven.version}
+
+----
+
+* Gradle (in your `build.gradle` file):
+
+[source,groovy,subs="+attributes"]
+----
+dependencies {
+ compile 'io.vertx:vertx-core:${maven.version}'
+}
+----
Let's discuss the different concepts and features in core.
-include::override/in-the-beginning.adoc[]
+== In the beginning there was Vert.x
+
+You can't do much in Vert.x-land unless you can communicate with a {@link io.vertx.core.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:
+
+[source,$lang]
+----
+{@link examples.CoreExamples#example1}
+----
+
+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 Vert.x object you can also specify options if the defaults aren't right for you:
+
+[source,$lang]
+----
+{@link examples.CoreExamples#example2}
+----
+
+The {@link io.vertx.core.VertxOptions} object has many settings and allows you to configure things like clustering, high availability, pool sizes and various other settings.
+
+=== Creating a clustered Vert.x object
+
+If you're creating a *clustered Vert.x* (See the section on the <> 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?
@@ -223,7 +281,93 @@ You can think of a verticle as a bit like an actor in the http://en.wikipedia.or
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 <>.
-include::override/verticles.adoc[]
+=== Writing Verticles
+
+Verticle classes must implement the {@link io.vertx.core.Verticle} interface.
+
+They can implement it directly if you like but usually it's simpler to extend
+the abstract class {@link io.vertx.core.AbstractVerticle}.
+
+Here's an example verticle:
+
+----
+public class MyVerticle extends AbstractVerticle {
+
+ // Called when verticle is deployed
+ public void start() {
+ }
+
+ // Optional - called when verticle is undeployed
+ public void stop() {
+ }
+
+}
+----
+
+Normally you would override the start method like in the example above.
+
+When Vert.x deploys the verticle it will call the start method, and when the method has completed the verticle will
+be considered started.
+
+You can also optionally override the stop method. This will be called by Vert.x when the verticle is undeployed and when
+the method has completed the verticle will be considered stopped.
+
+=== 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 start an HTTP server in the start method and
+propagate the asynchronous result of the server `listen` method.
+
+You can't block waiting for the HTTP server to bind in your start method as that would break the <>.
+
+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.
+
+Some time later, after you've done everything you need to do (e.g. start the HTTP server), you can call complete
+on the Future (or fail) to signal that you're done.
+
+Here's an example:
+
+----
+public class MyVerticle extends AbstractVerticle {
+
+ private HttpServer server;
+
+ @Override
+ public void start(Promise startPromise) {
+ server = vertx.createHttpServer().requestHandler(req -> {
+ req.response()
+ .putHeader("content-type", "text/plain")
+ .end("Hello from Vert.x!");
+ });
+
+ // Now bind the server:
+ server.listen(8080)
+ .mapEmpty()
+ .onComplete(startPromise);
+ }
+}
+----
+
+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.
+
+----
+public class MyVerticle extends AbstractVerticle {
+
+ @Override
+ public void stop(Promise stopPromise) {
+ doSomethingThatTakesTime()
+ .mapEmpty()
+ .onComplete(stopPromise);
+ }
+}
+----
+
+INFO: You don't need to manually stop the HTTP server started by a verticle, in the verticle's stop method. Vert.x
+will automatically stop any running server when the verticle is undeployed.
=== Verticle Types
@@ -258,7 +402,7 @@ Worker verticles are designed for calling blocking code, as they won't block any
If you don't want to use a worker verticle to run blocking code, you can also run <>
directly while on an event loop.
-If you want to deploy a verticle as a worker verticle you do that with {@link io.vertx.core.DeploymentOptions#setWorker}.
+If you want to deploy a verticle as a worker verticle you do that with {@link io.vertx.core.DeploymentOptions#setThreadingModel}.
[source,$lang]
----
@@ -268,6 +412,21 @@ If you want to deploy a verticle as a worker verticle you do that with {@link io
Worker verticle instances are never executed concurrently by Vert.x by more than one thread, but can executed by
different threads at different times.
+=== Virtual thread verticles
+
+A virtual thread verticle is just like a standard verticle but it's executed using virtual threads, rather than using an event loop.
+
+Virtual thread verticles are designed to use an async/await model with Vert.x futures.
+
+If you want to deploy a verticle as a <> you do that with {@link io.vertx.core.DeploymentOptions#setThreadingModel}.
+
+[source,$lang]
+----
+{@link examples.CoreExamples#example7_2}
+----
+
+NOTE: this feature requires Java 21
+
=== Deploying verticles programmatically
You can deploy a verticle using one of the {@link io.vertx.core.Vertx#deployVerticle} method, specifying a verticle
@@ -368,65 +527,33 @@ want to deploy:
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 utilise all the cores.
-include::override/verticle-configuration.adoc[]
-
-=== 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.
+=== Passing configuration to a verticle
-To run an verticle with the high availability enabled, just append the `-ha` switch:
+Configuration in the form of JSON can be passed to a verticle at deployment time:
-[source]
+[source,$lang]
----
-vertx run my-verticle.js -ha
+{@link examples.CoreExamples#example13}
----
-When enabling high availability, no need to add `-cluster`.
-
-More details about the high availability feature and configuration in the <>
- 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 JDK on your `PATH`.
-
-Vert.x supports Java from 8 to 17.
-
-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:
+This configuration is then available via the {@link io.vertx.core.Context} object or directly using the
+{@link io.vertx.core.AbstractVerticle#config()} method. The configuration is returned as a JSON object so you
+can retrieve data as follows:
+[source,$lang]
----
-# 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
+{@link examples.ConfigurableVerticleExamples#start()}
----
-You can even run Java source verticles without compiling them first!
+=== Accessing environment variables in a Verticle
+
+Environment variables and system properties are accessible using the Java API:
+[source,$lang]
----
-vertx run SomeJavaSourceFile.java
+{@link examples.CoreExamples#systemAndEnvProperties()}
----
-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.
@@ -550,7 +677,7 @@ A different worker pool can be specified in deployment options:
[[event_bus]]
include::eventbus.adoc[]
-include::override/json.adoc[]
+include::json.adoc[]
include::json-pointers.adoc[]
@@ -568,6 +695,9 @@ include::datagrams.adoc[]
include::dns.adoc[]
+[[virtual_threads]]
+include::virtualthreads.adoc[]
+
[[streams]]
include::streams.adoc[]
@@ -603,8 +733,8 @@ 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 {@link io.vertx.core.Vertx#executeBlocking} specifying both the blocking code to execute and a
-result handler to be called back asynchronous when the blocking code has been executed.
+It's done by calling {@link io.vertx.core.Vertx#executeBlocking} with blocking code to execute, as return you get a
+future completed with the result of the blocking code execution.
[source,$lang]
----
@@ -621,7 +751,7 @@ which can interact with verticles using the event-bus or {@link io.vertx.core.Co
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 {@link io.vertx.core.Vertx#executeBlocking(io.vertx.core.Handler,boolean)}
+If you don't care about ordering you can call {@link io.vertx.core.Vertx#executeBlocking(java.util.concurrent.Callable,boolean)}
specifying `false` as the argument to `ordered`. In this case any executeBlocking may be executed in parallel
on the worker pool.
@@ -660,334 +790,21 @@ Worker executors can be configured when created:
NOTE: the configuration is set when the worker pool is created
-== 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
-{@link io.vertx.core.spi.metrics.VertxMetrics API Documentation}.
+== Vert.x SPI
-You can also specify a metrics factory programmatically if embedding Vert.x using
-{@link io.vertx.core.metrics.MetricsOptions#setFactory(io.vertx.core.spi.VertxMetricsFactory)}.
+A Vert.x instance has a few extension points knows as _SPI_ (Service Provider Interface).
-== The 'vertx' command line
+Such SPI are often loaded from the classpath using Java's `ServiceLoader` mechanism.
-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 JDK on your `PATH`.
+=== Metrics and tracing SPI
-Vert.x supports Java from 8 to 17.
+By default, Vert.x does not record any metrics nor does any tracing. Instead, it provides an SPI for others to implement which can be added
+to the classpath. The metrics SPI is a feature which allows implementers to capture events from Vert.x in order to
+collect and report metrics, likewise the tracing SPI does the same for traces.
-NOTE: The JDK is required to support on the fly compilation of Java code.
+For more information on this, please consult https://vertx.io/docs/#monitoring
-=== Run verticles
-
-You can run raw Vert.x verticles directly from the command line using `vertx run`. Here is a couple of examples of
-the `run` _command_:
-
-[source]
-----
-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.
-
-[source]
-----
-vertx run groovy:io.vertx.example.MyGroovyVerticle
-----
-
-The `vertx run` command can take a few optional parameters, they are:
-
- * `-options ` - Provides the Vert.x options.
- `options` is the name of a JSON file that represents the Vert.x options, or a JSON string. This is optional.
- * `-conf ` - Provides some configuration to the verticle.
- `config` is the name of a JSON file that represents the configuration for the verticle, or a JSON string. This is optional.
- * `-cp ` - 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 ` - 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 bound 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
- bound for cluster communication with other Vert.x instances. If not set, the clustered eventbus tries to bind to the
- same host as the underlying cluster manager. As a last resort, an address will be picked among the available network
- interfaces.
- * `-cluster-public-port` - If the `cluster` option has also been specified then this determines which port will be advertised for
- cluster communication with other Vert.x instances. Default is `-1`, which means same as `cluster-port`.
- * `-cluster-public-host` - If the `cluster` option has also been specified then this determines which host address will be advertised for
- cluster communication with other Vert.x instances. If not specified, Vert.x uses the value of `cluster-host`.
- * `-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__+++`
-
-You can also set system properties using: `-Dkey=value`.
-
-Here are some more examples:
-
-Run a JavaScript verticle server.js with default settings
-[source]
-----
-vertx run server.js
-----
-
-Run 10 instances of a pre-compiled Java verticle specifying classpath
-[source]
-----
-vertx run com.acme.MyVerticle -cp "classes:lib/myjar.jar" -instances 10
-----
-
-Run 10 instances of a Java verticle by source _file_
-[source]
-----
-vertx run MyVerticle.java -instances 10
-----
-
-Run 20 instances of a ruby worker verticle
-[source]
-----
-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
-[source]
-----
-vertx run handler.js -cluster
-vertx run sender.js -cluster
-----
-
-Run a Ruby verticle passing it some config
-[source]
-----
-vertx run my_verticle.rb -conf my_verticle.conf
-----
-Where `my_verticle.conf` might contain something like:
-
-[source, json]
-----
-{
- "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:
-
-[source]
-----
-vertx bare
-----
-
-Depending on your cluster configuration, you may have to append the `cluster-host` and `cluster-port` parameters.
-
-=== Executing a Vert.x application 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. Like any executable Java jar it can be executed with.
-
-[source]
-----
-java -jar my-application-fat.jar
-----
-
-There is nothing really Vert.x specific about this, you could do this with any Java application
-
-You can either create your own main class and specify that in the manifest, but it's recommended that you write your
-code as verticles and use the Vert.x {@link io.vertx.core.Launcher} class (`io.vertx.core.Launcher`) as your main
-class. This is the same main class used when running Vert.x at the command line and therefore allows you to
-specify command line arguments, such as `-instances` in order to scale your application more easily.
-
-To deploy your verticle in a _fatjar_ like this you must have a _manifest_ with:
-
-* `Main-Class` set to `io.vertx.core.Launcher`
-* `Main-Verticle` specifying the main verticle (fully qualified class name or script file name)
-
-You can also provide the usual command line arguments that you would pass to `vertx run`:
-[source]
-----
-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: Please consult the Maven/Gradle simplest and Maven/Gradle verticle examples in the examples repository for
-examples of building applications as fatjars.
-
-A fat jar executes the `run` command, by default.
-
-=== Displaying version of Vert.x
-To display the vert.x version, just launch:
-
-[source]
-----
-vertx version
-----
-
-=== Other commands
-
-The `vertx` command line and the `Launcher` also provide other _commands_ in addition to `run` and `version`:
-
-You can create a `bare` instance using:
-
-[source]
-----
-vertx bare
-# or
-java -jar my-verticle-fat.jar bare
-----
-
-You can also start an application in background using:
-
-[source]
-----
-java -jar my-verticle-fat.jar start --vertx-id=my-app-name
-----
-
-If `my-app-name` is not set, a random id will be generated, and printed on the command prompt. You can pass `run`
-options to the `start` command:
-
-[source]
-----
-java -jar my-verticle-fat.jar start —-vertx-id=my-app-name -cluster
-----
-
-Once launched in background, you can stop it with the `stop` command:
-
-[source]
-----
-java -jar my-verticle-fat.jar stop my-app-name
-----
-
-You can also list the vert.x application launched in background using:
-
-[source]
-----
-java -jar my-verticle-fat.jar list
-----
-
-The `start`, `stop` and `list` command are also available from the `vertx` tool. The start` command supports a couple of options:
-
- * `vertx-id` : the application id, uses a random UUID if not set
- * `java-opts` : the Java Virtual Machine options, uses the `JAVA_OPTS` environment variable if not set.
- * `redirect-output` : redirect the spawned process output and error streams to the parent process streams.
-
- If option values contain spaces, don't forget to wrap the value between `""` (double-quotes).
-
- As the `start` command spawns a new process, the java options passed to the JVM are not propagated, so you **must**
- use `java-opts` to configure the JVM (`-X`, `-D`...). If you use the `CLASSPATH` environment variable, be sure it
- contains all the required jars (vertx-core, your jars and all the dependencies).
-
-The set of commands is extensible, refer to the <> section.
-
-=== Live Redeploy
-
-When developing it may be convenient to automatically redeploy your application upon file changes. The `vertx`
-command line tool and more generally the {@link io.vertx.core.Launcher} class offers this feature. Here are some
-examples:
-
-[source]
-----
-vertx run MyVerticle.groovy --redeploy="**/*.groovy" --launcher-class=io.vertx.core.Launcher
-vertx run MyVerticle.groovy --redeploy="**/*.groovy,**/*.rb" --launcher-class=io.vertx.core.Launcher
-java io.vertx.core.Launcher run org.acme.MyVerticle --redeploy="**/*.class" --launcher-class=io.vertx.core
-.Launcher -cp ...
-----
-
-The redeployment process is implemented as follows. First your application is launched as a background application
-(with the `start` command). On matching file changes, the process is stopped and the application is restarted.
-This avoids leaks, as the process is restarted.
-
-To enable the live redeploy, pass the `--redeploy` option to the `run` command. The `--redeploy` indicates the
-set of file to _watch_. This set can use Ant-style patterns (with `\**`, `*` and `?`). You can specify
-several sets by separating them using a comma (`,`). Patterns are relative to the current working directory.
-
-Parameters passed to the `run` command are passed to the application. Java Virtual Machine options can be
-configured using `--java-opts`. For instance, to pass the `conf` parameter or a system property, you need to
-use: `--java-opts="-conf=my-conf.json -Dkey=value"`
-
-The `--launcher-class` option determine with with _main_ class the application is launcher. It's generally
-{@link io.vertx.core.Launcher}, but you have use you own _main_.
-
-The redeploy feature can be used in your IDE:
-
-* Eclipse - create a _Run_ configuration, using the `io.vertx.core.Launcher` class a _main class_. In the _Program
-arguments_ area (in the _Arguments_ tab), write `run your-verticle-fully-qualified-name --redeploy=\**/*.java
---launcher-class=io.vertx.core.Launcher`. You can also add other parameters. The redeployment works smoothly as
-Eclipse incrementally compiles your files on save.
-* IntelliJ - create a _Run_ configuration (_Application_), set the _Main class_ to `io.vertx.core.Launcher`. In
-the Program arguments write: `run your-verticle-fully-qualified-name --redeploy=\**/*.class
---launcher-class=io.vertx.core.Launcher`. To trigger the redeployment, you need to _make_ the project or
-the module explicitly (_Build_ menu -> _Make project_).
-
-To debug your application, create your run configuration as a remote application and configure the debugger
-using `--java-opts`. However, don't forget to re-plug the debugger after every redeployment as a new process is
-created every time.
-
-You can also hook your build process in the redeploy cycle:
-
-[source]
-----
-java -jar target/my-fat-jar.jar --redeploy="**/*.java" --on-redeploy="mvn package"
-java -jar build/libs/my-fat-jar.jar --redeploy="src/**/*.java" --on-redeploy='./gradlew shadowJar'
-----
-
-The "on-redeploy" option specifies a command invoked after the shutdown of the application and before the
-restart. So you can hook your build tool if it updates some runtime artifacts. For instance, you can launch `gulp`
-or `grunt` to update your resources. Don't forget that passing parameters to your application requires the
-`--java-opts` param:
-
-[source]
-----
-java -jar target/my-fat-jar.jar --redeploy="**/*.java" --on-redeploy="mvn package" --java-opts="-Dkey=val"
-java -jar build/libs/my-fat-jar.jar --redeploy="src/**/*.java" --on-redeploy='./gradlew shadowJar' --java-opts="-Dkey=val"
-----
-
-The redeploy feature also supports the following settings:
-
-* `redeploy-scan-period` : the file system check period (in milliseconds), 250ms by default
-* `redeploy-grace-period` : the amount of time (in milliseconds) to wait between 2 re-deployments, 1000ms by default
-* `redeploy-termination-period` : the amount of time to wait after having stopped the application (before
-launching user command). This is useful on Windows, where the process is not killed immediately. The time is given
-in milliseconds. 0 ms by default.
-
-== Cluster Managers
+=== Cluster Manager SPI
In Vert.x a cluster manager is used for various functions including:
@@ -1003,17 +820,30 @@ The default cluster manager used in the Vert.x distributions is one that uses ht
can be easily replaced by a different implementation as Vert.x cluster managers are pluggable.
A cluster manager must implement the interface {@link io.vertx.core.spi.cluster.ClusterManager}. Vert.x locates
-cluster managers at run-time by using the Java
-https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html[Service Loader] functionality to locate
-instances of {@link io.vertx.core.spi.cluster.ClusterManager} on the classpath.
+cluster managers at run-time by using the Java https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html[Service Loader] functionality to locate instances of {@link io.vertx.core.spi.cluster.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
-{@link io.vertx.core.VertxOptions#setClusterManager(io.vertx.core.spi.cluster.ClusterManager)}.
+For more information on this, please consult https://vertx.io/docs/#clustering
+
+=== Programmatic SPI selection and configuration
+
+The {@link io.vertx.core.VertxBuilder} gives you more control over the SPI selection and configuration.
+
+[source,$lang]
+----
+{@link examples.CoreExamples#vertxBuilder}
+----
+
+Clustered instances can also be created.
+
+[source,$lang]
+----
+{@link examples.CoreExamples#clusteredVertxBuilder}
+----
== Logging
@@ -1025,7 +855,6 @@ The logging backend is selected as follows:
. JDK logging when a `vertx-default-jul-logging.properties` file is in the classpath or,
. a backend present in the classpath, in the following order of preference:
.. SLF4J
-.. Log4J
.. Log4J2
Otherwise Vert.x defaults to JDK logging.
@@ -1105,154 +934,142 @@ SEVERE: java.io.IOException: Connection reset by peer
It means that the client is resetting the HTTP connection instead of closing it. This message also indicates that you
may have not consumed the complete payload (the connection was cut before you were able to).
-include::override/hostname-resolution.adoc[]
+== Host name resolution
-== High Availability and Fail-Over
+Vert.x uses an an address resolver for resolving host name into IP addresses instead of
+the JVM built-in blocking resolver.
-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.
+A host name resolves to an IP address using:
-=== Automatic failover
+- the _hosts_ file of the operating system
+- otherwise DNS queries against a list of servers
-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_.
+By default it will use the list of the system DNS server addresses from the environment, if that list cannot be
+retrieved it will use Google's public DNS servers `"8.8.8.8"` and `"8.8.4.4"`.
-To run vert.x with the _HA_ enabled, just add the `-ha` flag to the command line:
+DNS servers can be also configured when creating a {@link io.vertx.core.Vertx} instance:
-[source]
+[source,$lang]
----
-vertx run my-verticle.js -ha
+{@link examples.CoreExamples#configureDNSServers}
----
-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:
+The default port of a DNS server is `53`, when a server uses a different port, this port can be set
+using a colon delimiter: `192.168.0.2:40000`.
-[source]
-----
-vertx run my-other-verticle.js -ha
-----
+NOTE: sometimes it can be desirable to use the JVM built-in resolver, the JVM system property
+_-Dvertx.disableDnsResolver=true_ activates this behavior
-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.
+=== Failover
-NOTE: the migration is only possible if the second vert.x instance has access to the verticle file (here
-`my-verticle.js`).
+When a server does not reply in a timely manner, the resolver will try the next one from the list, the search
+is limited by {@link io.vertx.core.dns.AddressResolverOptions#setMaxQueries(int)} (the default value is `4` queries).
-IMPORTANT: Please note that cleanly closing a Vert.x instance will not cause failover to occur, e.g. `CTRL-C`
-or `kill -SIGINT`
+A DNS query is considered as failed when the resolver has not received a correct answer within
+{@link io.vertx.core.dns.AddressResolverOptions#getQueryTimeout()} milliseconds (the default value is `5` seconds).
-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:
+=== Server list rotation
-[source]
-----
-vertx run -ha
-----
+By default the dns server selection uses the first one, the remaining servers are used for failover.
-When using the `-ha` switch you do not need to provide the `-cluster` switch, as a cluster is assumed if you
-want HA.
+You can configure {@link io.vertx.core.dns.AddressResolverOptions#setRotateServers(boolean)} to `true` to let
+the resolver perform a round-robin selection instead. It spreads the query load among the servers and avoids
+all lookup to hit the first server of the list.
-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.
+Failover still applies and will use the next server in the list.
-=== HA groups
+=== Hosts mapping
-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.
+The _hosts_ file of the operating system is used to perform a hostname lookup for an ipaddress.
-To specify an HA group you use the `-hagroup` switch when running the verticle, e.g.
+An alternative _hosts_ file can be used instead:
-[source]
+[source,$lang]
----
-vertx run my-verticle.js -ha -hagroup my-group
+{@link examples.CoreExamples#configureHosts}
----
-Let's look at an example:
+=== Search domains
-In a first terminal:
+By default the resolver will use the system DNS search domains from the environment. Alternatively an explicit search domain
+list can be provided:
-[source]
+[source,$lang]
----
-vertx run my-verticle.js -ha -hagroup g1
+{@link examples.CoreExamples#configureSearchDomains()}
----
-In a second terminal, let's run another verticle using the same group:
+When a search domain list is used, the threshold for the number of dots is `1` or loaded from `/etc/resolv.conf`
+on Linux, it can be configured to a specific value with {@link io.vertx.core.dns.AddressResolverOptions#setNdots(int)}.
-[source]
-----
-vertx run my-other-verticle.js -ha -hagroup g1
-----
+=== MacOS configuration
-Finally, in a third terminal, launch another verticle using a different group:
+MacOS has a specific native extension to get the name server configuration of the system based on https://opensource.apple.com/tarballs/mDNSResponder/[Apple's open source mDNSResponder]. When this extension is not present,
+Netty logs the following warning.
-[source]
----
-vertx run yet-another-verticle.js -ha -hagroup g2
+[main] WARN io.netty.resolver.dns.DnsServerAddressStreamProviders - Can not find io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider in the classpath, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS.
----
-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.
+This extension is not required as its absence does not prevent Vert.x to execute, yet is *recommended*.
-=== Dealing with network partitions - Quorum
+You can add it to your classpath to improve the integration and remove the warning.
-The HA implementation also supports quorum. 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 quorum http://en.wikipedia.org/wiki/Quorum_(distributed_computing)[here].
-
-To run vert.x instances with a quorum you specify `-quorum` on the command line, e.g.
-
-In a first terminal:
-[source]
+.Intel-based Mac
+[source,xml]
----
-vertx run my-verticle.js -ha -quorum 3
+
+ mac-intel
+
+
+ mac
+ x86_64
+
+
+
+
+ io.netty
+ netty-resolver-dns-native-macos
+ osx-x86_64
+
+
+
+
----
-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:
-[source]
+.M1/M2 Mac
+[source,xml]
----
-vertx run my-other-verticle.js -ha -quorum 3
+
+ mac-silicon
+
+
+ mac
+ aarch64
+
+
+
+
+ io.netty
+ netty-resolver-dns-native-macos
+ osx-aarch_64
+
+
+
+
----
-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.
+== Native transports
-In a third console, you can start another instance of vert.x:
+Vert.x can run with http://netty.io/wiki/native-transports.html[native transports] (when available) on BSD (OSX) and Linux:
-[source]
+[source,$lang]
----
-vertx run yet-another-verticle.js -ha -quorum 3
+{@link examples.CoreExamples#configureNative()}
----
-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.
-
-Quorum can also be used in conjunction with ha groups. In that case, quorum are resolved for each particular
-group.
-
-== Native transports
-
-Vert.x can run with http://netty.io/wiki/native-transports.html[native transports] (when available) on BSD (OSX) and Linux:
-
-include::override/configuring-native.adoc[]
+NOTE: preferring native transport will not prevent the application to execute (for example if a JAR is missing).
+If your application requires native transport, you need to check {@link io.vertx.core.Vertx#isNativeTransportEnabled()}.
=== Native Linux Transport
@@ -1382,105 +1199,6 @@ 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.
-== Vert.x Command Line Interface API
-
-include::cli.adoc[]
-
-== The vert.x Launcher
-
-The vert.x {@link io.vertx.core.Launcher} is used in _fat jar_ as main class, and by the `vertx` command line
-utility. It executes a set of _commands_ such as _run_, _bare_, _start_...
-
-=== Extending the vert.x Launcher
-
-You can extend the set of command by implementing your own {@link io.vertx.core.spi.launcher.Command} (in Java only):
-
-[source, java]
-----
-@Name("my-command")
-@Summary("A simple hello command.")
-public class MyCommand extends DefaultCommand {
-
- private String name;
-
- @Option(longName = "name", required = true)
- public void setName(String n) {
- this.name = n;
- }
-
- @Override
- public void run() throws CLIException {
- System.out.println("Hello " + name);
- }
-}
-----
-
-You also need an implementation of {@link io.vertx.core.spi.launcher.CommandFactory}:
-
-[source, java]
-----
-public class HelloCommandFactory extends DefaultCommandFactory {
- public HelloCommandFactory() {
- super(HelloCommand.class);
- }
-}
-----
-
-Then, create the `src/main/resources/META-INF/services/io.vertx.core.spi.launcher.CommandFactory` and add a line
-indicating the fully qualified name of the factory:
-
-----
-io.vertx.core.launcher.example.HelloCommandFactory
-----
-
-Builds the jar containing the command. Be sure to includes the SPI file
-(`META-INF/services/io.vertx.core.spi.launcher.CommandFactory`).
-
-Then, place the jar containing the command into the classpath of your fat-jar (or include it inside) or in the `lib`
-directory of your vert.x distribution, and you would be able to execute:
-
-[source]
-----
-vertx hello vert.x
-java -jar my-fat-jar.jar hello vert.x
-----
-
-=== Using the Launcher in fat jars
-
-To use the {@link io.vertx.core.Launcher} class in a _fat-jar_ just set the `Main-Class` of the _MANIFEST_ to
-`io.vertx.core.Launcher`. In addition, set the `Main-Verticle` _MANIFEST_ entry to the name of your main verticle.
-
-By default, it executed the `run` command. However, you can configure the default command by setting the
-`Main-Command` _MANIFEST_ entry. The default command is used if the _fat jar_ is launched without a command.
-
-=== Sub-classing the Launcher
-
-You can also create a sub-class of {@link io.vertx.core.Launcher} to start your application. The class has been
-designed to be easily extensible.
-
-A {@link io.vertx.core.Launcher} sub-class can:
-
-* customize the vert.x configuration in {@link io.vertx.core.Launcher#beforeStartingVertx(io.vertx.core.VertxOptions)}
-* retrieve the vert.x instance created by the "run" or "bare" command by
-overriding {@link io.vertx.core.Launcher#afterStartingVertx(io.vertx.core.Vertx)}
-* configure the default verticle and command with
-{@link io.vertx.core.impl.launcher.VertxCommandLauncher#getMainVerticle()} and
-{@link io.vertx.core.impl.launcher.VertxCommandLauncher#getDefaultCommand()}
-* add / remove commands using {@link io.vertx.core.impl.launcher.VertxCommandLauncher#register(java.lang.Class)}
-and {@link io.vertx.core.impl.launcher.VertxCommandLauncher#unregister(java.lang.String)}
-
-=== Launcher and exit code
-
-When you use the {@link io.vertx.core.Launcher} class as main class, it uses the following exit code:
-
-* `0` if the process ends smoothly, or if an uncaught error is thrown
-* `1` for general purpose error
-* `11` if Vert.x cannot be initialized
-* `12` if a spawn process cannot be started, found or stopped. This error code is used by the `start` and
-`stop` command
-* `14` if the system configuration is not meeting the system requirement (shc as java not found)
-* `15` if the main verticle cannot be deployed
-
== Configuring Vert.x cache
When Vert.x needs to read a file from the classpath (embedded in a fat jar, in a jar form the classpath or a file
@@ -1495,8 +1213,6 @@ application with:
[source]
----
-vertx run my.Verticle -Dvertx.cacheDirBase=/tmp/vertx-cache
-# or
java -jar my-fat.jar vertx.cacheDirBase=/tmp/vertx-cache
----
@@ -1511,4 +1227,4 @@ directory and serves it from there. Do not use this setting in production, it ca
Finally, you can disable completely the cache by using `-Dvertx.disableFileCPResolving=true`. This setting is not
without consequences. Vert.x would be unable to read any files from the classpath (only from the file system). Be
-very careful when using this settings.
+very careful when using this setting.
diff --git a/src/main/asciidoc/override/json.adoc b/src/main/asciidoc/json.adoc
similarity index 88%
rename from src/main/asciidoc/override/json.adoc
rename to src/main/asciidoc/json.adoc
index 8f3d263c5b2..535d1cad5b8 100644
--- a/src/main/asciidoc/override/json.adoc
+++ b/src/main/asciidoc/json.adoc
@@ -21,14 +21,14 @@ You can create a JSON object from a string JSON representation as follows:
[source,java]
----
-{@link docoverride.json.Examples#example0_1}
+{@link examples.JsonExamples#example0_1}
----
You can create a JSON object from a map as follows:
[source,java]
----
-{@link docoverride.json.Examples#exampleCreateFromMap}
+{@link examples.JsonExamples#exampleCreateFromMap}
----
==== Putting entries into a JSON object
@@ -39,7 +39,7 @@ The method invocations can be chained because of the fluent API:
[source,java]
----
-{@link docoverride.json.Examples#example1}
+{@link examples.JsonExamples#example1}
----
==== Getting values from a JSON object
@@ -48,7 +48,7 @@ You get values from a JSON object using the `getXXX` methods, for example:
[source,java]
----
-{@link docoverride.json.Examples#example2}
+{@link examples.JsonExamples#example2}
----
==== Mapping between JSON objects and Java objects
@@ -59,7 +59,7 @@ You can instantiate a Java object and populate its fields from a JSON object as
[source,java]
----
-{@link docoverride.json.Examples#mapToPojo}
+{@link examples.JsonExamples#mapToPojo}
----
Note that both of the above mapping directions use Jackson's `ObjectMapper#convertValue()` to perform the
@@ -92,7 +92,7 @@ You can create a JSON array from a string JSON representation as follows:
[source,java]
----
-{@link docoverride.json.Examples#example0_2}
+{@link examples.JsonExamples#example0_2}
----
==== Adding entries into a JSON array
@@ -101,7 +101,7 @@ You add entries to a JSON array using the {@link io.vertx.core.json.JsonArray#ad
[source,java]
----
-{@link docoverride.json.Examples#example3}
+{@link examples.JsonExamples#example3}
----
==== Getting values from a JSON array
@@ -110,7 +110,7 @@ You get values from a JSON array using the `getXXX` methods, for example:
[source,java]
----
-{@link docoverride.json.Examples#example4}
+{@link examples.JsonExamples#example4}
----
==== Encoding a JSON array to a String
@@ -125,5 +125,5 @@ When you are unsure of the string validity then you should use instead `{@link i
[source,java]
----
-{@link docoverride.json.Examples#example5}
+{@link examples.JsonExamples#example5}
----
diff --git a/src/main/asciidoc/net.adoc b/src/main/asciidoc/net.adoc
index c1d9a3d30bb..1b9105f6352 100644
--- a/src/main/asciidoc/net.adoc
+++ b/src/main/asciidoc/net.adoc
@@ -183,6 +183,16 @@ This handler will then be called when the close has fully completed.
{@link examples.NetExamples#example9}
----
+=== Client socket shutdown
+
+When a client is closed with a grace period, each socket opened by the client will be notified with a shutdown event, to
+let the opportunity to perform a protocol level close before the actual socket close.
+
+[source,$lang]
+----
+{@link examples.NetExamples#shutdownHandler}
+----
+
=== Automatic clean-up in verticles
If you're creating TCP servers and clients from inside verticles, those servers and clients will be automatically closed
@@ -204,14 +214,6 @@ You can instantiate more instances programmatically in your code:
{@link examples.NetExamples#example11}
----
-or, you can simply deploy more instances of your server verticle by using the `-instances` option
-on the command line:
-
-[source]
-----
-> vertx run com.mycompany.MyVerticle -instances 10
-----
-
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.
@@ -355,9 +357,27 @@ TCP server (Net/Http) can be configured with traffic shaping options to enable b
bandwidth can be limited through {@link io.vertx.core.net.TrafficShapingOptions}. For NetServer, traffic shaping options can be set
through {@link io.vertx.core.net.NetServerOptions} and for HttpServer it can be set through {@link io.vertx.core.http.HttpServerOptions}.
+[source,$lang]
+----
{@link examples.NetExamples#configureTrafficShapingForNetServer}
+----
+[source,$lang]
+----
{@link examples.NetExamples#configureTrafficShapingForHttpServer}
+----
+
+These traffic shaping options can also be dynamically updated after server start.
+
+[source,$lang]
+----
+{@link examples.NetExamples#dynamicallyUpdateTrafficShapingForNetServer}
+----
+
+[source,$lang]
+----
+{@link examples.NetExamples#dynamicallyUpdateTrafficShapingForHttpServer}
+----
[[ssl]]
=== Configuring servers and clients to work with SSL/TLS
@@ -377,7 +397,7 @@ 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.
+SSL/TLS servers usually provide certificates to clients in order to verify their identity to clients.
Certificates/keys can be configured for servers in several ways:
@@ -640,7 +660,11 @@ implement certificate rotation).
{@link examples.NetExamples#updateSSLOptions}
----
-When the update succeeds the new SSL configuration is used, otherwise the previous configuration is kept.
+When the update succeeds the new SSL configuration is used, otherwise the previous configuration is preserved.
+
+NOTE: The options object is compared (using `equals`) against the existing options to prevent an update when the objects
+are equals since loading options can be costly. When object are equals, you can use the `force` parameter to force
+the update.
==== Self-signed certificates for testing and development purposes
@@ -809,13 +833,13 @@ Java TLS supports ALPN (Java 8 with the most recent versions).
OpenSSL also supports (native) ALPN.
-OpenSSL requires to configure {@link io.vertx.core.net.TCPSSLOptions#setOpenSslEngineOptions(OpenSSLEngineOptions)}
+OpenSSL requires to configure {@link io.vertx.core.net.TCPSSLOptions#setSslEngineOptions(SSLEngineOptions)}
and use http://netty.io/wiki/forked-tomcat-native.html[netty-tcnative] jar on the classpath. Using tcnative may require
OpenSSL to be installed on your OS depending on the tcnative implementation.
=== Using a proxy for client connections
-The {@link io.vertx.core.net.NetClient} supports either a HTTP/1.x _CONNECT_, _SOCKS4a_ or _SOCKS5_ proxy.
+The {@link io.vertx.core.net.NetClient} supports either an HTTP/1.x _CONNECT_, _SOCKS4a_ or _SOCKS5_ proxy.
The proxy can be configured in the {@link io.vertx.core.net.NetClientOptions} by setting a
{@link io.vertx.core.net.ProxyOptions} object containing proxy type, hostname, port and optionally username and password.
diff --git a/src/main/asciidoc/override/buffer_from_bytes.adoc b/src/main/asciidoc/override/buffer_from_bytes.adoc
deleted file mode 100644
index 3f013f5da54..00000000000
--- a/src/main/asciidoc/override/buffer_from_bytes.adoc
+++ /dev/null
@@ -1,6 +0,0 @@
-Create a buffer from a byte[]
-
-[source,java]
-----
-{@link docoverride.buffer.Examples#example4}
-----
diff --git a/src/main/asciidoc/override/configuring-eventbus.adoc b/src/main/asciidoc/override/configuring-eventbus.adoc
deleted file mode 100644
index 64a7d15fe31..00000000000
--- a/src/main/asciidoc/override/configuring-eventbus.adoc
+++ /dev/null
@@ -1,24 +0,0 @@
-The event bus can be configured. It is particularly useful when the event bus is clustered.
-Under the hood the event bus uses TCP connections to send and receive messages, so the {@link io.vertx.core.eventbus.EventBusOptions} let you configure all aspects of these TCP connections.
-As the event bus acts as a server and client, the configuration is close to {@link io.vertx.core.net.NetClientOptions} and {@link io.vertx.core.net.NetServerOptions}.
-
-[source,$lang]
-----
-{@link examples.EventBusExamples#example13}
-----
-
-The previous snippet depicts how you can use SSL connections for the event bus, instead of plain TCP connections.
-
-**WARNING**: to enforce the security in clustered mode, you **must** configure the cluster manager to use encryption or enforce security.
-Refer to the documentation of the cluster manager for further details.
-
-The event bus configuration needs to be consistent in all the cluster nodes.
-
-The {@link io.vertx.core.eventbus.EventBusOptions} also lets you specify whether or not the event bus is clustered, the port and host.
-
-When used in containers, you can also configure the public host and port:
-
-[source,$lang]
-----
-{@link examples.EventBusExamples#example14}
-----
diff --git a/src/main/asciidoc/override/configuring-native.adoc b/src/main/asciidoc/override/configuring-native.adoc
deleted file mode 100644
index aabbb4e31e8..00000000000
--- a/src/main/asciidoc/override/configuring-native.adoc
+++ /dev/null
@@ -1,7 +0,0 @@
-[source,$lang]
-----
-{@link examples.CoreExamples#configureNative()}
-----
-
-NOTE: preferring native transport will not prevent the application to execute (for example if a JAR is missing).
-If your application requires native transport, you need to check {@link io.vertx.core.Vertx#isNativeTransportEnabled()}.
diff --git a/src/main/asciidoc/override/dependencies.adoc b/src/main/asciidoc/override/dependencies.adoc
deleted file mode 100644
index 554efdcfc4b..00000000000
--- a/src/main/asciidoc/override/dependencies.adoc
+++ /dev/null
@@ -1,22 +0,0 @@
-If you are using Maven or Gradle, add the following dependency to the _dependencies_ section of your
-project descriptor to access the Vert.x Core API:
-
-* Maven (in your `pom.xml`):
-
-[source,xml,subs="+attributes"]
-----
-
- io.vertx
- vertx-core
- ${maven.version}
-
-----
-
-* Gradle (in your `build.gradle` file):
-
-[source,groovy,subs="+attributes"]
-----
-dependencies {
- compile 'io.vertx:vertx-core:${maven.version}'
-}
-----
diff --git a/src/main/asciidoc/override/dns.adoc b/src/main/asciidoc/override/dns.adoc
deleted file mode 100644
index b92b15a9773..00000000000
--- a/src/main/asciidoc/override/dns.adoc
+++ /dev/null
@@ -1,32 +0,0 @@
-=== Error handling
-
-As you saw in previous sections the DnsClient allows you to pass in a Handler which will be notified with an
-AsyncResult once the query was complete. In case of an error it will be notified with a DnsException which will
-hole a {@link io.vertx.core.dns.DnsResponseCode} that indicate why the resolution failed. This DnsResponseCode
-can be used to inspect the cause in more detail.
-
-Possible DnsResponseCodes are:
-
-- {@link io.vertx.core.dns.DnsResponseCode#NOERROR} No record was found for a given query
-- {@link io.vertx.core.dns.DnsResponseCode#FORMERROR} Format error
-- {@link io.vertx.core.dns.DnsResponseCode#SERVFAIL} Server failure
-- {@link io.vertx.core.dns.DnsResponseCode#NXDOMAIN} Name error
-- {@link io.vertx.core.dns.DnsResponseCode#NOTIMPL} Not implemented by DNS Server
-- {@link io.vertx.core.dns.DnsResponseCode#REFUSED} DNS Server refused the query
-- {@link io.vertx.core.dns.DnsResponseCode#YXDOMAIN} Domain name should not exist
-- {@link io.vertx.core.dns.DnsResponseCode#YXRRSET} Resource record should not exist
-- {@link io.vertx.core.dns.DnsResponseCode#NXRRSET} RRSET does not exist
-- {@link io.vertx.core.dns.DnsResponseCode#NOTZONE} Name not in zone
-- {@link io.vertx.core.dns.DnsResponseCode#BADVERS} Bad extension mechanism for version
-- {@link io.vertx.core.dns.DnsResponseCode#BADSIG} Bad signature
-- {@link io.vertx.core.dns.DnsResponseCode#BADKEY} Bad key
-- {@link io.vertx.core.dns.DnsResponseCode#BADTIME} Bad timestamp
-
-All of those errors are "generated" by the DNS Server itself.
-
-You can obtain the DnsResponseCode from the DnsException like:
-
-[source,java]
-----
-{@link docoverride.dns.Examples#example16}
-----
diff --git a/src/main/asciidoc/override/eventbus.adoc b/src/main/asciidoc/override/eventbus.adoc
deleted file mode 100644
index c71819b873a..00000000000
--- a/src/main/asciidoc/override/eventbus.adoc
+++ /dev/null
@@ -1,41 +0,0 @@
-==== Message Codecs
-
-You can send any object you like across the event bus if you define and register a {@link io.vertx.core.eventbus.MessageCodec message codec} for it.
-
-Message codecs have a name and you specify that name in the {@link io.vertx.core.eventbus.DeliveryOptions}
-when sending or publishing the message:
-
-[source,java]
-----
-{@link docoverride.eventbus.Examples#example10}
-----
-
-If you always want the same codec to be used for a particular type then you can register a default codec for it, then
-you don't have to specify the codec on each send in the delivery options:
-
-[source,java]
-----
-{@link docoverride.eventbus.Examples#example11}
-----
-
-You unregister a message codec with {@link io.vertx.core.eventbus.EventBus#unregisterCodec}.
-
-Message codecs don't always have to encode and decode as the same type. For example you can write a codec that
-allows a MyPOJO class to be sent, but when that message is sent to a handler it arrives as a MyOtherPOJO class.
-
-Vert.x has built-in codecs for certain data types:
-
-- basic types (string, byte array, byte, int, long, double, boolean, short, char), or
-- some Vert.x data types (buffers, JSON array, JSON objects), or
-- types implementing the {@link io.vertx.core.shareddata.ClusterSerializable} interface, or
-- types implementing the `java.io.Serializable` interface.
-
-[IMPORTANT]
-====
-In clustered mode, {@link io.vertx.core.shareddata.ClusterSerializable} and `java.io.Serializable` objects are rejected by default, for security reasons.
-
-You can define which classes are allowed for encoding and decoding by providing functions which inspect the name of the class:
-
-- {@link io.vertx.core.eventbus.EventBus#clusterSerializableChecker EventBus.clusterSerializableChecker()}, and
-- {@link io.vertx.core.eventbus.EventBus#serializableChecker EventBus.serializableChecker()}.
-====
diff --git a/src/main/asciidoc/override/eventbus_headers.adoc b/src/main/asciidoc/override/eventbus_headers.adoc
deleted file mode 100644
index ec01fe30783..00000000000
--- a/src/main/asciidoc/override/eventbus_headers.adoc
+++ /dev/null
@@ -1,9 +0,0 @@
-==== Setting headers on messages
-
-Messages sent over the event bus can also contain headers. This can be specified by providing a
-{@link io.vertx.core.eventbus.DeliveryOptions} when sending or publishing:
-
-[source,$lang]
-----
-{@link docoverride.eventbus.Examples#headers(io.vertx.core.eventbus.EventBus)}
-----
diff --git a/src/main/asciidoc/override/hostname-resolution.adoc b/src/main/asciidoc/override/hostname-resolution.adoc
deleted file mode 100644
index e5a53ca2f81..00000000000
--- a/src/main/asciidoc/override/hostname-resolution.adoc
+++ /dev/null
@@ -1,125 +0,0 @@
-== Host name resolution
-
-Vert.x uses an an address resolver for resolving host name into IP addresses instead of
-the JVM built-in blocking resolver.
-
-An host name resolves to an IP address using:
-
-- the _hosts_ file of the operating system
-- otherwise DNS queries against a list of servers
-
-By default it will use the list of the system DNS server addresses from the environment, if that list cannot be
-retrieved it will use Google's public DNS servers `"8.8.8.8"` and `"8.8.4.4"`.
-
-DNS servers can be also configured when creating a {@link io.vertx.core.Vertx} instance:
-
-[source,$lang]
-----
-{@link examples.CoreExamples#configureDNSServers}
-----
-
-The default port of a DNS server is `53`, when a server uses a different port, this port can be set
-using a colon delimiter: `192.168.0.2:40000`.
-
-NOTE: sometimes it can be desirable to use the JVM built-in resolver, the JVM system property
-_-Dvertx.disableDnsResolver=true_ activates this behavior
-
-=== Failover
-
-When a server does not reply in a timely manner, the resolver will try the next one from the list, the search
-is limited by {@link io.vertx.core.dns.AddressResolverOptions#setMaxQueries(int)} (the default value is `4` queries).
-
-A DNS query is considered as failed when the resolver has not received a correct answer within
-{@link io.vertx.core.dns.AddressResolverOptions#getQueryTimeout()} milliseconds (the default value is `5` seconds).
-
-=== Server list rotation
-
-By default the dns server selection uses the first one, the remaining servers are used for failover.
-
-You can configure {@link io.vertx.core.dns.AddressResolverOptions#setRotateServers(boolean)} to `true` to let
-the resolver perform a round-robin selection instead. It spreads the query load among the servers and avoids
-all lookup to hit the first server of the list.
-
-Failover still applies and will use the next server in the list.
-
-=== Hosts mapping
-
-The _hosts_ file of the operating system is used to perform an hostname lookup for an ipaddress.
-
-An alternative _hosts_ file can be used instead:
-
-[source,$lang]
-----
-{@link examples.CoreExamples#configureHosts}
-----
-
-=== Search domains
-
-By default the resolver will use the system DNS search domains from the environment. Alternatively an explicit search domain
-list can be provided:
-
-[source,$lang]
-----
-{@link examples.CoreExamples#configureSearchDomains()}
-----
-
-When a search domain list is used, the threshold for the number of dots is `1` or loaded from `/etc/resolv.conf`
-on Linux, it can be configured to a specific value with {@link io.vertx.core.dns.AddressResolverOptions#setNdots(int)}.
-
-=== MacOS configuration
-
-MacOS has a specific native extension to get the name server configuration of the system based on
-Apple's open source mDNSResponder. When this extension is not present,
-Netty logs the following warning.
-
-----
-[main] WARN io.netty.resolver.dns.DnsServerAddressStreamProviders - Can not find io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider in the classpath, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS.
-----
-
-This extension is not required as its absence does not prevent Vert.x to execute, yet is *recommended*.
-
-You can use add it to your classpath to improve the integration and remove the warning.
-
-.Intel-based Mac
-[source,xml]
-----
-
- mac-intel
-
-
- mac
- x86_64
-
-
-
-
- io.netty
- netty-resolver-dns-native-macos
- osx-x86_64
-
-
-
-
-----
-
-.M1/M2 Mac
-[source,xml]
-----
-
- mac-silicon
-
-
- mac
- aarch64
-
-
-
-
- io.netty
- netty-resolver-dns-native-macos
- osx-aarch_64
-
-
-
-
-----
diff --git a/src/main/asciidoc/override/in-the-beginning.adoc b/src/main/asciidoc/override/in-the-beginning.adoc
deleted file mode 100644
index e4f50f943dc..00000000000
--- a/src/main/asciidoc/override/in-the-beginning.adoc
+++ /dev/null
@@ -1,37 +0,0 @@
-== In the beginning there was Vert.x
-
-You can't do much in Vert.x-land unless you can communicate with a {@link io.vertx.core.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:
-
-[source,$lang]
-----
-{@link examples.CoreExamples#example1}
-----
-
-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 Vert.x object you can also specify options if the defaults aren't right for you:
-
-[source,$lang]
-----
-{@link examples.CoreExamples#example2}
-----
-
-The {@link io.vertx.core.VertxOptions} object has many settings and allows you to configure things like clustering, high availability, pool sizes and various other settings.
-
-=== Creating a clustered Vert.x object
-
-If you're creating a *clustered Vert.x* (See the section on the <> 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.
diff --git a/src/main/asciidoc/override/verticle-configuration.adoc b/src/main/asciidoc/override/verticle-configuration.adoc
deleted file mode 100644
index 99a52bf7ff9..00000000000
--- a/src/main/asciidoc/override/verticle-configuration.adoc
+++ /dev/null
@@ -1,26 +0,0 @@
-=== Passing configuration to a verticle
-
-Configuration in the form of JSON can be passed to a verticle at deployment time:
-
-[source,$lang]
-----
-{@link examples.CoreExamples#example13}
-----
-
-This configuration is then available via the {@link io.vertx.core.Context} object or directly using the
-{@link io.vertx.core.AbstractVerticle#config()} method. The configuration is returned as a JSON object so you
-can retrieve data as follows:
-
-[source,$lang]
-----
-{@link examples.ConfigurableVerticleExamples#start()}
-----
-
-=== Accessing environment variables in a Verticle
-
-Environment variables and system properties are accessible using the Java API:
-
-[source,$lang]
-----
-{@link examples.CoreExamples#systemAndEnvProperties()}
-----
diff --git a/src/main/asciidoc/override/verticles.adoc b/src/main/asciidoc/override/verticles.adoc
deleted file mode 100644
index 53faeb1ca51..00000000000
--- a/src/main/asciidoc/override/verticles.adoc
+++ /dev/null
@@ -1,87 +0,0 @@
-=== Writing Verticles
-
-Verticle classes must implement the {@link io.vertx.core.Verticle} interface.
-
-They can implement it directly if you like but usually it's simpler to extend
-the abstract class {@link io.vertx.core.AbstractVerticle}.
-
-Here's an example verticle:
-
-----
-public class MyVerticle extends AbstractVerticle {
-
- // Called when verticle is deployed
- public void start() {
- }
-
- // Optional - called when verticle is undeployed
- public void stop() {
- }
-
-}
-----
-
-Normally you would override the start method like in the example above.
-
-When Vert.x deploys the verticle it will call the start method, and when the method has completed the verticle will
-be considered started.
-
-You can also optionally override the stop method. This will be called by Vert.x when the verticle is undeployed and when
-the method has completed the verticle will be considered stopped.
-
-=== 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 start an HTTP server in the start method and
-propagate the asynchronous result of the server `listen` method.
-
-You can't block waiting for the HTTP server to bind in your start method as that would break the <>.
-
-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.
-
-Some time later, after you've done everything you need to do (e.g. start the HTTP server), you can call complete
-on the Future (or fail) to signal that you're done.
-
-Here's an example:
-
-----
-public class MyVerticle extends AbstractVerticle {
-
- private HttpServer server;
-
- @Override
- public void start(Promise startPromise) {
- server = vertx.createHttpServer().requestHandler(req -> {
- req.response()
- .putHeader("content-type", "text/plain")
- .end("Hello from Vert.x!");
- });
-
- // Now bind the server:
- server.listen(8080)
- .mapEmpty()
- .onComplete(startPromise);
- }
-}
-----
-
-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.
-
-----
-public class MyVerticle extends AbstractVerticle {
-
- @Override
- public void stop(Promise stopPromise) {
- doSomethingThatTakesTime()
- .mapEmpty()
- .onComplete(stopPromise);
- }
-}
-----
-
-INFO: You don't need to manually stop the HTTP server started by a verticle, in the verticle's stop method. Vert.x
-will automatically stop any running server when the verticle is undeployed.
diff --git a/src/main/asciidoc/shareddata.adoc b/src/main/asciidoc/shareddata.adoc
index bc2b1cc4eda..e2fcbd5d69e 100644
--- a/src/main/asciidoc/shareddata.adoc
+++ b/src/main/asciidoc/shareddata.adoc
@@ -143,6 +143,16 @@ If your application doesn't need the lock to be shared with every other node, yo
{@link examples.SharedDataExamples#localLock}
----
+Sometimes, you use the lock API to retrieve an asynchronous result and apply the acquire/release pattern around the asynchronous call. Vert.x provides a simplified lock API to simplify this pattern.
+
+[source,$lang]
+----
+{@link examples.SharedDataExamples#withLock}
+----
+
+The lock is acquired before calling the supplier and released when the future returned by the supplier
+completes.
+
=== Asynchronous counters
It's often useful to maintain an atomic counter locally or across the different nodes of your application.
diff --git a/src/main/asciidoc/streams.adoc b/src/main/asciidoc/streams.adoc
index 6df8fc8c379..94aac890d71 100644
--- a/src/main/asciidoc/streams.adoc
+++ b/src/main/asciidoc/streams.adoc
@@ -119,7 +119,7 @@ Let's now look at the methods on `ReadStream` and `WriteStream` in more detail:
`ReadStream` is implemented by {@link io.vertx.core.http.HttpClientResponse}, {@link io.vertx.core.datagram.DatagramSocket},
{@link io.vertx.core.http.HttpClientRequest}, {@link io.vertx.core.http.HttpServerFileUpload},
{@link io.vertx.core.http.HttpServerRequest}, {@link io.vertx.core.eventbus.MessageConsumer},
-{@link io.vertx.core.net.NetSocket}, {@link io.vertx.core.http.WebSocket}, {@link io.vertx.core.file.AsyncFile}.
+{@link io.vertx.core.net.NetSocket}, {@link io.vertx.core.http.WebSocket} and {@link io.vertx.core.file.AsyncFile}.
- {@link io.vertx.core.streams.ReadStream#handler}:
set a handler which will receive items from the ReadStream.
diff --git a/src/main/asciidoc/virtualthreads.adoc b/src/main/asciidoc/virtualthreads.adoc
new file mode 100644
index 00000000000..a5a07137ed7
--- /dev/null
+++ b/src/main/asciidoc/virtualthreads.adoc
@@ -0,0 +1,100 @@
+== Vert.x Virtual Threads
+
+Use virtual threads to write Vert.x code that looks like it is synchronous.
+
+You still write the traditional Vert.x code processing events, but you have the opportunity to write synchronous code for complex workflows and use thread locals in such workflows.
+
+=== Introduction
+
+The non-blocking nature of Vert.x leads to asynchronous APIs.
+Asynchronous APIs can take various forms including callback style, promises and reactive extensions.
+
+In some cases, programming using asynchronous APIs can be more challenging than using a direct synchronous style, in particular if you have several operations that you want to do sequentially.
+Also, error propagation is often more complex when using asynchronous APIs.
+
+Virtual thread support allows you to work with asynchronous APIs, but using a direct synchronous style that you're already familiar with.
+
+It does this by using Java 21 https://openjdk.org/jeps/444[virtual threads]. Virtual threads are very lightweight threads that do not correspond to underlying kernel threads. When they are blocked they do not block a kernel thread.
+
+=== Using virtual threads
+
+You can deploy virtual thread verticles.
+
+A virtual thread verticle is capable of awaiting Vert.x futures and gets the result synchronously.
+
+When the verticle *awaits* a result, the verticle can still process events like an event-loop verticle.
+
+[source,java]
+----
+{@link examples.VirtualThreadExamples#gettingStarted}
+----
+
+NOTE: Using virtual threads requires Java 21 or above.
+
+==== Blocking within a virtual thread verticle
+
+You can use {@link io.vertx.core.Future#await} to suspend the current virtual thread until the awaited result is available.
+
+The virtual thread is effectively blocked, but the application can still process events.
+
+When a virtual thread awaits for a result and the verticle needs to process a task, a new virtual thread is created to handle this task.
+
+When the result is available, the virtual thread execution is resumed and scheduled after the current task is suspended or finished.
+
+IMPORTANT: Like any verticle at most one task is executed at the same time.
+
+You can await on a Vert.x `Future`
+
+[source,java]
+----
+{@link examples.VirtualThreadExamples#awaitingFutures1}
+----
+
+or on a JDK `CompletionStage`
+
+[source,java]
+----
+{@link examples.VirtualThreadExamples#awaitingFutures2}
+----
+
+==== Field visibility
+
+A virtual thread verticle can interact safely with fields before an `await` call. However, if you are reading a field before an `await` call and reusing the value after the call, you should keep in mind that this value might have changed.
+
+[source,java]
+----
+{@link examples.VirtualThreadExamples#fieldVisibility1}
+----
+
+You should read/write fields before calling `await` to avoid this.
+
+[source,java]
+----
+{@link examples.VirtualThreadExamples#fieldVisibility2}
+----
+
+NOTE: this is the same behavior with an event-loop verticle
+
+==== Awaiting multiple futures
+
+When you need to await multiple futures, you can use Vert.x {@link io.vertx.core.CompositeFuture}:
+
+[source,java]
+----
+{@link examples.VirtualThreadExamples#awaitingMultipleFutures}
+----
+
+==== Blocking without await
+
+When your application blocks without using `await`, e.g. using `ReentrantLock#lock`, the Vert.x scheduler is not aware of it and cannot schedule events on the verticle: it behaves like a worker verticle, yet using virtual threads.
+
+This use case is not encouraged yet not forbidden, however the verticle should be deployed with several instances to deliver the desired concurrency, like a worker verticle.
+
+==== Thread local support
+
+Thread locals are only reliable within the execution of a context task.
+
+[source,java]
+----
+{@link examples.VirtualThreadExamples#threadLocalSupport1}
+----
diff --git a/src/main/generated/io/vertx/core/DeploymentOptionsConverter.java b/src/main/generated/io/vertx/core/DeploymentOptionsConverter.java
index 092b745f2c0..1605bbce4ba 100644
--- a/src/main/generated/io/vertx/core/DeploymentOptionsConverter.java
+++ b/src/main/generated/io/vertx/core/DeploymentOptionsConverter.java
@@ -25,6 +25,11 @@ static void fromJson(Iterable> json, Deploym
obj.setConfig(((JsonObject)member.getValue()).copy());
}
break;
+ case "threadingModel":
+ if (member.getValue() instanceof String) {
+ obj.setThreadingModel(io.vertx.core.ThreadingModel.valueOf((String)member.getValue()));
+ }
+ break;
case "ha":
if (member.getValue() instanceof Boolean) {
obj.setHa((Boolean)member.getValue());
@@ -35,21 +40,6 @@ static void fromJson(Iterable> json, Deploym
obj.setInstances(((Number)member.getValue()).intValue());
}
break;
- case "maxWorkerExecuteTime":
- if (member.getValue() instanceof Number) {
- obj.setMaxWorkerExecuteTime(((Number)member.getValue()).longValue());
- }
- break;
- case "maxWorkerExecuteTimeUnit":
- if (member.getValue() instanceof String) {
- obj.setMaxWorkerExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
- }
- break;
- case "worker":
- if (member.getValue() instanceof Boolean) {
- obj.setWorker((Boolean)member.getValue());
- }
- break;
case "workerPoolName":
if (member.getValue() instanceof String) {
obj.setWorkerPoolName((String)member.getValue());
@@ -60,6 +50,16 @@ static void fromJson(Iterable> json, Deploym
obj.setWorkerPoolSize(((Number)member.getValue()).intValue());
}
break;
+ case "maxWorkerExecuteTime":
+ if (member.getValue() instanceof Number) {
+ obj.setMaxWorkerExecuteTime(((Number)member.getValue()).longValue());
+ }
+ break;
+ case "maxWorkerExecuteTimeUnit":
+ if (member.getValue() instanceof String) {
+ obj.setMaxWorkerExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+ }
+ break;
}
}
}
@@ -72,16 +72,18 @@ static void toJson(DeploymentOptions obj, java.util.Map json) {
if (obj.getConfig() != null) {
json.put("config", obj.getConfig());
}
+ if (obj.getThreadingModel() != null) {
+ json.put("threadingModel", obj.getThreadingModel().name());
+ }
json.put("ha", obj.isHa());
json.put("instances", obj.getInstances());
- json.put("maxWorkerExecuteTime", obj.getMaxWorkerExecuteTime());
- if (obj.getMaxWorkerExecuteTimeUnit() != null) {
- json.put("maxWorkerExecuteTimeUnit", obj.getMaxWorkerExecuteTimeUnit().name());
- }
- json.put("worker", obj.isWorker());
if (obj.getWorkerPoolName() != null) {
json.put("workerPoolName", obj.getWorkerPoolName());
}
json.put("workerPoolSize", obj.getWorkerPoolSize());
+ json.put("maxWorkerExecuteTime", obj.getMaxWorkerExecuteTime());
+ if (obj.getMaxWorkerExecuteTimeUnit() != null) {
+ json.put("maxWorkerExecuteTimeUnit", obj.getMaxWorkerExecuteTimeUnit().name());
+ }
}
}
diff --git a/src/main/generated/io/vertx/core/VertxOptionsConverter.java b/src/main/generated/io/vertx/core/VertxOptionsConverter.java
index 07d0abf6620..d05361e5a8f 100644
--- a/src/main/generated/io/vertx/core/VertxOptionsConverter.java
+++ b/src/main/generated/io/vertx/core/VertxOptionsConverter.java
@@ -20,39 +20,34 @@ public class VertxOptionsConverter {
static void fromJson(Iterable> json, VertxOptions obj) {
for (java.util.Map.Entry member : json) {
switch (member.getKey()) {
- case "addressResolverOptions":
- if (member.getValue() instanceof JsonObject) {
- obj.setAddressResolverOptions(new io.vertx.core.dns.AddressResolverOptions((io.vertx.core.json.JsonObject)member.getValue()));
- }
- break;
- case "blockedThreadCheckInterval":
+ case "eventLoopPoolSize":
if (member.getValue() instanceof Number) {
- obj.setBlockedThreadCheckInterval(((Number)member.getValue()).longValue());
+ obj.setEventLoopPoolSize(((Number)member.getValue()).intValue());
}
break;
- case "blockedThreadCheckIntervalUnit":
- if (member.getValue() instanceof String) {
- obj.setBlockedThreadCheckIntervalUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+ case "workerPoolSize":
+ if (member.getValue() instanceof Number) {
+ obj.setWorkerPoolSize(((Number)member.getValue()).intValue());
}
break;
- case "disableTCCL":
- if (member.getValue() instanceof Boolean) {
- obj.setDisableTCCL((Boolean)member.getValue());
+ case "blockedThreadCheckInterval":
+ if (member.getValue() instanceof Number) {
+ obj.setBlockedThreadCheckInterval(((Number)member.getValue()).longValue());
}
break;
- case "eventBusOptions":
- if (member.getValue() instanceof JsonObject) {
- obj.setEventBusOptions(new io.vertx.core.eventbus.EventBusOptions((io.vertx.core.json.JsonObject)member.getValue()));
+ case "maxEventLoopExecuteTime":
+ if (member.getValue() instanceof Number) {
+ obj.setMaxEventLoopExecuteTime(((Number)member.getValue()).longValue());
}
break;
- case "eventLoopPoolSize":
+ case "maxWorkerExecuteTime":
if (member.getValue() instanceof Number) {
- obj.setEventLoopPoolSize(((Number)member.getValue()).intValue());
+ obj.setMaxWorkerExecuteTime(((Number)member.getValue()).longValue());
}
break;
- case "fileSystemOptions":
- if (member.getValue() instanceof JsonObject) {
- obj.setFileSystemOptions(new io.vertx.core.file.FileSystemOptions((io.vertx.core.json.JsonObject)member.getValue()));
+ case "internalBlockingPoolSize":
+ if (member.getValue() instanceof Number) {
+ obj.setInternalBlockingPoolSize(((Number)member.getValue()).intValue());
}
break;
case "haEnabled":
@@ -60,39 +55,39 @@ static void fromJson(Iterable> json, VertxOp
obj.setHAEnabled((Boolean)member.getValue());
}
break;
+ case "quorumSize":
+ if (member.getValue() instanceof Number) {
+ obj.setQuorumSize(((Number)member.getValue()).intValue());
+ }
+ break;
case "haGroup":
if (member.getValue() instanceof String) {
obj.setHAGroup((String)member.getValue());
}
break;
- case "internalBlockingPoolSize":
- if (member.getValue() instanceof Number) {
- obj.setInternalBlockingPoolSize(((Number)member.getValue()).intValue());
- }
- break;
- case "maxEventLoopExecuteTime":
- if (member.getValue() instanceof Number) {
- obj.setMaxEventLoopExecuteTime(((Number)member.getValue()).longValue());
+ case "metricsOptions":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setMetricsOptions(new io.vertx.core.metrics.MetricsOptions((io.vertx.core.json.JsonObject)member.getValue()));
}
break;
- case "maxEventLoopExecuteTimeUnit":
- if (member.getValue() instanceof String) {
- obj.setMaxEventLoopExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+ case "fileSystemOptions":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setFileSystemOptions(new io.vertx.core.file.FileSystemOptions((io.vertx.core.json.JsonObject)member.getValue()));
}
break;
- case "maxWorkerExecuteTime":
+ case "warningExceptionTime":
if (member.getValue() instanceof Number) {
- obj.setMaxWorkerExecuteTime(((Number)member.getValue()).longValue());
+ obj.setWarningExceptionTime(((Number)member.getValue()).longValue());
}
break;
- case "maxWorkerExecuteTimeUnit":
- if (member.getValue() instanceof String) {
- obj.setMaxWorkerExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+ case "eventBusOptions":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setEventBusOptions(new io.vertx.core.eventbus.EventBusOptions((io.vertx.core.json.JsonObject)member.getValue()));
}
break;
- case "metricsOptions":
+ case "addressResolverOptions":
if (member.getValue() instanceof JsonObject) {
- obj.setMetricsOptions(new io.vertx.core.metrics.MetricsOptions((io.vertx.core.json.JsonObject)member.getValue()));
+ obj.setAddressResolverOptions(new io.vertx.core.dns.AddressResolverOptions((io.vertx.core.json.JsonObject)member.getValue()));
}
break;
case "preferNativeTransport":
@@ -100,34 +95,39 @@ static void fromJson(Iterable> json, VertxOp
obj.setPreferNativeTransport((Boolean)member.getValue());
}
break;
- case "quorumSize":
- if (member.getValue() instanceof Number) {
- obj.setQuorumSize(((Number)member.getValue()).intValue());
+ case "maxEventLoopExecuteTimeUnit":
+ if (member.getValue() instanceof String) {
+ obj.setMaxEventLoopExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
}
break;
- case "tracingOptions":
- if (member.getValue() instanceof JsonObject) {
- obj.setTracingOptions(new io.vertx.core.tracing.TracingOptions((io.vertx.core.json.JsonObject)member.getValue()));
+ case "maxWorkerExecuteTimeUnit":
+ if (member.getValue() instanceof String) {
+ obj.setMaxWorkerExecuteTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
}
break;
- case "useDaemonThread":
- if (member.getValue() instanceof Boolean) {
- obj.setUseDaemonThread((Boolean)member.getValue());
+ case "warningExceptionTimeUnit":
+ if (member.getValue() instanceof String) {
+ obj.setWarningExceptionTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
}
break;
- case "warningExceptionTime":
- if (member.getValue() instanceof Number) {
- obj.setWarningExceptionTime(((Number)member.getValue()).longValue());
+ case "blockedThreadCheckIntervalUnit":
+ if (member.getValue() instanceof String) {
+ obj.setBlockedThreadCheckIntervalUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
}
break;
- case "warningExceptionTimeUnit":
- if (member.getValue() instanceof String) {
- obj.setWarningExceptionTimeUnit(java.util.concurrent.TimeUnit.valueOf((String)member.getValue()));
+ case "tracingOptions":
+ if (member.getValue() instanceof JsonObject) {
+ obj.setTracingOptions(new io.vertx.core.tracing.TracingOptions((io.vertx.core.json.JsonObject)member.getValue()));
}
break;
- case "workerPoolSize":
- if (member.getValue() instanceof Number) {
- obj.setWorkerPoolSize(((Number)member.getValue()).intValue());
+ case "disableTCCL":
+ if (member.getValue() instanceof Boolean) {
+ obj.setDisableTCCL((Boolean)member.getValue());
+ }
+ break;
+ case "useDaemonThread":
+ if (member.getValue() instanceof Boolean) {
+ obj.setUseDaemonThread((Boolean)member.getValue());
}
break;
}
@@ -139,49 +139,49 @@ static void toJson(VertxOptions obj, JsonObject json) {
}
static void toJson(VertxOptions obj, java.util.Map json) {
- if (obj.getAddressResolverOptions() != null) {
- json.put("addressResolverOptions", obj.getAddressResolverOptions().toJson());
- }
+ json.put("eventLoopPoolSize", obj.getEventLoopPoolSize());
+ json.put("workerPoolSize", obj.getWorkerPoolSize());
json.put("blockedThreadCheckInterval", obj.getBlockedThreadCheckInterval());
- if (obj.getBlockedThreadCheckIntervalUnit() != null) {
- json.put("blockedThreadCheckIntervalUnit", obj.getBlockedThreadCheckIntervalUnit().name());
+ json.put("maxEventLoopExecuteTime", obj.getMaxEventLoopExecuteTime());
+ json.put("maxWorkerExecuteTime", obj.getMaxWorkerExecuteTime());
+ json.put("internalBlockingPoolSize", obj.getInternalBlockingPoolSize());
+ json.put("haEnabled", obj.isHAEnabled());
+ json.put("quorumSize", obj.getQuorumSize());
+ if (obj.getHAGroup() != null) {
+ json.put("haGroup", obj.getHAGroup());
}
- json.put("disableTCCL", obj.getDisableTCCL());
- if (obj.getEventBusOptions() != null) {
- json.put("eventBusOptions", obj.getEventBusOptions().toJson());
+ if (obj.getMetricsOptions() != null) {
+ json.put("metricsOptions", obj.getMetricsOptions().toJson());
}
- json.put("eventLoopPoolSize", obj.getEventLoopPoolSize());
if (obj.getFileSystemOptions() != null) {
json.put("fileSystemOptions", obj.getFileSystemOptions().toJson());
}
- json.put("haEnabled", obj.isHAEnabled());
- if (obj.getHAGroup() != null) {
- json.put("haGroup", obj.getHAGroup());
+ json.put("warningExceptionTime", obj.getWarningExceptionTime());
+ if (obj.getEventBusOptions() != null) {
+ json.put("eventBusOptions", obj.getEventBusOptions().toJson());
}
- json.put("internalBlockingPoolSize", obj.getInternalBlockingPoolSize());
- json.put("maxEventLoopExecuteTime", obj.getMaxEventLoopExecuteTime());
+ if (obj.getAddressResolverOptions() != null) {
+ json.put("addressResolverOptions", obj.getAddressResolverOptions().toJson());
+ }
+ json.put("preferNativeTransport", obj.getPreferNativeTransport());
if (obj.getMaxEventLoopExecuteTimeUnit() != null) {
json.put("maxEventLoopExecuteTimeUnit", obj.getMaxEventLoopExecuteTimeUnit().name());
}
- json.put("maxWorkerExecuteTime", obj.getMaxWorkerExecuteTime());
if (obj.getMaxWorkerExecuteTimeUnit() != null) {
json.put("maxWorkerExecuteTimeUnit", obj.getMaxWorkerExecuteTimeUnit().name());
}
- if (obj.getMetricsOptions() != null) {
- json.put("metricsOptions", obj.getMetricsOptions().toJson());
+ if (obj.getWarningExceptionTimeUnit() != null) {
+ json.put("warningExceptionTimeUnit", obj.getWarningExceptionTimeUnit().name());
+ }
+ if (obj.getBlockedThreadCheckIntervalUnit() != null) {
+ json.put("blockedThreadCheckIntervalUnit", obj.getBlockedThreadCheckIntervalUnit().name());
}
- json.put("preferNativeTransport", obj.getPreferNativeTransport());
- json.put("quorumSize", obj.getQuorumSize());
if (obj.getTracingOptions() != null) {
json.put("tracingOptions", obj.getTracingOptions().toJson());
}
+ json.put("disableTCCL", obj.getDisableTCCL());
if (obj.getUseDaemonThread() != null) {
json.put("useDaemonThread", obj.getUseDaemonThread());
}
- json.put("warningExceptionTime", obj.getWarningExceptionTime());
- if (obj.getWarningExceptionTimeUnit() != null) {
- json.put("warningExceptionTimeUnit", obj.getWarningExceptionTimeUnit().name());
- }
- json.put("workerPoolSize", obj.getWorkerPoolSize());
}
}
diff --git a/src/main/generated/io/vertx/core/cli/ArgumentConverter.java b/src/main/generated/io/vertx/core/cli/ArgumentConverter.java
deleted file mode 100644
index 7ba919378a8..00000000000
--- a/src/main/generated/io/vertx/core/cli/ArgumentConverter.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.vertx.core.cli;
-
-import io.vertx.core.json.JsonObject;
-import io.vertx.core.json.JsonArray;
-import io.vertx.core.json.impl.JsonUtil;
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-import java.util.Base64;
-
-/**
- * Converter and mapper for {@link io.vertx.core.cli.Argument}.
- * NOTE: This class has been automatically generated from the {@link io.vertx.core.cli.Argument} original class using Vert.x codegen.
- */
-public class ArgumentConverter {
-
-
- private static final Base64.Decoder BASE64_DECODER = JsonUtil.BASE64_DECODER;
- private static final Base64.Encoder BASE64_ENCODER = JsonUtil.BASE64_ENCODER;
-
- static void fromJson(Iterable> json, Argument obj) {
- for (java.util.Map.Entry member : json) {
- switch (member.getKey()) {
- case "argName":
- if (member.getValue() instanceof String) {
- obj.setArgName((String)member.getValue());
- }
- break;
- case "defaultValue":
- if (member.getValue() instanceof String) {
- obj.setDefaultValue((String)member.getValue());
- }
- break;
- case "description":
- if (member.getValue() instanceof String) {
- obj.setDescription((String)member.getValue());
- }
- break;
- case "hidden":
- if (member.getValue() instanceof Boolean) {
- obj.setHidden((Boolean)member.getValue());
- }
- break;
- case "index":
- if (member.getValue() instanceof Number) {
- obj.setIndex(((Number)member.getValue()).intValue());
- }
- break;
- case "multiValued":
- if (member.getValue() instanceof Boolean) {
- obj.setMultiValued((Boolean)member.getValue());
- }
- break;
- case "required":
- if (member.getValue() instanceof Boolean) {
- obj.setRequired((Boolean)member.getValue());
- }
- break;
- }
- }
- }
-
- static void toJson(Argument obj, JsonObject json) {
- toJson(obj, json.getMap());
- }
-
- static void toJson(Argument obj, java.util.Map json) {
- if (obj.getArgName() != null) {
- json.put("argName", obj.getArgName());
- }
- if (obj.getDefaultValue() != null) {
- json.put("defaultValue", obj.getDefaultValue());
- }
- if (obj.getDescription() != null) {
- json.put("description", obj.getDescription());
- }
- json.put("hidden", obj.isHidden());
- json.put("index", obj.getIndex());
- json.put("multiValued", obj.isMultiValued());
- json.put("required", obj.isRequired());
- }
-}
diff --git a/src/main/generated/io/vertx/core/cli/OptionConverter.java b/src/main/generated/io/vertx/core/cli/OptionConverter.java
deleted file mode 100644
index ad97d29e9e1..00000000000
--- a/src/main/generated/io/vertx/core/cli/OptionConverter.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package io.vertx.core.cli;
-
-import io.vertx.core.json.JsonObject;
-import io.vertx.core.json.JsonArray;
-import io.vertx.core.json.impl.JsonUtil;
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-import java.util.Base64;
-
-/**
- * Converter and mapper for {@link io.vertx.core.cli.Option}.
- * NOTE: This class has been automatically generated from the {@link io.vertx.core.cli.Option} original class using Vert.x codegen.
- */
-public class OptionConverter {
-
-
- private static final Base64.Decoder BASE64_DECODER = JsonUtil.BASE64_DECODER;
- private static final Base64.Encoder BASE64_ENCODER = JsonUtil.BASE64_ENCODER;
-
- static void fromJson(Iterable> json, Option obj) {
- for (java.util.Map.Entry member : json) {
- switch (member.getKey()) {
- case "argName":
- if (member.getValue() instanceof String) {
- obj.setArgName((String)member.getValue());
- }
- break;
- case "choices":
- if (member.getValue() instanceof JsonArray) {
- java.util.LinkedHashSet list = new java.util.LinkedHashSet<>();
- ((Iterable