Archive for the ‘development’ Category

Deploying a Merb app on Glassfish with Capistrano

Thursday, December 4th, 2008

A lot shorter than the last post with a lot less weirdness.

I have traditionally (can you say that for something you’ve used barely a year?) used Capistrano to deploy my Rails applications. Most of the time to a pack of Mongrel but lately all Phusion Passenger. So the natural thing to do when looking to deploy a Merb app into production was dusting of Capistrano.

Long story short, my deploy.rb file( (without all the usual stuff):

set :warfile_name, "calculator"

role :app, "85.17.94.1"
role :web, "85.17.94.1"
role :db, "85.17.94.1", :primary => true

namespace :deploy do
desc "Create WAR file after deploy and deploy that WAR file"
task :after_update_code do
run "cd #{release_path}/ && MERB_ENV=production warble"
end

task :stop do
run "/usr/local/glassfishv3-prelude/bin/asadmin undeploy #{warfile_name}"
end

task :start do
run "/usr/local/glassfishv3-prelude/bin/asadmin deploy --contextroot / #{release_path}/#{warfile_name}.war"
end

task :restart do
run "/usr/local/glassfishv3-prelude/bin/asadmin redeploy --name #{warfile_name} #{release_path}/#{warfile_name}.war"
end
end

Many thanks to the BrightLight blog for providing the initial inspiration.

Note the explicit MERB_ENV environment variable, this makes sure that, well you guessed it, build the WAR file with the production config file. The remainder is stupidly easy once you have figured it out.

There was one thing which threw a spanner in the works. When I was testing with (re)deploying etc I ran into a nasty ‘Permgen space’ Java error. I still hardly know what it does but apparently if you start your Glassfish server with the switch ‘-XX:MaxPermSize=256m’ everything should work fine again. No guarantees.

Glassfish v3 with Merb and Warbler

Wednesday, December 3rd, 2008

It’s been a looong time but this I want to share with you.
For a project I’m currently working on we needed something really really fast. Rails with Ruby MRI was out of the question so we went for JRuby and Merb. This particular piece of the project is ideally suited for Merb as we are using it as a backend system (webservice) only.

So you want JRuby because it is blazingly fast (at least compared to MRI)? Fine. But how to deploy the bugger? We quickly decided on Glassfish an open source application server made and maintained by Sun. Moreover this lovely server had a gem which you can use to fire up a Glassfish server. Easy as pie and within no time at all we were developing our Merb app on Glassfish.

I was charged with the task to deploy the app to the server and that’s when the trouble began. First off I installed JRuby 1.1.5 (in /usr/local/jruby) and installed the Glassfish gem (v0.9.0). I had no idea how to monitor and fire up the gem but that was for later. Installed the glassfish and merb-core (!) gem ($ jruby -S gem install glassfish merb-core). Don’t install Merb! This won’t work as it depends on a gem which tries to build native extensions.

Still manually copying over the source of our app I ran the glassfish command only to be greeted with an Activator error. Took me a while to figure out but this appears to be a proper bug. The maintainer is aware of the issue and will fix it in the 0.9.1 release of the gem. No good for me so onward.

If the gem doesn’t work than the true Glassfish server might do the trick. I come from a Java background but have been developing Rails/Ruby now for over a year and I quite forgot how incredibly verbose the Java world is. After reading for an odd couple of hours or so. I went for the installer of the Glassfish v3 prelude. The v3 release does not require you to package up your app in a WAR file which sounded very good. Unfortunately the installer died with some unclear error messages and I just downloaded the zip and unpacked it in /usr/local/glassfish.

More dark clouds ahead! I have no idea how this stuff works and although there are a couple of Rails examples non worked for our Merb app. :S Starting the server with jruby was already a challenge, in the end

java -J-server -Xmx256m -Djruby.home=/usr/local/jruby-1.1.5/ -jar /usr/local/glassfishv3-prelude/glassfish/modules/glassfish.jar

did the trick. But how to get Glassfish to accept my ‘exploded’ (eg non WAR/EAR) Merb app? I still have no idea. Enter Warbler.

This charming little gem turns a Rails, Merb or Rack app into a WAR file ready to be deployed. I’ll leave out all the errors and just to it. First off edit the config.rb file of the warbler gem (found in /usr/local/jruby-1.1.5/lib/ruby/gems/1.8/gems/warbler-0.9.11/lib/warbler/), got to the auto_detect_merb method and change the line:

@gems[”merb”] = Merb::VERSION

to:

@gems[”merb-core”] = Merb::VERSION

This will enable warbler to find the correct gem. Installing the gem ‘merb’ was not an option for JRuby!

Second edit the merb-core gemspec (found in /usr/local/jruby-1.1.5/lib/ruby/gems/1.8/specifications) and find all references to webrat and remove them. Webrat depends on Nokogiri which in turn has native dependencies… etc etc.

Third replace the jruby and jruby-rack version in /usr/local/jruby-1.1.5/lib/ruby/gems/1.8/gems/warbler-0.9.11/lib with the hottest flavours (JRuby-Rack: http://kenai.com/downloads/jruby-rack/, JRuby: http://dist.codehaus.org/jruby/)

We are now ready for WAR.

Config the war file!

$ jruby -S warble config

Edit the config/warble.rb file. Remove the ‘vendor’ and ‘tmp’ directory from the config.dirs directive. LEAVE all references to config.gem alone. This does not work as expected config.gem -= “rails” does not remove the rails dependency. On the contrary. The config.webxml.booter needs to say :merb. Save-close-etc.

Create the war file!

$ jruby -S warble war

Tell the now running Glassfish server to deploy it with

$ /urs/local/glassfish/bin/asadmin deploy your_app.war

The server is running on port localhost:8080/your_app
May this help.

Configuring Cruisecontrol, Git and RSpec

Tuesday, May 13th, 2008

The realization we needed a continuous integration server sank in good last week when work on our internal project really got started. The project has seen quite some development in the past, mainly when my skills in (RSpec) testing where, uhm, less than optimal. This on top of some high pressure hacking left the project in a pretty shabby shape. We are now working on it with three people and we’d like to introduce a bit more rigour in our development process.

One of the first steps was to use a continuous integration server. I was actually surprised so few existed and the choice for CruiseControl(CC) was a quick one. This pretty piece of software did not support Git out of the box but there exists a GitHub branch incorporating this functionality. What is even better is this post which explains how to use it! So I won’t go into the nitty gritty details, what I will do is point out some pit falls and how to make CruiseControl play nice with RSpec. Which it also does not support out of the box but which is really easy.

Install CC as per previously mentioned post. What threw me off where the site_config.rb and the cruise_config.rb I got the (wrong) impression that these files lived in the root directory of the CC install. This is not the case. When installing CC it, by default, creates a directory ~/.cruise which holds your projects. It is here where the site_config.rb file lives. And this is the file to configure ActionMailer! And in the directory ~/.cruise/projects/MyProject the other file can be found in which to configure the people who need to receive emails when the build breaks.

When CC builds a project it just runs some Rake tasks, one of which is cruise. Getting CC to use RSpec is as simple a overwriting this task! This is what I gleaned from other posts:


desc "Task to do some preparations for CruiseControl"
task :prepare do
RAILS_ENV = 'test'
end

desc "Task for CruiseControl.rb, automatically picked up"
task :cruise => [:prepare, "db:migrate", "spec"] do

end

The first task is to make sure the test environment is used which is really what you want in a situation like this.

The next step would be to produce something more readable than the dump of the log file with the results of the ran RSpecs.