Scala is here

TL;DR:

  • Scala sup­port for Vert.x is here!
  • It is based on Scala 2.12, no sup­port for 2.11 planned
  • all Vert.x-​modules are avail­able in a Scala fla­vor
  • It’s awe­some
  • Get started here

Intro

The rise of Scala as one of the most im­por­tant lan­guages on the JVM caught many (me in­cluded) by sur­prise. This hy­brid of func­tional and im­per­a­tive par­a­digms struck a chord with many de­vel­op­ers. Thanks to Scala a lot of peo­ple who’d never have touched a lan­guage like Haskell got ex­posed to func­tional pro­gram­ming. This ex­po­sure was one of the dri­ving forces to get streams and lambda into the JVM.

With the re­lease of Vert.x 3.4.0 we fi­nally in­tro­duced Scala to the fam­ily of sup­ported lan­guages: vertx-​lang-scala.

In this post I will in­tro­duce the new stack and how the power of Scala can be used in your fa­vorite re­ac­tive toolkit.

Basics

vertx-​lang-scala is based on Scala 2.12. There are no plans to sup­port 2.11.

All mod­ules avail­able for Vert.x are sup­ported (you can check here ).

Future and Promise both need a ExecutionContext

Mod­ules use the fol­low­ing naming-​scheme: io.vertx:<name-​of-vertx-module>-​scala_2.12:<vertx-​major-version>. The Scala ver­sion of io.vertx:vert-​web:3.4.0 would be io.vertx:vertx-​web-scala_2.12:3.4.0.

There is an sbt-​based quickstart-​project avail­able that will be up­dated for each Vert.x-​release.

Please note: Al­though sbt is used in this quick­start it is by no means re­quired. There are no spe­cial plu­g­ins in­volved so vertx-​lang-scala can eas­ily be used with Gra­dle or Maven.

I use sbt as it is the de­fault build sys­tem used for Scala projects.

Quickstart

Let’s get started by cloning the quick­start:

git clone git@github.com:vert-x3/vertx-sbt-starter.git

You just got the fol­low­ing things:

  • An sbt project con­tain­ing de­pen­den­cies to Vert.x-​core and Vert.x-web
  • The abil­ity to cre­ate a fat-​jat via sbt assembly
  • The abil­ity to cre­ate a docker con­tainer via sbt docker
  • A few ex­am­ple ver­ti­cles
  • Unit test ex­am­ples
  • a pre-​configured Scala-​shell in­side sbt

We will now run the ap­pli­ca­tion to get some quick sat­is­fac­tion. Use sbt assembly to pro­duce the fat-​jar fol­lowed by java -jar target/scala-2.12/vertx-scala-sbt-assembly-0.1-SNAPSHOT.jar. Now point your browser to http://lo­cal­host:8666/hello for a clas­sic wel­come mes­sage.

The details

Open your IDE so we can take a look at what’s going on under the hood. We start with the HttpVer­ti­cle.

package io.vertx.scala.sbt

import io.vertx.lang.scala.ScalaVerticle
import io.vertx.scala.ext.web.Router

import scala.concurrent.Future

class HttpVerticle extends ScalaVerticle { // <1>


