Vert.x on Raspberry Pi

Lightweight JVM web server

Some people say that using Java on Raspberry Pi is a stupid idea. Sure, JVM uses a lot of system resources but when you can watch HD movies on RPi why don’t run a tiny Java app? But I do mean really tiny – no Tomcat nor any other application server involved, no war and deployment stuff. That’s why I came out with idea of using vert.x – a relatively new framework for writing modern web application. In this post I’ll try to show lessons learned after developing a sample app using vert.x and then running it on the Raspberry Pi.

Working with vert.x on RPi

Vert.x is node.js on steroids for JVM. In addition to all the libs for the JVM it offers you a lot more:

  • polyglot – write your application in any language that runs on the JVM (or mix a few)
  • really simple programming model
  • inter-app communication via event bus and shared data
  • ease of scalability and concurrency handling

If you want a gentle start in the world of vert.x I definitely suggest you reading the manual on project website.

Installation

First of all – install Java 8 early access build for ARM from Oracle website. Vert.x indeed requires Java 7, but the 8 build has a real hard float support.

The easiest way to manage vert.x installation is to use GVM:

curl -s get.gvmtool.net | bash
gvm install vertx

Now you should be able to run vertx from the command line.

Development process

In my approach I’m developing the app on my laptop and want to have straight path of running the code on RPI. Since I love the Intellij Idea 12 I put my sources into common maven/gradle structure and use Verticle interface to get full benefits of my IDE: code completion, refactoring and testing support. I use Groovy as a language for my verticles but I want the sources to be compiled on my laptop instead of RPI which a bit improves startup time of the app.

The examples for vert.x distribution are not reaaly development-friendly but I’ve found great example of Groovy starter project on GitHub which introduces two huge ideas: separating configuration of the app in single JSON file and a runVertx gradle task to build and run the app in a single step. I also use the web-server vert.x module to serve static web files of the app frontend. So I have SockJS and REST verticles in the backend and JavaScript frontend in a single project root.

Here is the final layout explained:

src/main/groovy - verticles code
    App.groovy - app lancher
src/main/test - verticles tests
web - frontend stuff
build.gradle - gradle script with runVertx task
run.sh - script for running app on RPI (no compilation)

And a typical development process looks like this:

  • write verticles code (*)
  • write unit tests for verticles (*)
  • run the app on laptop and modify the frontend
  • copy binaries to RPi and run the app from command line

(*) change the order of these two for TDD ;)

The only thing I’m only struggling from is lack of runtime reloading of verticles. Maybe using JRebel could help there but I ain’t got the licence (yet).

You can see my example project here.

Benchmark

I also did some benchmarking of vert.x app on RPI throughput. Sure, you cannot expect that single RPI could handle a lot of transactions per sec, so the test was just for fun. In the test I served a static CSS (bootstrap) and invoked a really simple REST resource (example details/Joe/123 mapping from RouteMatcher). I used siege with 2 and 200 consumers and compared the results between the very.x (1 instance), node.js express and nginx (just for static CSS). I installed node.js 0.8.18 from binaries found here.

  • It is nice that serving static files is quite as fast as in the nginx. There is a benchmark showing that Monkey web server is a bit faster, but in my environment I wasn’t able to achieve more than 45 req/sec on nginx, so ~40 req/sec on vert.x is really good result.
  • Vert.x seems to be about 2-2.5 times faster than node.js with express. This is similar to Tim Fox’ benchmark with both node.js and vert.x in single instance. (BTW: I have no idea how to get 30k req/sec on a workstation as in Tim’s test).
  • The benchmark shows that RPi is indeed a toy PC – on my workstation it’s really easy to achieve thousands of requests per second. So forget about handling hundreds of requests per seconds on a single RPi instance.

(a bit) Speeding up startup time

The thing that really puts node.js in front is the startup time. Java is slow at both JVM startup and while classloading. My first application deployed on RPi took about 30 sec to start, while on my laptop it was about 2-3 seconds. It is possible to cut it down to 18 seconds, here are a few hints:

  • don’t compile sources directly on RPi – build a jar on your workstation. In my setup I run the server from gradle on my laptop but also have a bash script to run it on raspberry which passes vert.x a -cp parameter pointing to builded jar.
  • don’t run a SockJS server when not needed. It tooks about 5 sec to start. You can disable it by setting bridge to false in mod-web configuration.
  • you can write your own mod-web in just a few lines of code. You will save some milliseconds but also this setup allows you to pass custom RESTful routes to RouteMatcher. Look at this example:
