Skip to main content

Development is fun again with nodejs

Being a longtime Java developer, back from when servlets where cool and Struts was making MVC popular among web devs, I always try to find new and more productive ways to deliver software within the Java ecosystem.

Recently I turned to Grails and delivered several projects with it. When developing with Grails you can use the power and the expressiveness of Groovy to write compact, elegant, fluent and readable code.
The downside is that Grails is huge:

  1. even the most simple Grails apps will weigh in the 40MB range
  2. compilation, test and building takes a long time (minutes, actually) even in recent versions
  3. it is (fairly) complex, but that I can understand because it does so much
  4. it will consume a huge chunk of you app server memory when deployed
I have been using Grails as the backend for Mappu too, initially just because I wanted to bootstrap the project quickly and Grails is simply perfect for that. But as time passed I started to find Grails too heavy for a simple REST API. I am currently running the demo on the smallest Rackspace server and it's constantly swapping. It's not slow, but it could be better.


Then last year Packt Publishing gave away a free ebook to all those who claimed it. I rushed and got the Node Cookbook. The book is well written and starts from the basics of node. Javascript knowledge is required. I read the book in small bites and finished it last month.

Node, when combined with Express, is basically another MVC framework, only leaner than any I've seen in Java (well, maybe Struts in the early days was lean too). Also Node+Express gives you a very low level access to the HTTP layer, which feels quite weird for Java devs as most Java frameworks put numerous layers of abstraction between the HTTP protocol and the application.

Initially I resisted the idea of using Javascript on the server side and for some time I thought that maybe instead of totally switching side I could just move from the Grails to the Scala camp, but then I saw the size of the average Scala/Play app and decided that it is not for me. Not anymore anyway.

So all this just to tell you that this week I started rewriting the Mappu API in Node+Express. My Javscript skills are in a pretty good shape and it was easier than I thought.
The major differences I stumbled upon were:
  1. POSTs are handled differently than GETs by Express. Surprisingly (well, for me) POST params are stored in the req.body property, whereas GET params are stored in req.params. It took a couple of hours before I figured this out and I felt pretty dumb afterwards
  2. there is no standard for almost anything: in Java the ecosystem has grown and stabilized (actually it shrunk) so picking, say, an authentication authorization framework is a straightforward process. Node.js is quite the bazaar as there are hundreds of modules to choose from (all on github, btw) for pretty much anything. So now, when I look at my package.json file I think (and worry): how many of these modules are actually still going to be maintained in the next 6 months?
  3. because of 2 I had to actually code an authorization middleware. I think I had not done it since 2004, but doing in Javascript is a breeze and a couple of hours later it was done, complete with Mocha tests
  4. asynchronous callbacks felt weird at first, but I got over it pretty quickly
The (big) advantages over Grails are:
  1. speed: running all (integration+unit) tests takes 141 ms, and I have a lot more in Node+Express! In Grails it took minutes. I dare not do the math on wasted time.
  2. flexibility: Javascript lets you mess with extend pretty much anything and this is a powerful feature. Forget about interfaces, abstract classes, private functions, protected members and all that. Of course with great power comes great responsibility so you and I have to be careful not to abuse this power and craft spaghetti code
  3. low level: you can work around pretty much anything, for instance gracefully handle database errors by retrying a couple of seconds later. You can do the same in Grails too but it is harder because of the Hibernate ORM layer
  4. it is ready for the cloud. Seriously, believe the hype. I will explain another time
Time to go now, let me know what you think in the comments.


Comments

Popular posts from this blog

Mirth: recover space when mirthdb grows out of control

I was recently asked to recover a mirth instance whose embedded database had grown to fill all available space so this is just a note-to-self kind of post. Btw: the recovery, depending on db size and disk speed, is going to take long. The problem A 1.8 Mirth Connect instance was started, then forgotten (well neglected, actually). The user also forgot to setup pruning so the messages filled the embedded Derby database until it grew to fill all the available space on the disk. The SO is linux. The solution First of all: free some disk space so that the database can be started in embedded mode from the cli. You can also copy the whole mirth install to another server if you cannot free space. Depending on db size you will need a corresponding amount of space: in my case a 5GB db required around 2GB to start, process logs and then store the temp files during shrinking. Then open a shell as the user that mirth runs as (you're not running it as root, are you?) and cd in

From 0 to ZFS replication in 5m with syncoid

The ZFS filesystem has many features that once you try them you can never go back. One of the lesser known is probably the support for replicating a zfs filesystem by sending the changes over the network with zfs send/receive. Technically the filesystem changes don't even need to be sent over a network: you could as well dump them on a removable disk, then receive  from the same removable disk.

How to automatically import a ZFS pool built on top of iSCSI devices with systemd

When using ZFS on top of iSCSI devices one needs to deal with the fact that iSCSI devices usually appear late in the boot process. ZFS on the other hand is loaded early and the iSCSI devices are not present at the time ZFS scans available devices for pools to import. This means that not all ZFS pools might be imported after the system has completed boot, even if the underlying devices are present and functional. A quick and dirty solution would be to run  zpool import <poolname> after boot, either manually or from cron. A better, more elegant solution is instead to hook into systemd events and trigger zpool import as soon as the devices are created.