Vert.x instead of servlets, time for something new

Why

How old are dear servlets? 15 years you say? Hm, maybe it would be time to check on alternative technologies, not because servlets would be necessarily bad but just to check whether new times brought also new concepts forward. And you bet they did – look at Node.js, it‘s quite popular nowadays. JavaScript aside, Node.js has a different way of working – a reactor pattern, not at least a very good way to use the multicore facilities of today’s machines. Node.js is actually not alone in this league – the very popular Nginx (yes, the one stealing Apache web server’s crown) works apparently the same way. But if you want to replace your servlets Java web application, you’ll HAVE to try vert.x. Cool, multithreading without writing yourself threads! NOTE: Worth mentioning here: vert.x can do a lot of stuff and a web application is only one of its possible uses.

Go

This blog is not about teaching the concepts of vert.x (or any other concepts, for that matter) so please, head off first to vert.x site and start reading the concepts, then download and install it (did you notice it’s based on Netty?). This was the really easy part, uuuuntilllll I noticed there’s a LOT of documentation and no obvious way to start small. That’s actually not that unusual especially for opensource, that’s why it’s worth mentioning here the vert.x Google group – very responsive and a good read for many details left out of the „official way“. So, downloaded, created a test project with Maven according to the guide and… ouch.

Running Maven from the command line according to the guide worked fine. Running Maven from Eclipse? Noooot quite! It gives me always heaps of warnings about incorrect logger setup, it can‘t do mvn install because it won’t find the integration tests classes, mvn clean doesn’t really clean if combined with another goal… but it’s not the first time when I ran into m2e problems so I didn’t really bother anymore. You just have to get used with m2e bitching that it won’t support whatever goals for pretty much every basic pom then paint your dear project always in red. A maven runMod (that’s how you run your fresh vert.x module) will work fine, but if I do changes while running the server (yes vert.x can hotdeploy changes) it will forget later my custom enum class… m2e fun, right – so only a project clean helps here. And in 5 minutes again. Then again.

The application

My application would have to simulate a backend under development, so it will have to answer a few HTTP requests with crafted answers. A stub, so to say. For this, vert.x works in the good old Sinatra way: with routing. You set handlers to the routes you want to handle and that’s it. The RouteMatcher code given as example in the vert.x documentation is SO straightforward that it’s not even worth mentioning here. It just worked out-of-the-box. Really!

As my server stub application needs to check the request data and answer with some fixed answers, the simplest way was to store all these in a few files. But, should I load the files on EACH request? Of course not! The vertices are supposed to be quick and non-blocking, rrrright? One could program for this a worker vertice, which would read in memory the (small and few) files, then sit in the container and listen for requests coming through the event bus (by the way, based on Hazelcast) – then provide my request handlers with the right files. Is this too much of a programming effort, to register with the event bus and pass messages around? Enter shared data, a very very simple concept of putting stuff in Multimaps or Sets which are then accessed by name by other vertices from the same instance. From the same instance only, mind you, but in my case it was plenty enough. Below’s some code which gets the shared data maps created by simply referencing them the first time.

Note: if you handle text files, think twice about the charset you’re going to have them!

public class FilesReader extends Verticle {
    public void start() {
        final Logger logger = container.logger();
        ConcurrentSharedMap<string, string=""> textMap = vertx.sharedData().getMap("vpmsstub.textfiles");
        for (MyFiles file : MyFiles.values()) {
            try {
                URL url = Resources.getResource(file.getFile());
                    textMap.put(file.name(), Resources.toString(url, Charsets.US_ASCII));
            } catch (Exception e) {
                logger.info("Server error, could not read file: " + e.getLocalizedMessage());
                container.exit();
            }
        }
    }
}

In case you wonder what’s that resource reading thing, it’s Google Guava. Highly recommended – less code than regular Java classpath searching, and it works for both IDE and packaged version (unlike addressing files directly)

MyFiles is just an enum of my creation, containing the file names I wanted to handle. I also thought initially I would use these enums as keys in the shared data maps but surprise surprise, vert.x doesn’t support them. Whyzdat? Enums in Java 7 aren’t immutable indeed (I wonder what the background for this funny decision was) so I can understand the decision.

I programmed also test clients for nice automated testing. I know I could have used PhantomJS for this (no, I don’t use Selenium for automated testing) because there’s no complicated JS/layout to test, but I could really use the supplementary vert.x programming exercise.

Speaking of exercise, that’s how I noticed that once you run the vertice directly, you won’t have the module dependence JARs around anymore. Really obvious when you think about it (they are MODULE dependences, right), but because I wrote first the clients with Guava, I had to do the work again this time with regular Java stuff. Now that I come to think about it, the manual does describe how to specify classpath entries in the command line, but I couldn’t bother to do it that way.  And they had to load the test files themselves, as the shared data wouldn’t be available to them either (different vert.x instance…). So, rewrote they were and here’s a small client code example:

public class TestPost extends Verticle {
    public void start() {
        HttpClientRequest req = vertx.createHttpClient().setPort(8080).setHost("localhost")
                .post("/myapp/blah", new Handler() {
                    public void handle(HttpClientResponse response) {
                        response.bodyHandler(new Handler() {
                            public void handle(Buffer data) {
                                System.out.println(data);
                                container.exit();
                            }
                        });
                    }
                });
        try (Scanner s = new Scanner(new File("../../../../resources/process.json"))) {
            s.useDelimiter("\\Z");  // not just one token but the whole file
            String text = s.next();
            req.headers().set("Content-length", Integer.toString(text.length()));
            req.write(text).end();
        } catch (Exception e) {
            e.printStackTrace();
            container.exit();
        }
    }
}

Yes, I also hate that long path to grab the file but didn’t bother to change it. Enough programming for a test case. They also read the test files in just one go (not exactly the ideal use case for a Scanner…) but in my case they’re going to be small. You, don’t do this if you need to handle arbitrary sized files!

Test question: why didn‘t I end the start() function with a general container.exit() call? Well, let’s have again a look at the client start() function: it makes a HTTP GET request and registers a handler for the event when the answer comes back from the server. Thsi means, a container.exit() at the end of the function would exit the client application immediately – without waiting for an answer at all!

What else…

Instead of having a static client application throwing predefined POST requests, how about a page with a JSON editor which sends customized requests? With jQuery and its JSON editor plugin? But this has nothing to do with vert.x so… it’s a TODO for me.

And… maybe some day vert.x will also have regular IDE integration – a vert.x Eclipse plugin or such – without forcing you to use the clumsy Maven or Gradle plugins…

Advertisements

2 thoughts on “Vert.x instead of servlets, time for something new

  1. VertX 3 has much better docs and sample code.
    I used Groovy instead of Java. Was able to fire up a simple web service as a test tool in about an hour. Work benchmarked it as 20 times faster than a similar Python service and 2x faster than NodeJS.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s