DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How are you handling the data revolution? We want your take on what's real, what's hype, and what's next in the world of data engineering.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • Advanced Error Handling in JavaScript
  • Mastering macOS Client-Server Application Testing: Tools and Key Differences
  • Enhancing Testing Efficiency: Transitioning From Traditional Code Coverage to Code Change Coverage
  • The Naming Nuance of Non-Functional Requirements

Trending

  • Exploring Data Redaction Enhancements in Oracle Database 23ai
  • The Scrum Guide Expansion Pack
  • A Complete Guide to Modern AI Developer Tools
  • Run Scalable Python Workloads With Modal
  1. DZone
  2. Coding
  3. Frameworks
  4. Introduction to Eclipse Vert.x - My First Vert.x Application

Introduction to Eclipse Vert.x - My First Vert.x Application

Eclipse Vert.x is a toolkit that let you write reactive applications. In Part 1 of this tutorial series, we'll learn how to make your first Vert.x application.

By 
Clement Escoffier user avatar
Clement Escoffier
·
Apr. 16, 18 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
12.8K Views

Join the DZone community and get the full member experience.

Join For Free

Let's say, you heard someone saying that Eclipse Vert.x is awesome. Ok great, but you may want to try it yourself. The next logical question is "where do I start?". This article is a good starting point. It shows: how to build a very simple Vert.x application (nothing fancy), how it is tested, and how it is packaged and executed. Basically everything you need to know before building your own groundbreaking application.

The code developed in this article is available on GitHub. This is part of the "Introduction to Vert.x Series." The code for this post is located in the repository in the post-1 directory.

Let's Start!

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

So, you would get something like:

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

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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>io.vertx.intro</groupId>
  <artifactId>my-first-app</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <vertx.version>3.5.0</vertx.version>
    <vmp.version>1.0.13</vmp.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-core</artifactId>
      <version>${vertx.version}</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>io.fabric8</groupId>
        <artifactId>vertx-maven-plugin</artifactId>
        <version>${vmp.version}</version>
        <executions>
          <execution>
            <id>vmp</id>
            <goals>
              <goal>initialize</goal>
              <goal>package</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <redeploy>true</redeploy>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

This pom.xml file is pretty straightforward:

  • It declares a dependency on the `vertx-core`, the Vert.x version is declared as a property.
  • It configures the `maven-compiler-plugin` to use Java 8.
  • It declares the `vertx-maven-plugin`; we will come back to this in a bit.

Vert.x requires at least Java 8, so don't try to run a Vert.x application on a Java 6 or 7 JVM; it won't work.

The vertx-maven-plugin is an optional plugin that packages your app and provides additional functionality (documentation is here). Otherwise, you can use the maven-shade-plugin or any other packaging plugin. The vertx-maven-plugin is convenient as it packages the application without any configuration. It also provides a redeploy feature, restarting the application when you update the code or the resources.

Let's Code!

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

package io.vertx.intro.first;

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

public class MyFirstVerticle extends AbstractVerticle {

    @Override
    public void start(Future<Void> fut) {
        vertx
            .createHttpServer()
            .requestHandler(r ->
                r.response()
                 .end("
<h1>Hello from my first Vert.x application</h1>

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

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

The start method is called when the verticle is deployed. We could also implement a stop method (called when the verticle is undeployed), but in this case, Vert.x takes care of the garbage for us. The start method receives a Future object that lets us notify Vert.x when our start sequence has been completed or reports an error if anything bad happens. One of the particularities of Vert.x is its asynchronous and non-blocking aspect. When our verticle is going to be deployed it won't wait until the start method has been completed. So, the Future parameter is important for notification of the completion. Notice that you can also implement a version of the start method without the Future parameter. In this case, Vert.x considers the verticle deployed when the start method returns.

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

Before trying the application, edit the pom.xml file and add the vertx.verticle entry in the properties:

<properties>
    <vertx.version>3.5.0</vertx.version>
    <vmp.version>1.0.13</vmp.version>
    <!-- line to add: -->
    <vertx.verticle>io.vertx.intro.first.MyFirstVerticle</vertx.verticle>
</properties>

This property instructs Vert.x to deploy this class when it starts.

Let's try to compile the application using:

mvn compile vertx:run

The application is started; open your browser to http://localhost:8080 and you should see the Hello message. If you change the message in the code and save the file, the application is restarted with the updated message.

Hit CTRL+C to stop the application.

That's all for the application.

Let's Test!

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

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

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-unit</artifactId>
  <version>${vertx.version}</version>
  <scope>test</scope>
</dependency>

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

package io.vertx.intro.first;

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

@RunWith(VertxUnitRunner.class)
public class MyFirstVerticleTest {

    private Vertx vertx;

    @Before
    public void setUp(TestContext context) {
        vertx = Vertx.vertx();
        vertx.deployVerticle(MyFirstVerticle.class.getName(),
            context.asyncAssertSuccess());
    }

    @After
    public void tearDown(TestContext context) {
        vertx.close(context.asyncAssertSuccess());
    }

    @Test
    public void testMyApplication(TestContext context) {
        final Async async = context.async();

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

This is a JUnit test case for our verticle. The test uses vertx-unit, so we configure a custom runner (with the @RunWith annotation). vertx-unit makes easy to test asynchronous interactions, which are the basis of Vert.x applications.

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

Well, the tearDown (called after each test) method is straightforward, and just closes the vertx instance we created.

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

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

Let's take a minute to mention the assertions. Unlike in traditional JUnit tests, it uses context.assert.... Indeed, if the assertion fails, it will interrupt the test immediately. So it's important to use these assertions because of the asynchronous aspect of the Vert.x application and tests. However, Vert.x Unit provides hooks to let you use Hamcrest or AssertJ, as demonstrated in this example and this other example.

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

mvn clean test

Packaging

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

To create a fat jar, just run:

mvn clean package

The vertx-maven-plugin is taking care of the packaging and creates the target/my-first-app-1.0-SNAPSHOT.jar file embedding our application along with all the dependencies (including Vert.x itself). Check the size: around 6MB; and this includes everything to run the application.

Executing Our Application

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

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

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

To stop the application, hit CTRL+C.

Conclusion

This Vert.x crash course has presented: how you can develop a simple application using Vert.x; how to test it, package it, and run it. So you now have a great start on the road to building an amazing system on top of Vert.x. Next time we will see how to configure our application.

Happy coding and stay tuned!

application Vert.x Testing Eclipse

Published at DZone with permission of Clement Escoffier, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Advanced Error Handling in JavaScript
  • Mastering macOS Client-Server Application Testing: Tools and Key Differences
  • Enhancing Testing Efficiency: Transitioning From Traditional Code Coverage to Code Change Coverage
  • The Naming Nuance of Non-Functional Requirements

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: