Sunday, October 28, 2012

Do we really need another build tool?

Recently I've been getting to know Maven a little bit better. Underneath all the XML fuzz there's a really good, well designed and extremely modular application that does pretty much everything one can ask for (and then some).

With Maven things are simple: bloated XML contains every possible setting for every possible plugin, every possible dependency and what have you. You might hate the fact that it is XML. I say screw it - let's try to live with it.

On many occasions the XML nature has been the corner stone for many people to start developing their own build tools. I'd say their repulsion came from Ant and if so it wasn't totally unjustified. I hate Ant with a passion when it comes to building Java projects. Ant is great for cross-platform imperative tasks (download this, unzip, make a link, go get coffee) but Java projects are a completely different beast. It's not that you can't do it with Ant but rather that it takes forever to do everything (not to mention that everyone is doing it differently).

Like I said people's repulsion to XML configuration files pushed some of them into the hands of Groovy (my absolutely favorite language) to create Gradle. One of my very good friends, Szczepan Faber, works on this tool and I am grateful for his efforts. It makes the landscape of build tools a lot more interesting. It's from diversity that the progress comes in this case.

Being all Groovy geek and loving the language and what one can do with it I must say I am a little bit confused as to why I'd use Gradle. I mean I get that the build file is terse, that the default source/target compiler makes more sense, that I can declare 10 dependencies in one line... But what about plugin support?

From my personal perspective the idea of creating a new tool from scratch is pure nonsense. Maven is the de-factor standard in Java world and not without reason. It does what it does and does it good. Where Maven lacks in features is imperative programming but that can easily be overcome with either custom Maven plugins or GMaven plugin. For me it'd make a lot more sense if Gradle adopted the Maven API for plugins and build on that to gain the much needed functionality into the fold before it is missing.

Like I said before, I get that one can feel intimidated by all the XML in Maven builds. I get that one can mess things up with Maven really bad. I also get that Gradle, Buildr and others might be better in some cases. What I hate about the overall landscape is that the plugins for build systems aren't compatible and even if I'd like to use Gradle to build my next gen rocking cool enterprise java application I'd dead in the water pretty soon because the EAR/EJB archive support in Gradle is non-existent. I hope this changes some day...

Have a nice day!

Tomcat Clustering and a pile of problems

I've been trying to familiarize myself with Tomcat's clustering capabilities today. At the end of it I succeeded but the experience was way less than pleasant. But let's start from the beginning...

At first all seemed really nice: Sunday afternoon, not much to do, some thoughts around playing with Tomcat for the sake of finding out what it's capable of.. Basically the idyll. So I though wouldn't it be nice if I learned how to setup a Tomcat cluster? I already done some horrible things to Tomcat in the past (Single Sing On for instance) but I've never tried clustering. How about that? And so I started what anybody would do - to read the configuration files. No - I'm kidding :) I started to Google for some clustering HOWTO to see if I'm alone in what I'm trying to accomplish. Fortunately it turned out to be a pretty well described topic with some ready-to-copy-and-paste examples. Highly encouraged by what I found myself copying parts of what I found in that miserable HOWTO into configuration of my 2 Tomcats that are supposed to form "the cluster". After about 2 minutes of frantic alt-tabbing, CTRL+C/CTRL+V-ing I arrived at the glamorous point where I was able to start at least one of the Tomcat's to see if the configuration even allows to the server to start. Well, it started, all right. But it didn't work.
Oct 28, 2012 5:14:09 PM org.apache.catalina.ha.deploy.FarmWarDeployer start
SEVERE: FarmWarDeployer can only work as host cluster subelement!
Oh what the heck is this? I though.Wasn't the example from original documentation? I was always banking on those to be really of good quality and now this dissapointment? There's a number of things wrong with the example (and as it turned out with the original server.xml as well). But let's start from the beginning.

server.xml and it's comments

There is a dark place in server.xml that shows how to configure a cluster in Tomcat.
      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/> -->
So I removed the comment in two instances but it turned out not to be what I expected. Well it did something (not sure what exactly) but it wasn't all that inspiring. There is however a reference to further documentation. I followed that and then the frantic copy/paste activity started. All was quite nice up until I started Tomcat and saw the SEVERE I mentioned before. Back to Google. And then some. Finally I arrived at this discussion where I learned that the <Cluster> element is supposed to be nested within the <Host> element and not where it was suggested by the original server.xml file. Go figure. Anyways, I moved the section down to the Host and this time
Oct 28, 2012 5:01:34 PM org.apache.catalina.ha.deploy.FarmWarDeployer start
INFO: Cluster FarmWarDeployer started.
Great Scott! It will work now! And so I copied my beloved distributable, servlet-api-3.0-enabled hello.war into the /tmp/war-listen folder hoping to see Tomcat spring to work, install the application and make my day. But nothing happened! The example in Tomcat documentation specifies watchEnable="false" by default. What was going through the mind of that someone who wrote it is beyond my understanding of the universe. Anyways, after I changed it to true finally something started to happen.

Since Tomcat ain't for the faint-hearted I was presented with a puzzle:
Oct 28, 2012 5:29:36 PM org.apache.catalina.ha.deploy.FarmWarDeployer fileModified
INFO: Installing webapp [/hello] from [/tmp/war-deploy1/hello.war]
Oct 28, 2012 5:29:36 PM org.apache.catalina.ha.deploy.FarmWarDeployer remove
INFO: Cluster wide remove of web app [/hello]
What the heck? Cluster wide what? I just installed this application, didn't I? I mean thought it will be enough to copy the file in the proper folder and that should be it, should it not?