  override def startFuture(): Future[Unit] = { // <2>
    val router = Router.router(vertx) // <3>
    val route = router
      .get("/hello")
        .handler(_.response().end("world"))

    vertx //<4>
      .createHttpServer()
      .requestHandler(router.accept)
      .listenFuture(8666, "0.0.0.0")  // <5>
        .map(_ => ()) // <6>
  }
}
  1. ScalaVer­ti­cle is the base class for all Scala-​Verticles. It pro­vides all re­quired meth­ods to in­te­grate with the Vert.x-​runtime.
  2. There are two ways to start a Ver­ti­cle. Over­rid­ing start­Fu­ture, like in this ex­am­ple, tells Vert.x to only con­sider the Ver­ti­cle fully started after the re­turned Fu­ture[Unit] has been suc­cess­fully com­pleted. Al­ter­na­tively one can over­ride start and by that sig­nal to Vert.x the in­stant avail­abil­ity of the Ver­ti­cle.
  3. This block cre­ates a Router for in­com­ing HTTP-​requests. It reg­is­ters a han­dler to an­swer with “world” if a re­quest to the URL “/hello” ar­rives. The class is com­ing from the Vert.x-​web-module.
  4. Every Ver­ti­cle has ac­cess to the Vert.x-​instance. Here we use it to cre­ate a web­server and reg­is­ter our router to han­dle in­com­ing re­quests.
  5. We fi­nally reached the rea­son why I use start­Fu­ture in the first place. All op­er­a­tions in Vert.x are asyn­chro­nous. So start­ing the web­server most def­i­nitely means it takes some more time until it bound to the given port (8666 in this case). That’s why lis­ten­Fu­ture is used, which re­turns a Fu­ture which in turn con­tains the ac­tual in­stance of the web­server that just got started. So our Ver­ti­cle will be ready to re­ceive re­quests after the re­turned Fu­ture has been com­pleted.
  6. In most cases we can re­turn the Fu­ture di­rectly. In this case the Fu­ture re­turned by lis­ten­Fu­ture has the wrong type. We get a Fu­ture[HttpServer] but we need a Fu­ture[Unit] as you can see in the sig­na­ture of start­Fu­ture. This call takes care of map­ping the given Fu­ture[HttpServer] to the re­quired re­turn type.

Testing

I use Sca­laT­est for all my test­ing needs. It comes with stel­lar sup­port for asyn­chro­nous op­er­a­tions and is a per­fect fit for test­ing Vert.x-​applications.

The fol­low­ing HttpVer­ti­cle­Spec shows how to test an HTTP-​API using only Vert.x-​classes. Per­son­ally I pre­fer REST-​assured with its rich DSL. For this post I wanted to stick with Vert.x-API, so here we go.

package io.vertx.scala.sbt

import org.scalatest.Matchers

import scala.concurrent.Promise

class HttpVerticleSpec extends VerticleTesting[HttpVerticle] with Matchers { // <1>

  "HttpVerticle" should "bind to 8666 and answer with 'world'" in { // <2>
    val promise = Promise[String] // <3>

    vertx.createHttpClient()  // <4>
      .getNow(8666, "127.0.0.1", "/hello",
        r => {
          r.exceptionHandler(promise.failure)
          r.bodyHandler(b => promise.success(b.toString))
        })

    promise.future.map(res => res should equal("world")) // <5>
  }

}
  1. Ver­ti­cleTest­ing is a base class for your tests in­cluded with the quickstart-​project. It’s a small helper that takes care of de­ploy­ing/un-​deploying the Ver­ti­cle to be tested and man­ages a Vert.x-​instance. It ad­di­tion­ally ex­tends AsyncFlat­Spec so we can use Fu­tures as test-​return-types.
  2. Isn’t it nice and read­able?
  3. The promise is re­quired as the whole test will run async
  4. We use the vertx-​instance pro­vided by Ver­ti­cleTest­ing to cre­ate a Netty-​based Http­Client. We in­struct the client to call the spec­i­fied URL and to suc­ceed the Promise with the re­turned body.
  5. This cre­ates the ac­tual as­ser­tion. After get­ting the Fu­ture from the Promise an as­ser­tion is cre­ated: The Re­sult should be equal to the String “world”. Sca­laT­est takes care of eval­u­at­ing the re­turned Fu­ture.

That’s all you need to get started!

Futures in vertx-lang-scala

Now for a more in depth topic I think is worth men­tion­ing. vertx-​lang-scala treats async op­er­a­tions the Scala-​way which is a lit­tle dif­fer­ent from what you might be used from Vert.x. For async op­er­a­tions like sub­scrib­ing to the event­bus or de­ploy­ing a Ver­ti­cle you would call a method like this:

vertx.deployVerticle("com.foo.OtherVerticle", res -> {
  if (res.succeeded()) {
    startFuture.complete();
  } else {
    startFuture.fail(res.cause());
  }
});

