Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

Rapid App Development with Vert.x 3

Jez PrimeHi, I’m Jeremy Prime, an independent software consultant based in the UK. My primary professional interests revolve around software development on the JVM, and hence most of my development projects are Java-based. I first used JRebel (in its trial version) on a Spring/JavaEE project I worked on in 2013, and was pretty much instantly addicted to the reliable hot class reloading, sufficiently so that it took just days before I shouted “TAKE MY MONEY” to ZeroTurnaround to buy a full licence. I’ve had a strong interest in the non-blocking application platform Vert.x (http://vertx.io) since I first heard of it back in 2012, and late in 2014 I was asked to join a project using Vert.x (at that time version 2) as one of its core technologies. So in my idealized world for this project, I’d want to keep my Vert.x application running while making code changes and recompiling.

TL;DR: version 3 of the Vert.x non-blocking framework works well with JRebel, unlike version 2. For more information, read on!

Introducing Vert.x

logo-white-big

Vert.x is an asynchronous, non-blocking framework for development of applications of all kinds. While it has mainly been talked about in the context of web applications, it has far wider potential uses than purely the web. It is intended to support high performance and ease development of non-blocking applications, and it also supports several languages available on the JVM. Think of it (for those who have heard of node.js) as node.js on the JVM, but not restricted to Javascript.

How well do JRebel and Vert.x 2 play together?

When I started my current Vert.x-based project, I decided to investigate whether or not Vert.x and JRebel could play nicely together, and was sadly disappointed (#sadPanda) – see here and here. The information at these two links was supported by my own unsophisticated experiments, so I was resigned to not having the convenience of JRebel on this particular project.

The reason for this is that basically the classloader isolation approach used in Vert.x 2 (each module runs in its own classloader doesn’t appear to behave in line with JRebel’s expectations. Damn those pesky classloaders! This would imply that to support Vert.x 2, appreciable work would be required in JRebel (Similar the the work done in OSGi, for per-bundle classloaders). In addition, Vert.x 2 had a mechanism for restarting a module whose classes had changed – this typically took a few seconds and any existing state was abandoned, but it proved useful during development. I doubt therefore that the work required to make JRebel play nicely with Vert.x 2 was a high priority.

What’s changed in Vert.x 3?

In Vert.x 3, the module infrastructure used by Vert.x 2 was effectively abandoned, and the model for loading classes by default changed so that each verticle (the unit of code in Vert.x) is loaded by the current classloader, in effect leading to a single flat classpath within the application. This makes a Vert.x deployment essentially like any other JVM application. It is possible to deploy a verticle in an isolated classloader, but this is not the default behaviour.

On our current project, we’re only using the default, non-isolated, classloader behaviour, so it would appear that JRebel might now work well with Vert.x 3.0. I therefore decided to give it a shot with a simple experiment, and was pleased to find that indeed JRebel can reload classes correctly within a Vert.x 3.0 application, with no special tweaking.

Show me JRebel working with Vert.x 3!

I’ve created a very simple Vert.x 3 project (using Maven for convenience, but it should be reasonably easy to port to gradle/ant/any other build tool of choice if you wish) – you can find it on github. You should note that this currently uses the milestone 4 release of Vert.x 3, though I will update and re-test with each new pre-release milestone.

You’ll also need the JRebel plugin installed in your favourite IDE – I use IntelliJ IDEA, with which I’ve tested this setup, but this should also work on Eclipse or NetBeans. If you don’t already have JRebel, you can try it out for free using the 14 day trial.

Clone the repository above, import it into your IDE (with JRebel plugin already installed), and run the main method in the DemoVerticle class, using the JRebel plugin so that when you modify and recompile the class, it will be reloaded automatically. The code you’ll be interested in DemoVerticle is the responseBody method:

    private String responseBody(final HttpServerRequest req) {
        String param = req.params().get("abc");
        return("Hello" + (param == null ? "" : " " + param + "0"));
    }

Then hit the URL http://localhost:8080/?abc=1, and you should see Hello 10 in the body of the response, as you can see from my screenshot.

VertxBeforeChange

So far so good. With the code still running, modify the DemoVerticle::responseBody method so that it will return a different response, I suggest the following, making use of JRebel’s ability to augment the class schema by adding new methods…

    private String responseBody(final HttpServerRequest req) {
        String param = req.params().get("abc");
        return appendParam(param);
    }

    private String appendParam(String param) {
        return("Hello" + (param == null ? "" : " " + param + "000"));
    }

Now re-compile the class (if your IDE isn’t configured to do so automatically on save) – still without needing to stop your application. Refresh your browser, and you should now see a different response, corresponding to the change you made. How great is that!

VertxAfterChange

Your JRebel console should also show that it has reloaded the file.

So everything’s perfect in the JRebel/Vert.x world, right?

minion-not-perfectNot quite, but it’s very useful to be able to use JRebel and Vert.x together for those of us who are working with Vert.x. The turnaround time for “exploratory” code changes is much smaller (I generally practice TDD but it is often useful also to fiddle with some running code just to get my thoughts in order, and JRebel makes this a breeze).

The elements where there is still room for improvement are firstly that code in the verticle start method won’t be re-run. Normally when you deploy a verticle the start method is called and used to configure http listeners, event bus listeners etc. If you change the start method to add a new event bus listener, for example, that code will not get re-run on a JRebel reload. This is similar to how JRebel doesn’t re-run constructors on existing objects in a runtime, due to the code potentially being of a run-once only design. You can write a JRebel plugin to invoke the constructor or start method code on a class reload, if that’s important to you. More info about writing JRebel plugins can be found here.

Another related recommendation (which is a generally good practice anyway) – don’t directly embed code as lambdas in the start method of a verticle, but have message handlers, http handlers etc which you create in that start method call out to other methods (changes to which will be reflected by JRebel, automatically) where possible.

As well as JRebel, ZeroTurnaround also offer a profiling product called XRebel, which helps identify areas of poor performance. Sadly this does not yet offer any Vert.x integration at all (Vert.x doesn’t expose the endpoint) so we’re not quite in “perfect world” territory just yet. I would really love XRebel to work with Vert.x but at the same time appreciate that there’s probably quite a lot of work involved to make that happen and I don’t know whether there is enough demand among Vert.x users to make that change worthwhile from ZeroTurnaround’s point of view. I live in hope, however.

Ok, so maybe not perfect, but this is still very welcome

Very much so! Even for someone like me whose main development cycle is test-driven, it can frequently be useful to be able to reload classes in situ following small changes. The faster the turnaround of code changes the better, and I am now very happy at being able to use JRebel in the development cycle on my current Vert.x-based project.

In summary

You made it, Great job! Thanks to a significant simplification of the classloader structure in Vert.x 3, it is now possible to use JRebel to reload classes within a Vert.x application in situ, this cutting down on the turnaround time to observe the effect of code changes within a running application during development. Have you tried JRebel with your Vert.x projects? Let me know how your experience was in the comments below, or ping me on twitter, @jezprime. Looking forward to hearing from you!