def rm = new RouteMatcher()
rm.get('/details/:user/:id', { HttpServerRequest req ->
    req.response.end "User: ${req.params()['user']} ID: ${req.params()['id']}"
} as Handler<HttpServerRequest>)

// Catch / - serve the index page
rm.get('/', { HttpServerRequest req ->
    req.response.sendFile("web/index.html")
} as Handler<HttpServerRequest>)

// Catch all - just send the file from web directory
rm.getWithRegEx('.*', { HttpServerRequest req ->
    req.response.sendFile "web/${req.path}"
} as Handler<HttpServerRequest>)    

To debug the most time consuming steps on app startup, you should configure log4j logging. Vert.x outputs some info about deploying verticles, you can also put your own logging messages. Just copy log4j.jar to vert.x lib directory and add

-Dorg.vertx.logger-delegate-factory-class-name=org.vertx.java.core.logging.impl.Log4jLogDelegateFactory

parameter in vert.x startup script.

Sample project

You can check these concepts by cloning a top monitor GitHub project. It is a Dashing-inspired web app showing results from calling a top command by lucid JQuery knobs.
Every 2 seconds stats from the top call are pushed through eventBus (and internally by SockJS) to frontend.

The project itself it not smashing, you can just check the structure and the tests when I’m mocking ARM-specific top command results. Enjoy!

You May Also Like

Writing JAXB in Groovy

Suppose you want write a jaxb class in groovy. Why? Because you do not have to write these all getters, setters and other methods. You only have to write your fields down.@XmlRootElement@HashCodeAndEquals@ToStringclass Person { String firstName String ...

Inconsistent Dependency Injection to domains with Grails

I've encountered strange behavior with a domain class in my project: services that should be injected were null. I've became suspicious as why is that? Services are injected properly in other domain classes so why this one is different?

Constructors experiment

I've created an experiment. I've created empty LibraryService that should be injected and Book domain class like this:

class Book {
def libraryService

String author
String title
int pageCount

Book() {
println("Finished constructor Book()")
}

Book(String author) {
this()
this.@author = author
println("Finished constructor Book(String author)")
}

Book(String author, String title) {
super()
this.@author = author
this.@title = title
println("Finished constructor Book(String author, String title)")
}

Book(String author, String title, int pageCount) {
this.@author = author
this.@title = title
this.@pageCount = pageCount
println("Finished constructor Book(String author, String title, int pageCount)")
}

void logInjectedService() {
println(" Service libraryService is injected? -> $libraryService")
}
}
class LibraryService {
def serviceMethod() {
}
}

Book has 4 explicit constructors. I want to check which constructor is injecting dependecies. This is my method that constructs Book objects and I called it in controller:

class BookController {
def index() {
constructAndExamineBooks()
}

static constructAndExamineBooks() {
println("Started constructAndExamineBooks")
Book book1 = new Book().logInjectedService()
Book book2 = new Book("foo").logInjectedService()
Book book3 = new Book("foo", 'bar').logInjectedService()
Book book4 = new Book("foo", 'bar', 100).logInjectedService()
Book book5 = new Book(author: "foo", title: 'bar')
println("Finished constructor Book(Map params)")
book5.logInjectedService()
}
}

Analysis

Output looks like this:

Started constructAndExamineBooks
Finished constructor Book()
Service libraryService is injected? -> eu.spoonman.refaktor.LibraryService@2affcce2
Finished constructor Book()
Finished constructor Book(String author)
Service libraryService is injected? -> eu.spoonman.refaktor.LibraryService@2affcce2
Finished constructor Book(String author, String title)
Service libraryService is injected? -> null
Finished constructor Book(String author, String title, int pageCount)
Service libraryService is injected? -> null
Finished constructor Book()
Finished constructor Book(Map params)
Service libraryService is injected? -> eu.spoonman.refaktor.LibraryService@2affcce2

What do we see?

  1. Empty constructor injects dependencies.
  2. Constructor that invokes empty constructor explicitly injects dependencies.
  3. Constructor that invokes parent's constructor explicitly does not inject dependencies.
  4. Constructor without any explicit call declared does not call empty constructor thus it does not inject dependencies.
  5. Constructor provied by Grails with a map as a parameter invokes empty constructor and injects dependencies.

Conclusion

Always explicitily invoke empty constructor in your Grail domain classes to ensure Dependency Injection! I didn't know until today either!

Multi module Gradle project with IDE support

This article is a short how-to about multi-module project setup with usage of the Gradle automation build tool.

Here's how Rich Seller, a StackOverflow user, describes Gradle:
Gradle promises to hit the sweet spot between Ant and Maven. It uses Ivy's approach for dependency resolution. It allows for convention over configuration but also includes Ant tasks as first class citizens. It also wisely allows you to use existing Maven/Ivy repositories.
So why would one use yet another JVM build tool such as Gradle? The answer is simple: to avoid frustration involved by Ant or Maven.

Short story

I was fooling around with some fresh proof of concept and needed a build tool. I'm pretty familiar with Maven so created project from an artifact, and opened the build file, pom.xml for further tuning.
I had been using Grails with its own build system (similar to Gradle, btw) already for some time up then, so after quite a time without Maven, I looked on the pom.xml and found it to be really repulsive.

Once again I felt clearly: XML is not for humans.

After quick googling I found Gradle. It was still in beta (0.8 version) back then, but it's configured with Groovy DSL and that's what a human likes :)

