Redmine is a web based project management app written in Ruby on Rails. We wanted to use this app at work, but we are a closed Windows shop. I explored several avenues in order to make this work on Windows Server 2003 easily without a huge Apache + pack of Mongrels setup, and ended up using Java, JRuby and the Glassfish Gem.
JRuby is an implementation of Ruby that runs in the Java VM. Glassfish is Sun’s open source application server. Glassfish Gem is just the lightweight core of the Glassfish server, all nicely packed up into a Ruby ‘gem’. Put all the pieces together and you have a nicely scalable and manageable little one-stop shop dedicated to running Redmine.
Initially I struggled a bit, until Arun Gupta from Sun picked up on my twitterings and sent me a great set of up to date instructions. I basically followed those instructions, and with a couple of extra steps (setting up a dedicated JRE, keeping everything contained in one directory). Here’s a brief summary of the steps of what I did.
- Created
E:\Applications\jredmine. This is the directory in which I want to keep everything self-contained. The JRE, JRuby and the Redmine files themselves will all live under here.
- Copied JRE 6.0 into
E:\Applications\jredmine\jre. I got this by installing the JDK on my machine, and grabbing the C\:Program Files\Java\jdk_1.6.xx\jre directory
- Set my
JAVA_HOME with SET JAVA_HOME=E:\Applications\jredmine\jre
- Downloaded and unzipped JRuby into
E:\Applications\jredmine\jruby-1.2.0
- Installed the Glassfish gem:
jruby-1.2.0\bin\jruby -S gem install glassfish
- Downloaded and unzipped Redmine into
E:\Applications\jredmine\redmine
- Changed Redmine’s
configdatabase.yml production to point to the MySQL server. I also created the database and the database username and password here.
- Changed Redmine’s
configemail.yml production to point to the SMTP server.
- Jumped into the redmine directory and executed
..\jruby-1.2.0\bin\jruby -S rake db:migrate RAILS_ENV="production" to create the tables in the database
- Executed
..\jruby-1.2.0\bin\jruby –S rake redmine:load_default_data RAILS_ENV="production" to load the database tables with the defaults.
- Tested the app by executing
..\jruby-1.2.0\bin\jruby -S glassfish -e production, waited 60 seconds or so to let things settle down and verified that it works, and that I could login with admin:admin.
Everything worked fantastic: the application was fast and was contained in one java.exe process. The next step: setting it up as a Windows service so that it can run without a user being logged into the box, and starts up whenever the box restarts.
I used the Windows Service Wrapper available from http://kenai.com/projects/winsw/. It’s a simple .NET service that executes whatever you want. It’s easily configurable with a simple XML file.
I threw the executable into E:\Applications\jredmine and renamed it to jredmine-svc.exe. I created jredmine-svc.xml and filled it with:
<service>
<id>jredmine</id>
<name>JRedmine</name>
<description>Redmine running under Glassfish gem</description>
<executable>%BASE%jruby-1.2.0binjruby.bat</executable>
<arguments>--server -J-Xrs -S glassfish %BASE%redmine -e production</arguments>
<env name="JAVA_HOME" value="%BASE%jre" />
</service>
The BASE environment variable contains the path of the service wrapper executable, and is automatically populated by the service wrapper.
Also note the arguments I pass. --server tells Java to use the VM optimised for server use. I’m not 100% sure what’s different, except it takes a bit longer to startup. I’ll trust Sun on that one
. -J-Xrs is an argument that is passed to the Java VM, which tells it to ignore some signals from the operating system, in particular, when the user logs out. We don’t want to shut down the Java VM when someone logs out of the box. All the other arguments are the same as before.
I then installed the service with jredmine-svc install, then started it with jredmine-svc start. This is asynchronous, so you should wait 60 seconds or so before trying to visit the page in your browser. If all goes well, you should get the Redmine home page!
Now, there is a rather large fly in the ointment here. When you stop the service, the service wrapper doesn’t stop the Java VM. I suspect that this is because the wrapper stores the process ID of the batch file used to start JRuby, not the Java VM itself. It’s not a showstopper for me; I just make sure I run taskkill /F /IM java.exe when I shut down the service. Also note that the Java VM does shut down automatically when you reboot or shutdown the machine.
So now I have a great project tracking system running in a solid Java VM, multi threaded and multi process as needed, inside a system service, inside one directory.
There are a couple of improvements I’d like to tackle at some point. Obviously the first is making the service stop the Java VM itself. Rather than firing off the batch file, I could possibly start the Java VM with JRuby directly.
I’d also like to investigate swapping out the mysql driver with a native JDBC driver to take advantage of performance improvements and connection pooling.
I’d also like to get it proxied through IIS, although this really isn’t a big deal.
Overall, I’m very happy with the Java + JRuby + Glassfish combo. If you’re in an environment where you can’t set up a full Apache + pack of Mongrels, or you’d rather use the tried and tested Java VM, give it a shot!