The de­ployVer­ti­cle method takes the Verticle-​name and a Han­dler[Asyn­cRe­sult] as its ar­gu­ments. The Han­dler[Asyn­cRe­sult] is called after Vert.x tried de­ploy­ing the Ver­ti­cle. This style can also be used for Scala (which might ease the tran­si­tion when com­ing from the Java-​world) but their is a way more scalaish way of doing this.

For every method tak­ing a Han­dler[Asyn­cRe­sult] as its ar­gu­ment I cre­ate an al­ter­na­tive method using Scala-​Futures.

vertx.deployVerticleFuture("com.foo.OtherVerticle") // <1>
  .onComplete{  // <2>
    case Success(s) => println(s"Verticle id is: $s") // <3>
    case Failure(t) => t.printStackTrace()
  }
  1. A method pro­vid­ing a Fu­ture based al­ter­na­tive gets Fu­ture ap­pended to its name and re­turns a Fu­ture in­stead of tak­ing a Han­dler as its ar­gu­ment.
  2. We are now free to use Fu­ture the way we want. In this case on­Com­plete is used to react on the com­ple­tion.
  3. Pat­tern match­ing on the re­sult <3

I strongly rec­om­mend using this ap­proach over using Han­dlers as you won’t run into Callback-​hell and you get all the good­ies Scala pro­vides for async op­er­a­tions.

Future and Promise both need a ExecutionContext

The Vertx­Ex­e­cu­tion­Con­text is made im­plic­itly avail­able in­side the ScalaVer­ti­cle. It makes sure all op­er­a­tions are ex­e­cuted on the cor­rect Event Loop. If you are using Vert.x with­out Ver­ti­cles you have to pro­vide it on your own.

Using the console

A great fea­ture of sbt is the em­bed­ded, con­fig­urable Scala-​console. The con­sole avail­able in the quickstart-​project is pre-​configured to pro­vide a fresh Vert.x-​instance and all re­quired im­ports so you can start play­ing around with Vert.x in an in­stant.

Ex­e­cute the fol­low­ing com­mands in the project-​folder to de­ploy the HttpVer­ti­cle:

sbt
> console
scala> vertx.deployVerticle(nameForVerticle[HttpVerticle])
scala> vertx.deploymentIDs

After ex­e­cut­ing this se­quence you can now point your browser http://lo­cal­host:8666/hello to see our mes­sage. The last com­mand is­sued shows the Ids under which Ver­ti­cles have been de­ployed.

To get rid of the de­ploy­ment you can now type vertx.undeploy(vertx.deploymentIDs.head).

That’s it!

This was a very quick in­tro­duc­tion to our new Scala-​stack. I hope to have given you a lit­tle taste of the Scala good­ness now avail­able with Vert.x. I rec­om­mend dig­ging a lit­tle more through the quick­start to get a feel­ing for what’s there. In my next blog post I will ex­plain some of the de­ci­sions I made and the ob­sta­cles I faced with the dif­fer­ences be­tween Java and Scala /Hint: They are way big­ger than I was aware of).

Enjoy!

Next post

Dynamic Routing in Serverless Microservice with Vert.x Event Bus

The Serverless Framework has become the de facto toolkit for building and deploying serverless functions or applications.

Read more
Previous post

Data-driven Apps made easy with Vert.x 3.4.0 and headless CMS Gentics Mesh

I would like to share why Vert.x is not only a robust foundation for the headless Content Management System Gentics Mesh but also how it can be used to build a template-based web server.

Read more
Related posts

Unit and Integration Tests

Let’s refresh our mind about what we developed so far in the introduction to vert.x series. We forgot an important task. We didn’t test the API.

Read more

My first Vert.x 3 Application

Let's say, you heard someone saying that Vert.x is awesome. Ok great, but you may want to try it by yourself. Well, the next natural question is “where do I start ?”

Read more

Eclipse Vert.x for Scala next steps

This blog post gives an overview of the current plans for the vertx-lang-scala module, in particular with respect to the upcoming Vert.x 4.

Read more