Where are we

In the time Ant can be met but among IT guerrillas, Maven is still on top and couple of others like for example Ivy conquer for the best position, Gradle smoothly went into its mature age. It's now available in 1.3 version, released at 20th of November 2012. I'm glad to recommend it to anyone looking for relief from XML configured tools, or for anyone just looking for simple, elastic and powerful build tool.

Lets build

I have already written about basic project structure so I skip this one, reminding only the basic project structure:
<project root>

├── build.gradle
└── src
├── main
│ ├── java
│ └── groovy

└── test
├── java
└── groovy
Have I just referred myself for the 1st time? Achievement unlocked! ;)

Gradle as most build tools is run from a command line with parameters. The main parameter for Gradle is a 'task name', for example we can run a command: gradle build.
There is no 'create project' task, so the directory structure has to be created by hand. This isn't a hassle though.
Java and groovy sub-folders aren't always mandatory. They depend on what compile plugin is used.

Parent project

Consider an example project 'the-app' of three modules, let say:
  1. database communication layer
  2. domain model and services layer
  3. web presentation layer
Our project directory tree will look like:
the-app

├── dao-layer
│ └── src

├── domain-model
│ └── src

├── web-frontend
│ └── src

├── build.gradle
└── settings.gradle
the-app itself has no src sub-folder as its purpose is only to contain sub-projects and build configuration. If needed it could've been provided with own src though.

To glue modules we need to fill settings.gradle file under the-app directory with a single line of content specifying module names:
include 'dao-layer', 'domain-model', 'web-frontend'
Now the gradle projects command can be executed to obtain such a result:
:projects

------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'the-app'
+--- Project ':dao-layer'
+--- Project ':domain-model'
\--- Project ':web-frontend'
...so we know that Gradle noticed the modules. However gradle build command won't run successful yet because build.gradle file is still empty.

Sub project

As in Maven we can create separate build config file per each module. Let say we starting from DAO layer.
Thus we create a new file the-app/dao-layer/build.gradle with a line of basic build info (notice the new build.gradle was created under sub-project directory):
apply plugin: 'java'
This single line of config for any of modules is enough to execute gradle build command under the-app directory with following result:
:dao-layer:compileJava
:dao-layer:processResources UP-TO-DATE
:dao-layer:classes
:dao-layer:jar
:dao-layer:assemble
:dao-layer:compileTestJava UP-TO-DATE
:dao-layer:processTestResources UP-TO-DATE
:dao-layer:testClasses UP-TO-DATE
:dao-layer:test
:dao-layer:check
:dao-layer:build

