This post has been migrated to http://www.thinkcode.se/blog/2014/02/28/scripting-with-ruby-and-maven
In my assignment as a Configuration Manager, CM, I need to script a lot of things. I also need to automate the execution. Most of the stuff I build is built using Maven. Some is built using Ant. Both Maven and Ant are easy to run from TeamCity. But none of them are very flexible when it comes to scripting. Maven isn’t designed for it and Ant is missing some features and get very verbose. The most important feature I am missing in Ant is repetition.
I saw a panel debate a while ago where three guys were discussing their favorite tools. The tools represented were Scala, Ruby and Groovy. One thing that I remembered from that session was that the Scala guy mentioned that he often used Ruby when scripting. My problem with using Ruby is that I don’t have control over my execution environment. I can’t install tools in it. I am not interested, either, because that wouldn’t scale very well since the installation done on our build servers are done manually. I can, however, expect that Maven and Ant will work.
Given that I can expect Maven to work, I decided to try to execute a Ruby script from Maven. It turned out to work very well. I was able to reduce the size of an Ant script with 50% on my first attempt. In my opinion, the readability increased a lot. I was able to write the script more or less as prose.
If you are interested, this is how I did.
The file structure I use in this example looks like this:
example |-- pom.xml `-- src `-- main `-- ruby `-- script_from_maven.rb
I will execute a Ruby script from Maven. Let me start with a simple script that will demonstrate this. It is a little more than a Hello World, but not much. If you are a Ruby guy, you might have opinions about my style. Please let me know, I am just starting out on the Ruby path.
This is my script. I define a Ruby class. At the end of the file I create an instance of the class and executes one method.
The only thing I do is print hello to greet any user and print the value of my JAVA_HOME environment variable. But this is enough for me to know that my script was possible to execute.
I need a Maven pom that calls my script above. An example may look like this:
The two important things in this pom are the Maven exec plugin that I use to call JRuby and the dependency to JRuby.
I execute JRuby in the same Java process as Maven is executed. This has the benefit that I will not risk leaving any dangling processes behind if something fails unexpectedly. I also connect the execution to a Maven lifecycle phase to make my life easier. I have decided that this fantastic script should always be executed during the process-resources phase.
Why not write a Maven plugin that will solve the same problem? This is a valid question and the simple answer is that sometimes I don’t have a need to be a part of the Maven eco system. In these cases, it definitely makes sense to script using something else. In other situations, it may be a good thing to be a part of the Maven eco system. When I have that need I will write a Maven plugin instead.
As usual, it all depends, and using the right tool at the right time is important.
Why is this so good then?
- I have access to a complete programming language with all the possibilities this brings to the table
- I can easily develop my script using my favorite tool, Jetbrains IntelliJ Idea
- I can test drive my code
- I can execute this wherever I can execute Maven
Do I need more reasons than this? No, not really. Two of them would have been enough.