As it turns out it does work quite nicely if you specify the deployDir to where Tomcat expects to auto deploy applications (by default webapps, or rather ${catalina.base}/webapps). After I changed that, copied the Cluster configuration to the second Tomcat, started both and copied the hello.war application to /tmp/war-listen both Tomcats have received the proper nourishment and started talking my language.

Summary

There's a number of lessons learned from this encounter. First and foremost Tomcat is just awesome. It's so unbelievably small yet so feature-packed. It just makes my day. While debugging Tomcat configuration issues it really helps to start it (at least under Linux) not by ./startup.sh but ./catalina.sh run. This way you'll have the console to view the logs and to terminate it all in case you're not happy with what you see. And last but not least: Google is your friend. I mean it. It is the one thing all this could not be possible without in terms of knowledge sharing.

Have a nice day!

Maven and Tomcat 7

You might be unaware of this but Maven is capable of running Tomcat 7 as embedded container. The maven-tomcat-plugin has been moved under the Apache Foundation umbrella and is being developed further. The current version is 2.0, packing in both versions of Tomcat, 6 and 7. Setting it up is explained here. All the configuration is very similar to the original one and your IDE will help you out there (at least Eclipse does).

Finally... It's been way to long to wait for an update on this one.

Sunday, October 14, 2012

GitHub, Travis and status image

Since not so long ago GitHub provides an opportunity to build OpenSource projects on Travis CI. The integration is quite stunning and includes among other things:
  • Single sign-on with GitHuub
  • Automatic build setup with a single mouse click
  • Status image generation
Well, I tried to setup build of my Spring examples today and Markdown gave ma a little bit of a hard time to figure out how to put together an image link to by build status. Finally I stumbled upon this stackoverflow.com question but the brackets were all wrong. Here's what it should look like:
[![_alt_text_](_image_url_)](_link_)
With the parentheses instead of brackets all works nice :)

And live is good again :)

Friday, September 28, 2012

Foreman and multiple ports per process

The problem

Composing an application of multiple software components is the de facto standard these days. It's rarely the case for the application to embed a database server, queue server or the like. To help manage the ever growing complexity of this kind of systems we can use Foreman - a Ruby application using a Procfile to spin off instances of declared services (same as for example Heroku uses to manage processes).

Many software components these days besides providing the core functionality tend to give the user some sort of administration interface. That interface is often available under different a port. Up until now Foreman assigned only one single port per process, via the $PORT environment variable. As I started using Foreman recently this inconvenience became a stopper for me trying to start ActiveMQ, 2 instances of MongoDB in a shard and Neo4j with my Sinatra application. All was nice but the lack of ability to start MongoDB's control interface on separate ports blew it all out of the water.

The solution

I've came to the conclusion that it'd be a really handy to use multiple ports not just for the case I just described. And so I created a ticket on GitHub for this. Being a forthcoming guy and all I decided to take a crack at implementing this functionality myself. A few hours later a working and tested solution covering all the cases was ready to be pulled in. Let's see if the maintainer will agree to pull it in :)

How to use it?

Assuming David will pull it in the formula is as follows:
alpha: command_to_start -p1 $PORT -p2 $PORT0
beta:  command_to_start -p1 $PORT1 -p3 $PORT9
What would that mean?

alpha would get assigned 2 ports: $PORT = 50xx and $PORT0 = 51xx
beta would get assigned 3 ports: $PORT = 52xx, $PORT1 = 53xx and $PORT9 = 54xx

Since Foreman makes an assumption that at most 100 ports are assigned to one variable this new functionality uses that to assign ranges for subsequent ports. And because I wanted to stay compatible with results not using this new feature the original port range numeration regardless of the usage of $PORT in the command stayed the same. That's why beta still gets the $PORT assigned even though it is not used.

Have a nice day!

Thursday, September 6, 2012

AMQP, RabbitMQ and round robin

I'm working on a set of examples of how to use RabbitMQ from different languages. Among other things I've worked on reviewing the ruby AMQP gem examples. Unfortunately when it came to demonstrating multiple consumers (a sort of scalability example) I hit a snag: even though I have had 4 consumers only the first one was used.

After setting the number of test messages to a really high number things were finally looking up - the second and third and forth consumers were involved. But that sucked big time and to prove it I started digging further to find out what actually makes it do the things it does.

:prefetch => 1 was the setting (as stated on some stackoverflow.com page) but setting it alone didn't do the trick because that made the channel get only one message and that was it. To continue receiving messages they have had to be ack'ed.

Talking is cheap - here's the example code



Have fun!

Monday, August 27, 2012

The not so obvious fact about tag libraries

I've came across this thing today and quite frankly I feel a little bit ashamed that I didn't know it yet. The concept of tag libraries is not new in the JSP world. It's just unusual to write tags because one needs to provide a tag library description file along with it and that increases the complexity of the solution (or so it is seen).

The nice thing about tag libraries is that they don't necessarily need a TLD file to drive them - a folder is more than enough for simple cases:

File /WEB-INF/tags/hello.tag
Hello, world! from a tag
File /index.jsp
<@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>

<tags:hello />
It's really that simple!

There's obviously more to it (how to pass the tag body, how to pass parameters to the tag) - maybe next time :)