July 26, 2008

Tips and tricks to deploy JRuby apps onto heavy J2EE containers

This is a list of things to note when developing Rails/JRuby applications that will be deployed to java web containers such as Tomcat, WebSphere et alli. It's obviously incomplete but it is much longer than I thought it would be when I first started.
  • RAILS_ROOT becomes the context therefore your traditional Rails folders aren't where you'd expect them to be. In a java container the public area is usually context's root. Warbler helps be copying the files from the application's Rails public folder and you can also modify how it packs the app by changing the entries in warbler.rb.
  • Rails caching usually depends on where public files are and things tend to go bezerk unless you set where the public folder lives. So, place this in your environment.rb: Rails.public_path="#{RAILS_ROOT}/.."
  • Try to stick to one interpreter only. It's quite confusing managing dependencies and versions when having too many rubys installed, and it's very easy to end up with:
  1. the IDE's JRuby
  2. the JRuby you installed
  3. the JRuby that comes with warbler
  4. the C-ruby install
  • Assuming the app will run in JRuby prefer NOT to use a C-ruby interpreter at all, not even in development. This doesn't necessarily means giving up Mongrel/Webrick. Java containers won't refresh changes to view files so it is very handy to use Mongrel/Webrick for the minor css/html changes, otherwise you'll loose rails quick feedback cycle.
  • Make sure that the version you're developing in is the same the app will be running when in production.
  • Don't use warbler's (v. 0.9.9) JRuby version (1.1.1) it will most certainly cause you grief. Delete it from the installed GEM and get the latest jruby-complete.jar, then place it in the lib directory so warbler picks it up when packing the war.
  • Check config.webxml.rails.env in warble.rb to make sure the warbled app is configured with the environment you want it to be. This variable creates an entry in the generated web.xml that defines which RAILS_ENV will be executed.
  • JDBC adapters seem to be a problem still. When running RSpec the test environment crashes because recreate-database method isn't implemented yet. It seems that Derby is the only one fully implemented.
  • Gems dependencies (Rails 2.1) aren't working properly. It seems that it has issues with java gems. I failed to install/unpack hpricot and activerecord-jdbc. So use other ways to freeze gems into the project. Don't forget to use config.load_paths to tell where the gems are in relation to the app in the java container.
  • Deploy as frequently as possible to the target java container to avoid surprises. I can assure you that there will bad surprises if you don't do it.
  • Autotest (ZenTest) doesn't seem to like the script/spec command. A cheap way to overcome this is to create a softlink called script in JRuby's bin directory that points to the bin directory itself.
  • I'm using H2 (file based) in development and it is a cool database but there is one annoyance in Windows. Windows locks H2 log file even if the connection is explicitly saying that it shouldn't - url: jdbc:h2:file:db/development;FILE_LOCK=NO. In Linux/MacOS it behaves properly.
  • JNDI resources are available for databases only, if you need to grab a hold of other JNDI resources some code has to be cooked to do the lookup. I wrote this very simple JNDI adapter.
  • Let database adapters do their jobs, it's a little more code but it guarantees you won't run into type conversion problems. For instance:
  1. GOOD -> Person.find_by_name name, :conditions => ["alive = :breathing", {:breathing => true}]
  2. BAD -> Person.find_by_name name, :conditions => ["alive = true"]
  • Use Exception Notification. It provides a very nice snapshot of the state of affairs and you'll need it.
  • Use HAML, it really makes things simpler. This not a JRuby thing but a still a good recommendation.
  • Pay attention to links. Strive to use rails resolvers to create links and urls, as traditionally, in a java container you'll usually have a context. In regular rails it looks like this: http://localhost:3000/persons and in java-land most likely this: http://localhost:8080/appName/persons
  • Netbeans 6.1 made me smile after frustrated weeks using Aptana and E. I know IDE's are religious war starters but this is my take on it. Netbeans works the others don't.
  • If possible prefer NOT to develop in Windows, especially because it is definitely much slower. If you must use Cygwin. BTW there is this cool tool called Terminator, it keeps all terminals together in tabs.
  • I had problems making controllers see some modules. More specifically cache sweeping. In my controller I had to add these 2 lines, or it doesn't work:
  1. require File.expand_path("#{RAILS_ROOT}/vendor/rails/actionpack/lib/action_controller/caching/sweeping") unless defined? cache_sweeper
  2. include ActionController::Caching unless defined? cache_sweeper
  • Protect from forgery has problems with WebSphere. It always complains about the generated tokens not been compatible. Is any one using it?

No comments:

Post a Comment