Monday Apr 30, 2007

Ruby on Rails meets GlassFish High Availability

One of the key features of GlassFish v2 release is its cluster support. Various GlassFish server instances can be grouped together to form a single virtual entity - a cluster. One of the salient services offered via clustering is high availability, which is implemented as in-memory replication of state across participating server instances.

Since, I've been looking at getting Ruby on Rails applications running as web applications in a Java EE container, I was asked a couple of weeks ago if RoR applications could run in a GlassFish cluster. Well, with Rails-Integration 1.1.1, you can ! Its relatively straightforward to enable failover support for a web application in GlassFish and is no different for RoR (as a web application). The hard part, or so it seems at first, is setting up the GlassFish cluster.

For the easy part first, the only changes needed to enable failover session support for a web application are :

  • The deployment descriptor, web.xml, needs a marking distributable element - <distributable/>
  • Enable the high availability flag during deployment. For command line, this would be of the form
    ${GLASSFISH_HOME}/bin/asadmin deploy --target ${CLUSTER_NAME} --availabilityenabled=true ${path-to-war-file}

One important fact that I learned during this process, was that a load balancer facade is not necessarily needed for development/testing scenario. In other words if server instances, that share application state, are listening on the same host (different port), then failover can be simulated by simply sending requests to the other node (port).
Now, the part about setting up a GlassFish cluster. The references below give detailed information about the clustering architecture and setup steps but the takeaway is a lot simpler.

  • Download GlassFish v2 from
  • java -Xmx256m -jar ${GLASSFISH-v2.jar downloaded above}
  • cd glassfish; ant -f setup-cluster.xml

  • {GLASSFISH_HOME}/bin/asadmin start-domain ${domain-name} // ${domain-name} typically is 'domain1'

  • cd ${GLASSFISH_HOME}/samples/quickstart/clusterjsp/
  • ${GLASSFISH_HOME}/bin/asant setup-one-machine-cluster
  • ${GLASSFISH_HOME}/bin/asant start_cluster // stop_cluster to stop
  • (The last 2 steps will create a cluster named 'cluster1' with two instances, instance-ONE and instance-TWO listening for HTTP requests on port 1110 and 1111 respectively. Of course, you could do the same(creating/starting/stopping) via the asadmin command options like '(create|start|stop)-(cluster|instance|node-agent)', but it's a lot easier to get started via the clusterjsp sample)
That's all there is to it !


Tuesday Apr 24, 2007

Rails-Integration 1.1.1

rails-integration 1.1.1 has just been released !
Source and binaries can be downloaded from
rails-integration details can be found at

The fundamental change in this release as compared to 1.0, is performance and compatibility. When used in standalone mode, rails-integration 1.0 had this hack wherein it performed installation of JRuby and the rails libraries at runtime (during web application initialization i.e., once per web container process lifetime). Not only was this ugly, but it also caused compatibility problems with GlassFish since it expected the web application constituents after deployment (implementation dependent)in a particular format. No runtime installation needed with 1.1.1 !
Aiding to the performance improvements is JRuby 0.9.9 which has made great strides in improving performance as compared to its previous versions.
Also, this release is compatible with rails 1.2.x, solves session related and other issues that plagued 1.0.

All in all, a great release that blends the two architectures - RoR and Java EE - giving you the best of both worlds - the development convenience of RoR and the enterprise level features of the Java EE platform. No longer do you have to pick and choose one !

Many thanks to all the folks involved in getting the release out !

Friday Mar 16, 2007

JRuby and Rails - status

JRuby 0.9.8 is out and so is rails-integration 1.0. Rails 1.2.x has been out for a couple of months and there's a new release of ActiveRecord-JDBC 0.2.3. The good news is that JRuby 0.9.8 is lot more Rails compatible than ever before.

For GlassFish users this means:

  • For RoR deployed as a WAR - only the shared mode works. Therefore, instead of running that standalone rake task you should run 'rake war:shared:create'. You need to have the JRUBY_HOME enviroment variable set and a jruby/rails installation.
  • For RoR deployed directly on Grizzly, things seem to have regressed. Hopefully, we'll get the fixes real soon but there are workarounds and if you're interested email me at ashish dot sahni at sun dot com
Stay tuned ...

Wednesday Feb 21, 2007

RoR with Embedded Derby

I got a request on trying to figure out how to get a RoR application working with Embedded Derby. And even though it's pretty straightforward it took me a couple of hours, so maybe the details below will save you some time.

The starting point would be to modify the RoR configuration in database.yml to look something like

    driver: org.apache.derby.jdbc.EmbeddedDriver
    url:    jdbc:derby:${database-name}

The Apache Derby database data files persists in the directory defined by 'derby.system.home'. And if this system property is not explicitly defined, the current working directory defaults as the property value. Surprisingly, in my case I could not locate the database files in the working directory used to start the database process. Well, it so happens that the derby isn't very user friendly in it's spewing error messages(at least not version Even though on startup the server would emit 'Server is ready to accept connections on port 1527', it was not the process serving client requests(though I suspect it has got something to do with network interface bindings). There was another long running Derby process which was actually responsible for servicing the requests and its 'derby.system.home' will forever remain a mystery. After killing the long running process I was able to give a meaningful value to derby.system.home

For the RoR application running as a WAR in GlassFish, I made the following modification to domain configuration

   <java-config ...
     <jvm-options&rt; -Dderby.system.home=/my/value/of/derby/system/home <jvm-options>

Last but not the least, the Derby database process probably has some kind of an locking mechanism so that multiple processes do not step over each other. So, it means something like this - one process per database. You can use either the embedded or network mode Derby to serve you data from 'the' database.

Thursday Feb 15, 2007

RoRaWAR - A War Roar ?

No, it's not a war roar. This is not a current world affairs blog ;)

RoRaWAR stands for Ruby on Rails as Web ARchive.

The rails integration (under the jruby-extras umbrella) project's purpose is to WAR'up a RoR application. And it's great to see how far the project has come along since its inception a few months ago !

The creation of a web archive from a RoR application is as simple as

  • svn checkout svn:// rails-integration
  • cd rails-integration; mvn install;

  • the couple of steps above are one time only

  • cp -R <rails-integrations>/plugins/war <rails-app-dir>/vendor/plugins/
    cp -R <rails-integrations>/plugins/war-snapshot/\* <rails-app-dir>/vendor/plugins/war
  • cd <rails-app-dir>; rake war:standalone:create or rake war:shared:create ;
    #standalone mode will archive the rails framework libraries whereas the shared mode will not
It's as simple as that !

Note: There are a few implied dependencies here - JRuby, maven2, rails framework libraries. Also, since the rails-integration project is trying to utilize the latest and greatest JRuby releases, you might have to install the jruby.jar into maven2 repository via the maven install:install-file command. Eventually, the first couple of steps will not be needed once the rails-integration libraries are downloadable as a binary release, but until then ...

Wednesday Jan 24, 2007

Grizzlicious ... Part II

Part I described how to get a RoR application working on GlassFish. However, if you want something lightweight for development only or do not want anything to do with configuration changes(which btw, will only get simpler) or any other reason, read on ...

The elegant design of Grizzly allows you to write just a few lines of code and have a custom HTTP server suited to your specific requirements. The rails module does just that for primarily running a RoR application. This is how:

  1. Download rails-module-0.1-SNAPSHOT.jar
  2. The latest Grizzly binaries
  3. And of course, the JRuby binaries, Rails framework libraries and database specific JDBC drivers. For JRuby, I recommend working with the current trunk version as there are issues with the 0.9.2 release and the rails-module. Copy plaincharset.jar(in ${JRUBY_HOME}/lib) to jre/lib/ext of your Java runtime. For installing the Rails framework including activerecord-jdbc see steps #3 and #4. Use the flags(--no-rdoc --no-ri) for faster gem installation.

    Steps 1,2 and 3 are one time only.

  4. Create the Rails applications. Perform the following edits
    • Database related configuration edits - db config and step #8 here
    • In config/development.rb set config.breakpoint_server to false. See JRuby issue for more details.
  5. That's it ! Run it as something like
    # set the CLASSPATH variable to include
    # rails-module, grizzly, JDBC driver, 
    # JRuby libs(jruby.jar, jvyaml, asm, jline and jruby-openssl)
    java -classpath ${CLASSPATH} -Djruby.base=${JRUBY_HOME}
        com.sun.grizzly.rails.standalone.Main ${RAILS_ROOT}
    Or download the script and modify it to run in your environment.

Friday Jan 19, 2007

Grizzlicious ... RoR on GlassFish

In some of the previous episodes, I described how to go about deploying a Ruby on Rails(RoR) application on GlassFish. The first post described the method of deployment in which the RoR application is packaged as a WAR file, whereas the later posts(here and here) utilized the native Ruby interpreter at runtime(RoR-as-WAR runs on JRuby).

However, both deployment models are not quite ideal for a production deployment scenario. Enter Grizzly ! The NIO based HTTP connector for GlassFish. The beauty of Grizzly is not only that it's fast and scalable but that it is also highly extensible. TAKAI Naoto was quick to realize this fact and quickly dished out the first version of the adapter code needed to deploy RoR applications directly on top of Grizzly.

Without further ado, the steps to get a RoR application working as a first-class citizen within GlassFish:

  1. Download and install GlassFish in ${GLASSFISH_HOME}
  2. Download rails-module-0.1-SNAPSHOT.jar to ${GLASSFISH_HOME}/lib
  3. Checkout the latest source of JRuby and build it.
    Copy jruby.jar jvyaml.jar and asm-2.2.2.jar and to ${GLASSFISH_HOME}/lib
  4. Copy plaincharset.jar(in ${JRUBY_HOME}/lib) to jre/lib/ext of your Java runtime installation.
  5. Install the rails libraries including activerecord-jdbc. See step #3, #4 .
  6. The rails applications should installed under ${GLASSFISH_HOME}/domains/${domain-name}/applications/rails and you still need to do edits to get jdbc adapter working with JRuby. See steps #7 and #8 from the previous post
  7. Modify GlassFish configuration (which persists in ${GLASSFISH_HOME}/domains/${domain-name}/config/domain.xml - you could use the great administration UI - typically available at port 4848 via the browser or the command line interface to perform the changes) as below.
    • Add RoR specific http listener
          <http-listener acceptor-threads="1" address="" 
                blocking-enabled="false" default-virtual-server="server" enabled="true" 
                family="inet" id="http-listener-rails" port="8081"
                security-enabled="false" server-name="" xpowered-by="true">
              <property name="selectorThreadImpl" value="com.sun.grizzly.rails.RailsSelectorThread"/>
    • To the java-config add the system property 'jruby.base'
  8. Modify $GLASSFISH_HOME}/domains/${domain-name}/applications/rails/config/environments/development.rb by setting the property config.breakpoint_server to false. Once issue #427 in JRuby is fixed this step will not be needed.
Give it a shot !

Monday Jan 08, 2007

Derby's Identity column trivia

In a previous post, I described the SQL command to create a table with an auto increment column in the Derby database. It turns out that the 'GENERATED' keyword can be used in a couple of way.
For details see the relevant section of the Derby manual here. Essentially the distinguishing fact being - by using 'BY DEFAULT' the user has the ability to specify a value for the identity column as part of a (insert) SQL statement, whereas with 'ALWAYS', the column can never be explicitly edited by the user. Also 'ALWAYS' guarantees uniqueness, but 'BY DEFAULT' does not (use the UNIQUE/PRIMARY KEY attribute to achieve the same effect though)

So, the better suited SQL statement for creating a table in Derby in a RoR application would be

CREATE TABLE ${table-name} ( 
    ${other-columns-and-constraints} )
Running a simple RoR application with the underlying identifier created via either option works without any issues. However, if you want to run the tests that comes in built with Rails framework the difference is detrimental (since the test framework seems to explicitly want to insert a value for the identifier column).

Friday Dec 15, 2006

GlassFish and Ruby

GlassFish and JRuby are obviously a great match, since both run on the Java virtual machine which allows Ruby code running on JRuby to access Java framework and libraries and the possibilities are endless.

However, GlassFish is also capable of running Ruby code via a native Ruby interpreter. This is possible using CGI support in GlassFish. For this first post, I shall keep things simple and demonstrate how you could go about dedicating an entire instance of the GlassFish server for a single RoR application

All you'll need is to install GlassFish v2 build 29 or greater, the native Ruby interpreter with the Rails framework libraries and make some minor modifications to GlassFish configuration. Of course, you'll need to create your rails application. The minor modifications amount to modifying ${glassfish.home}/domains/${domain-name}/config/default-web.xml with the following CGI configuration enabled.

          <!-- in this case the path will be appended to
               ${glassfish.home}/domains/${domain-name}/docroot/ -->


On UNIX make sure that the native Ruby interpreter is in the PATH and LD_LIBRARY_PATH is set to satisfy the native Ruby interpreter's/Rails dependencies in the GlassFish process's environment. This is the reason for configuring the 'passShellEnvironment' parameter to true.

That's pretty much all there is to it. Accessing http://${host}:${port}/ should bring up the default Rails page !

Friday Dec 01, 2006

Deploying a Ruby on Rails application in GlassFish

There are a few ways a Ruby on Rails(RoR) application could be deployed on a Java EE based application server platform. One of them is to create a WAR file containing the RoR application with the appropriate adapter code between the application server and the ruby application. On how to go about developing and deploying a RoR application on GlassFish - an open source Java EE 5 application server - follow the steps below:

1. Install GlassFish application server
2. Install JRuby
3. Install Rails Framework 'gems install rails -y' (if behind a http proxy, set HTTP_PROXY=http://${http-proxy-host}:${http-proxy-port}/)
4. Install activerecord-jdbc 'gems install activerecord-jdbc'
5. Install database/jdbc driver (for mysql
6. Generate your Ruby on Rails application (
7. Modify database.yaml
           adapter: jdbc
           driver: com.mysql.jdbc.Driver (for mysql)
           url: jdbc:mysql://${database-hostname}/${db-schema}
           username: ${username}
           password: ${password}
8. Modify environment.rb by adding
       require 'active_record/connection_adapters/jdbc_adapter'
9. Download rails-integration-${version}-SNAPSHOT.jar into the WEB-INF/lib by checking out and building the rails-integration project
10. Modify the template web.xml(see references below) with the right value of jruby.home
11. Create a WEB-INF directory in the RoR application directory
12. Copy web.xml to WEB-INF and rails-integration-${version}-SNAPSHOT.jar under WEB-INF/lib
13. Jar up the RoR application directory contents as a WAR file

Requests to appropriate context-root of the deployed web application should invoke your Ruby code !

If you'd like to automate the building of a war file:
Edit rails-integration/build.xml and add the following XML snippet
  <property environment="env"/>
  <target name="build-rails-war" depends="jar">
    <delete file="${rails-app-dir}/${rails-app-name}.war"/>
    <mkdir dir="${rails-app-dir}/WEB-INF/lib"/>
    <copy todir="${rails-app-dir}/WEB-INF/lib">
      <fileset file="${}/${}.jar"/>
      <fileset file="${maven.repo.local}/org/jruby/jruby/0.9.1/jruby-0.9.1.jar"/>
      <fileset file="${maven.repo.local}/asm/asm/2.2.2/asm-2.2.2.jar"/>
      <fileset file="${maven.repo.local}/javax/activation/activation/1.1/activation-1.1.jar"/>
    <copy todir="${rails-app-dir}/WEB-INF/">
      <fileset file="samples/scaffold/WEB-INF/web.xml"/>
    <replace file="${rails-app-dir}/WEB-INF/web.xml" token="/usr/local/jruby" value="${env.JRUBY_HOME}"/>
    <jar jarfile="${rails-app-dir}/${rails-app-name}.war" basedir="${rails-app-dir}"/>

Make sure JRUBY_HOME is set and run
'ant -Drails-app-dir=${ror-app-dir} -Drails-app-name=${war-file-name} build-rails-war'
${ror-app-dir}/${ror-app-name}.war should be ready for deployment !

All of this is work in progress some of this might change very soon. Thanks to rail-integration developers and the jruby folks !



« July 2016