JRuby on Rails and legacy java apps: Managing dependencies

Filed Under (JRuby, Java, Rails) by Leonardo Borges on 01-07-2009

Tagged Under : , ,

The motivation for this post came from a couple of messages I’ve seen on the jruby’s google group and because I think it’s pretty cool to share how we tackled this problem.

- A little bit of context

We, as a vast amount of people out there, have legacy Java code. A lot. In our case this legacy is pretty much crucial to our business. We can’t just trash it and start from scratch. Bad idea.

On the other hand we do have new features to be built on top of it. But we wanted an easier way to develop this new stuff and decided for a JRuby on Rails solution, using it as a front-end to our existing services.

- What we decided to do

Our final rails project would make use of a specially created jar file containing our Java application. This Jar would also contain a public interface of the services we’d have to interact with from rails.

As any Java application, ours depend on a number of external jar files that correspond to the various framewoks we usually have in place. e.g.: Hibernate, Spring, apache-commons …

Which means we need to make our app’s jar and all it’s dependencies available in the JRuby classpath in order to use it.

Given we’re using warbler to package our application as a war file, we just need to place all jars needed into our rails app’s lib folder. Warbler then takes care of copying any jar files located in there into the war.

- The problem

So we needed a smart way to include all these dependencies into the project, and copy/paste isn’t an option.

In the Java world we use Maven to manage our projects dependencies - and you should too. Because of that our approach involved turning our rails application into a Maven aware project.

Basically we needed a pom file that would declaratively list our java project as a dependency. From there on, Maven knows what the dependencies are and downloads them to your local repository.

Which leaves us with one more task. We need to put all these dependencies into our lib folder after maven has downloaded them.