BUILD SUCCESSFUL

Total time: 3.256 secs
To use Groovy plugin slightly more configuration is needed:
apply plugin: 'groovy'

repositories {
mavenLocal()
mavenCentral()
}

dependencies {
groovy 'org.codehaus.groovy:groovy-all:2.0.5'
}
At lines 3 to 6 Maven repositories are set. At line 9 dependency with groovy library version is specified. Of course plugin as 'java', 'groovy' and many more can be mixed each other.

If we have settings.gradle file and a build.gradle file for each module, there is no need for parent the-app/build.gradle file at all. Sure that's true but we can go another, better way.

One file to rule them all

Instead of creating many build.gradle config files, one per each module, we can use only the parent's one and make it a bit more juicy. So let us move the the-app/dao-layer/build.gradle a level up to the-app/build-gradle and fill it with new statements to achieve full project configuration:
def langLevel = 1.7

allprojects {

apply plugin: 'idea'

group = 'com.tamashumi'
version = '0.1'
}

subprojects {

apply plugin: 'groovy'

sourceCompatibility = langLevel
targetCompatibility = langLevel

repositories {
mavenLocal()
mavenCentral()
}

dependencies {
groovy 'org.codehaus.groovy:groovy-all:2.0.5'
testCompile 'org.spockframework:spock-core:0.7-groovy-2.0'
}
}

project(':dao-layer') {

dependencies {
compile 'org.hibernate:hibernate-core:4.1.7.Final'
}
}

project(':domain-model') {

dependencies {
compile project(':dao-layer')
}
}

project(':web-frontend') {

apply plugin: 'war'

dependencies {
compile project(':domain-model')
compile 'org.springframework:spring-webmvc:3.1.2.RELEASE'
}
}

idea {
project {
jdkName = langLevel
languageLevel = langLevel
}
}
At the beginning simple variable langLevel is declared. It's worth knowing that we can use almost any Groovy code inside build.gradle file, statements like for example if conditions, for/while loops, closures, switch-case, etc... Quite an advantage over inflexible XML, isn't it?

Next the allProjects block. Any configuration placed in it will influence - what a surprise - all projects, so the parent itself and sub-projects (modules). Inside of the block we have the IDE (Intellij Idea) plugin applied which I wrote more about in previous article (look under "IDE Integration" heading). Enough to say that with this plugin applied here, command gradle idea will generate Idea's project files with modules structure and dependencies. This works really well and plugins for other IDEs are available too.
Remaining two lines at this block define group and version for the project, similar as this is done by Maven.

After that subProjects block appears. It's related to all modules but not the parent project. So here the Groovy language plugin is applied, as all modules are assumed to be written in Groovy.
Below source and target language level are set.
After that come references to standard Maven repositories.
At the end of the block dependencies to groovy version and test library - Spock framework.

Following blocks, project(':module-name'), are responsible for each module configuration. They may be omitted unless allProjects or subProjects configure what's necessary for a specific module. In the example per module configuration goes as follow:
  • Dao-layer module has dependency to an ORM library - Hibernate
  • Domain-model module relies on dao-layer as a dependency. Keyword project is used here again for a reference to other module.
  • Web-frontend applies 'war' plugin which build this module into java web archive. Besides it referes to domain-model module and also use Spring MVC framework dependency.

At the end in idea block is basic info for IDE plugin. Those are parameters corresponding to the Idea's project general settings visible on the following screen shot.


jdkName should match the IDE's SDK name otherwise it has to be set manually under IDE on each Idea's project files (re)generation with gradle idea command.

Is that it?

In the matter of simplicity - yes. That's enough to automate modular application build with custom configuration per module. Not a rocket science, huh? Think about Maven's XML. It would take more effort to setup the same and still achieve less expressible configuration quite far from user-friendly.

Check the online user guide for a lot of configuration possibilities or better download Gradle and see the sample projects.
As a tasty bait take a look for this short choice of available plugins:
  • java
  • groovy
  • scala
  • cpp
  • eclipse
  • netbeans
  • ida
  • maven
  • osgi
  • war
  • ear
  • sonar
  • project-report
  • signing
and more, 3rd party plugins...