Below you’ll find the pom.xml file that we use to achieve this with inline comments explaining each bit:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.company</groupId>
  <!-- notice how we specify the packaging to be a war,
          that way, maven knows where to copy the jar files -->
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <artifactId>railsApp</artifactId>
  <name>railsApp</name>
    <dependencies>
        <dependency>
            <groupId>com.company</groupId>
            <artifactId>java-legacy-app</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>railsApp</finalName>
        <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <executions>
          <execution>
            <!-- This tasks only creates a basic structure expected by maven,
                    so it can do its work -->
            <id>create-mock-web-descriptor</id>
            <phase>compile</phase>
            <configuration>
              <executable>/bin/sh</executable>
              <workingDirectory>.</workingDirectory>
              <arguments>
                <argument>-c</argument>
                <argument>
                    mkdir -p src/main/webapp/WEB-INF
                    touch    src/main/webapp/WEB-INF/web.xml
                </argument>
              </arguments>
            </configuration>
            <goals>
              <goal>exec</goal>
            </goals>
          </execution>
          <execution>
            <!-- Now in the package phase we copy the jar files
                    that maven put into the fake web app to our rails' lib folder -->
            <id>copy-needed-jars-into-lib</id>
            <phase>package</phase>
            <configuration>
              <executable>/bin/sh</executable>
              <workingDirectory>.</workingDirectory>
              <arguments>
                <argument>-c</argument>
                <argument>
                    rm -f lib/*.jar
                    cp target/railsApp/WEB-INF/lib/*.jar lib
                    rm -rf target/railsApp*
                    rm -rf src
                </argument>
              </arguments>
            </configuration>
            <goals>
              <goal>exec</goal>
            </goals>
          </execution>
          <execution>
           <!-- Here we optionally create the final war file containing our rails app using warbler,
                     doing a small cleanup of the files and folders maven created  -->
            <id>create-final-war</id>
            <phase>package</phase>
            <configuration>
              <executable>/bin/sh</executable>
              <workingDirectory>.</workingDirectory>
              <arguments>
                <argument>-c</argument>
                <argument>
                   rm -rf *.war tmp/war
                   jruby -S warble &amp;&amp; \
                   mv *.war target/railsApp.war
                </argument>
              </arguments>
            </configuration>
            <goals>
              <goal>exec</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
     </plugins>
    </build>
</project>

Now from the command line we can just run mvn package and we’re good to go.

Maven will start to package the application as a war file. Since it’s not a Java application we create the empty web.xml file in the compile phase, to fool maven.

After it has copied all the dependencies into WEB-INF/lib the next packaging goals will make sure we copy them to our rails’ lib folder, also creating the final war file, ready for deployment.

Note that once done, you can use a simple code snippet similar to this one as an initializer and load all dependencies:

Dir.entries("#{RAILS_ROOT}/lib").sort.each do |entry|
  if entry =~ /.jar$/
    require entry
  end
end

Then we can just use script/console, script/server and so on, as we normally would.

Sorry for the long post, I tried to pack in as much as I could and I certainly hope it’s useful to someone. Any doubts, comments and etc… just drop me a line. :)

Google IO: Thoughtworks on GAE

Filed Under (JRuby, Java) by Leonardo Borges on 22-06-2009

Tagged Under : ,

I’ve just watched a video from Google IO where Martin Fowler and Rebecca Parsons went through some of the aspects that involves the development of an application for the cloud - focusing on the JVM.

In terms of the Google App Engine, you don’t have access to a relational database, thing I found out when I first tried it.  Instead you get a Big Table.

Martin put out a good analogy and you can just think of it as a nested hash map. It’s certainly a shift on how we think these days, but layers of abstraction like google’s DataStore and the Java Persistence API will help in the transition.

Another interesting bit about the presentation was on how concurrency works on GAE.

Essentially, in an standard Java application you have a single memory space where you have at least one running thread. You can create threads on the fly, which will share the same memory space, thus making it easy to share data.

On the app engine, things work differently. What you have are separate memory spaces with a single thread on each one. Any attempt to create a new thread will result in an exception. The solution for sharing information in this case? Use the nested hash map (big table).

Now, whereas you might not be worried about this since your application doesn’t span any threads, as well pointed by Martin Fowler, it’s the code you don’t see that you need to be careful with. Any Java application uses a number of 3rd party libraries that might span out threads of their own, which will result in your application blowing up.

That rang a bell. Again, back when I was trying the app engine, one of the configuration bits shared by Ola Bini looked like this:

   config.webxml.jruby.min.runtimes = 1
   config.webxml.jruby.max.runtimes = 1
   config.webxml.jruby.init.serial = true

I think the properties are pretty much self-explanatory but I didn’t quite understand the reason for setting it back then.

If you happen to have bigger values for the number of runtimes you want, you need to set the serial property to true, otherwise JRuby will span several threads to create the runtimes.

This is a really good example of things that might fail whether you’re migrating or developing a new app to deploy on the App Engine. Luckily for us, JRuby has a smart and neat way to handle this - the configuration I’ve just shown, but most of the libraries out there that might rely on threads are not prepared.

Martin and Rebecca’s opinion on this is that new releases of these same libraries will start to take it into account, since a bigger adoption of the Cloud seem to be on the way.

Make sure you watch the video. I certainly left a lot of interesting stuff out.

Helping the JRuby effort: Debugging the source

Filed Under (JRuby, Java, Ruby) by Leonardo Borges on 14-06-2009

Tagged Under : , ,

Wanna help improve JRuby? Make sure you read this post by Charles Nutter first. There he explains how to run Ruby specs with JRuby.

Start with fixing Ruby specs is a great way to get acquainted with the code. And it’s also a important task in order to make sure JRuby is the most complete and compatible ruby implementation out there.

But before you get your hands dirty, it will be a lot easier if you can actually debug JRuby’s source while fixing any specs - or bugs/features for that matter.

Taking as an example one of the specs I fixed, this is how you run it - form within your jruby source directory:

$ bin/jruby spec/mspec/bin/mspec spec/ruby/language/class_spec.rb

This is using jruby to execute the mspec binary against the class_spec.rb script. Now, if you want to debug this script instead of only running it, try this:

$ bin/jruby -J-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=4000 \
 -J-Xdebug \
 spec/mspec/bin/mspec -T-X+C spec/ruby/language/class_spec.rb

The extra arguments will start a debugging session on port 4000 and suspend the VM, which will be waiting for another debug process to attach. You can do that using any IDE of your choice but I’ll use Eclipse for this example.

Go to the Run menu and select the “Debug Configurations…” item. You’ll see a screen similar to the one shown below:

Eclipse Debug Configurations Wizard

Eclipse Debug Configurations Wizard

As you can see, you need to create a new “Remote Java Application” configuration, setting the port to the same one you used to start the debugger session - 4000 in our case. Don’t forget to add JRuby’s source code in the Source tab on this same screen.

Once you’re done, set a breakpoint anywhere in JRuby’s sources and run the newly created configuration.

That’s it! Enjoy!

How do you keep yourself focused?

Filed Under (Productivity, Programming, Tools) by Leonardo Borges on 08-06-2009

Tagged Under : , ,

This is basically a compilation of a few tools/habits that I use to keep focused and at a high level of productivity when working alone. Works great for me and I hope there are useful tips for you as well.

Music
This is one of my favorites. When working alone I hate having noisy people around, which happens quite often if you work in an open office space like me. - It is great for pair programming but I find it inefficient otherwise. Thus, I came up with the term the Heavy Metal effect. Ok, just fit your favorite music genre there but the important thing is that it must act as a barrier to the outside world. It won’t work if you put something new and start babbling the lyrics!
Password Manager
In my day to day I have a number of web sites open like API documents, programming related groups, email… There are also the ones you open a few times a day like the company bug tracker, review board and etc. I find that having a password manager, in my case LastPass, saves a lot of time. The big advantage of it over similar tools like 1Password is that it works on mac, linux or windows. It’s just a firefox plugin.
Multiple Workspaces
Probably the most obvious item on this list to developers but I’s never too much to reinforce it. Multiple workspaces are great. And they are available in whatever platform you happen to be locked in. In my case, I split my environment in at least 3 workspaces:
-Development - where I keep things like my IDE, Browser and Terminal
-Documentation - where I keep API documents, tutorials and related stuff
-Communication - where I have my email, both personal and business, twitter and etc. This allows me to easily set a time per day to do each of my stuff without having noise from things that aren’t important to what I’m focusing in that very moment.
App Launcher
A must! On Mac I use QuickSilver and on Linux, Gnome Do. I won’t say much here. If you don’t use some sort of application launcher, do yourself a favor, stop reading and install one. You have no idea of how comfortable and time saver they are.
Batch tasks
Maybe this wasn’t the best title but I couldn’t think of anything better.
As a result of having a communication workspace that I use a few times a day, I find stuff that I’m interested in but don’t have the time to dig at the moment. So I need a way to queue that and read later when I’m home. The tools of the trade in this case are Twitter + Evernote.
Evernote is roughly a to-do manager. And since they released their Twitter integration it’s been dead easy to queue those things I talked about earlier. Just send a direct message to evernote and the item gets added instantly.

Now, what about you? What works for you?

Coding Dojo #1 - the fun begins

Filed Under (CodingDojo) by Leonardo Borges on 06-06-2009

Tagged Under :

Yesterday I organized our first CodingDojo here at the company and I’m glad to say it was a great success!
The problem chosen was the Karate Chop, from Dave Thomas’ Code Kata.

As it was also my first time organizing a Dojo, we took some time to get things straight, explain everyone the rules and start coding. Nothing that would compromise the experience, though.

The rules were basically the ones of a RandoriKata and as a mechanism for switching pairs we chose the TimeBox with a limit of 5 minutes.

We came up with 3 different solutions in about 1h 30min. The 1st one looking like crap! :)

Which was actually interesting because the general feeling before we started was that it would be boring, or too easy since “everyone” knows what a binary chop/search is.
Wrong!!! It all changes when you have a time limit and a bunch of people behind you doing funny noises! It’s a pressure different from your day to day job. A healthy one in my opinion.

Hearing the feedback afterwards was rewarding. Everyone seemed to have had a lot of fun and can’t wait for the next one.

I guess the most important lesson we got from it was to be quiet and not bother the current pair when we do not agree with their idea - not even if we do. This one is very important as it both shows respect and allows you to learn from how your colleagues think.

Next thursday we’ll keep going with this one and hopefully finish and pick up the next problem! :)

Railswaycon: JRuby Internals by Ola Bini

Filed Under (Conferences, JRuby, Java, Ruby) by Leonardo Borges on 29-05-2009

As always I expected a good talk from Ola and once more he delivered it. But this one was different. It might have been even boring to some ruby developers since we saw a fair amount of java code in this presentation. Ola gave us a tour through the main classes that make JRuby possible with a single purpose: so we can check out the code and hack ourselves. You can download his slides here.

If you’ve been following both JRuby and Ola Bini for the past year or so, you’ve noticed the trend and evolution of this alternative - and so far the most complete one - implementation of the ruby language. Specially at conferences.

Last year at QCon London, Ola was also talking about JRuby. At Euruko ‘08, in Prague, Charles Nutter also talked about it. RailsConf in Berlin also had its share. What all these talks had in common is that they talked about JRuby from a user/developer point of view. They were selling the solution. Convincing people to use it and presenting successful use cases.

And as the trend goes on, JRuby is now faced as a true alternative - one that we, btw, believe here at the company as we’re actively using it - and it seems that now the call is for help. Help to make JRuby an even more complete and overall better ruby implementation. Charles’ call for help was a great step. As he states, it’s a good way to get your feet wet. I answered the call and am hacking JRuby myself, having already submitted a couple of patches. Perhaps this was the reason for which I enjoyed the talk the most. I was already familiar with some of the structure and classes in JRuby.

There were 2 more talks about JRuby: The Pleasure and Pain of Migrating to jRuby, by Steven Bristol and Integrating Enterprise Java with JRuby and Rails, Michael Johann. Unfortunately only the first one was a real case experience, where Steven walked through the problems he faced integrating JRuby with an existing java project. Interesting insights.

Michael Johann basically presented a short tutorial on how to integrate rails with EJB3 which, albeit interesting, failed to address issues faced on real life projects, like dependency management. Issues which we have already addressed in a very cool way here and I plan to share it soon. Still deciding how though…

Rails’ readable test names: run individual tests from the console

Filed Under (Rails, Ruby) by Leonardo Borges on 16-05-2009

Tagged Under : ,

As you probably know, since rails 2.1 you can write test methods in the following format:

test "hotel should return its permalink" do
  #your test code here
end

Which is great, as the test name becomes much more clear. But you can’t simply run this test easily from the command line. You’d have to run something like:

$ ruby your_test_file.rb -n test_hotel_should_return_its_permalink

It annoys me. And it’s not practical either to make the test fail just so you can get the test’s real name.
I wanted to be able to just copy and paste the readable name in the console and have Test::Unit do the conversion and run it for me, like this:

$ ruby your_test_file.rb -n "hotel should return its permalink"

So I created readable_test_names_runner. It’s a tiny rails plugin that adds this feature for you.

Enjoy.

Rcov, JRuby and rcov_plugin

Filed Under (JRuby, Rails, Testing) by Leonardo Borges on 05-05-2009

Tagged Under : , ,

The rcov_plugin project is a rails plugin for rcov that adds some useful rake tasks to your application.  And since I’m currently working in a JRuby project it made sense to use this plugin.

The thing is, among other stuff, an rcov report from a JRuby project includes some files that shouldn’t be there at all, plus you also need to change the way you call rcov as such. Thus, I thought I’d contribute these changes to the plugin and my pull request was approved this morning - just install the latest version and you should be good to go.

It was useful for us here, hope it might be useful for you too.

Enjoy :)

Git cheat sheet

Filed Under (Git) by Leonardo Borges on 22-04-2009

Tagged Under :

For those who don’t know Git is a version control system developed by Linus Torvalds. It’s main difference from other tools like SVN and CVS is the fact that it’s distributed.

Recently I gave a workshop about Git here at the company where I walked through the most common cases I usually see when working in a team and thought about posting a summary of the commands used in the workshop.

It turns out that just this morning I found this - a.k.a the rest of my post. It’s a really nice and concise Git Cheat Sheet that covers most of what I talked about  in the workshop. So I highly recommend you bookmark it. It will certainly be useful.

JRuby on Rails and Google App Engine

Filed Under (JRuby, Java, Rails) by Leonardo Borges on 10-04-2009

Tagged Under : , ,

As many of you know the new language supported at GAE now is Java, as officially announced on their blog. As a Ruby/Rails developer you might not be interested on it but here is a reason you should be: JRuby.

It was only a matter of time until we saw some people deploying JRuby on Rails apps on GAE, like Ola Bini’s mini blog app. Guess that was the first one really, as he was beta testing the service in secret. Google App Engine imposes a few catches to any java application deployed there and any JRuby app wouldn’t be different. For instance, your Java API access is limited to these classes - called JRE Class whitelist.

As you can see on his blog, you don’t need active record and in fact shouldn’t even be loading that on your app.

I felt compelled to try it and the timing was perfect. I am currently developing a JRuby on Rails app at the company I work for and it was a perfect fit, since we are not using ActiveRecord. The reason is that we get the data we need from other sources, such as web services and even text files.

Ola Bini’s tips were crucial here. He provides a small script you can use to prepare the jars you’re sending to your app. Another important piece was the Google App Engine SDK for Java. It ships with a server that emulates GAE’s behaviour locally so you’re less likely to have problems once you deploy it.

I did have a problem though with the number of files uploaded to my appspot. It’s currently limited to 1000 - a thousand - and a Rails app can easily exceed this limit. So before deploying, remove anything that is not crucial: activerecord - you should’ve done it already - , all tests directories - including the ones inside gems your app needs in order to work, fixtures and etc.

After that it was rewarding seeing a custom JRuby On Rails application working perfectly on GAE. And as much as I’d like to, I can’t really share the URL since it’s a private app but I encourage people to try it. I believe GAE will ultimately help the community improve JRuby even more.

And as a last tip, this time thanks to Fabio Akita, is this snippet. You should redirect your log so you can debug your app form GAE’s dashboard.

Have fun!