Rails Powered by the GlassFish Application Server

   
By Arun Gupta and Rick Palkovic, March 2008  
  This article introduces JRuby, JRuby on Rails, and the GlassFish application server. It presents a traditional Ruby-on-Rails application deployment, describes an alternative using the GlassFish application server, and explains the various options for deploying JRuby applications on GlassFish.  

Many developers see the GlassFish application server as the superior solution for developing and deploying JRuby-on-Rails applications chiefly due to the following advantages:

  • You can develop in the same environment in which you deploy.
  • You can deploy multiple applications in a GlassFish instance that is already running.
  • GlassFish can handle multiple requests by maintaining JRuby runtimes and database connections in pools.
  • Clustering and high availability are integrated into GlassFish v2.
  • GlassFish leverages existing investment in the Java Platform, Enterprise Edition (Java EE) while hosting JRuby-on-Rails applications in the same environment.
 
Contents

About Ruby and JRuby
About Rails
About the GlassFish Application Server
Deploying JRuby-on-Rails Applications on the GlassFish Application Server
Advantages of JRuby-on-Rails With the GlassFish Application Server
Example Project
Summary
Links in This Article
For More Information

About Ruby and JRuby

JRuby is a 100% pure-Java technology implementation of the Ruby programming language. JRuby combines the libraries and power of the Java platform with the simplicity and productivity of Ruby.

You can download the JRuby runtime at no cost. It requires JDK version 1.4 or later, which you can also download at no cost.

Here is a trivial example that shows how to mix Ruby and Java technologies and how to invoke them by using JRuby:

# Give access to bundled Java libraries.
include Java

# Create a Java Frame.
frame = javax.swing.JFrame.new "JRuby Demo"

# Add a label to Frame.
label = javax.swing.JLabel.new "Hello JRuby World!"

# Call Java methods as if they were defined in Ruby.
frame.content_pane.add label
frame.default_close_operation = javax.swing.JFrame::EXIT_ON_CLOSE
frame.set_size 200, 100
frame.visible = true
 

If you save this code in a file named hello.rb, you can run it as a JRuby program with the following command:

jruby hello.rb
 

This code opens a window like the one shown in Figure 1.

Figure 1. Hello Application Output
 

You can easily run any pure Ruby application by invoking the JRuby runtime from the command line as just described. You don't need to know any Java syntax in order to run your Ruby applications using the JRuby runtime.

The advantage of using JRuby is that your Ruby code can be embedded into any Java technology-based application with full two-way access between the Java and Ruby code. The specification that enables you to invoke Ruby code from within a Java application is JSR 223: Scripting for the Java Platform.

Using JRuby instead of Ruby provides the following key advantages:

  • A vast number of Java libraries are accessible to Ruby programs through the JRuby interpreter.
  • JRuby supports Java Unicode strings. Ruby and Java strings go back and forth safely.
  • Ruby 1.x uses green threads to implement the language-threading libraries. JRuby uses Java threads, which map to native Ruby threads. As a result, JRuby can spin off multiple threads easily. Moreover, these threads can be easily pooled.
  • JRuby enables easy adoption of Ruby in enterprise environments where Java technology is already prominent.

At this writing, version 1.0.3 is the stable release of JRuby. A release candidate of version 1.1, the next scheduled release, is available for download.

The core functionality of Ruby or JRuby can be extended by Ruby gems. A gem is a packaged Ruby application that uses a predefined packaging system. For example, Rails is a gem that can be installed in any Ruby installation.

About Rails

Rails is a full-stack framework for developing database-backed web applications according to the model-view-controller design pattern.

The two overarching principles of Rails are the following:

  • Convention-over-Configuration (CoC) . Following this principle, a Rails application is generated with a standard convention and with reasonable defaults. No configuration is required if the defaults are acceptable -- and no configuration is encouraged.
     
  • Don't Repeat Yourself (DRY) . This principle requires that the behavior of an application be defined at an authoritative location and not repeated at other places in the application. DRY greatly improves application maintainability because it minimizes the number of edits required when the program code changes.  

Rails is a Ruby gem that you can install in a JRuby installation with the following command:

 
jruby -S gem install rails --include-dependencies
 

This command installs the latest version of Rails in your JRuby installation directory and includes all the appropriate dependencies. The -S switch indicates that the rails script is in JRuby's bin directory. JRuby version 1.1 includes dependencies by default, so the --include-dependencies switch is not required with that version.

You can also install earlier versions of Rails. For example, the following command installs Rails 1.2.6:

 
jruby -S gem install rails -version 1.2.6 --include-dependencies
 

To deploy an application, you need a database and a web server in addition to the Ruby-on-Rails framework and the JRuby interpreter. This article will first outline the way that a Ruby-on-Rails application is traditionally deployed — if the word tradition can be applied to such a recent technology. Then the article examines the alternative of using the GlassFish application server.

Traditional Rails Deployment

Software in a Traditional Ruby-on-Rails Deployment

WEBrick is an open-source HTTP server library written in Ruby. WEBrick is part of the standard Ruby library and is used to test Ruby-on-Rails applications in development environments.

Mongrel is a fast HTTP library and web server for Ruby that can host Ruby web applications in production. You install Mongrel as a Ruby gem.

Capistrano is a tool written in Ruby for automating the deployment of Rails applications. You install Capistrano as a Ruby gem.

Apache HTTPD is an open-source module that includes the popular Apache HTTP Server.

nginx is a lightweight web server and reverse proxy.

LightTPD is a web server optimized for speed-critical environments.

 

A traditional deployment environment for a Rails application consists of a lightweight web server such as Apache HTTPD, nginx, or LightTPD at the front end. It is layered on a cluster of Mongrel web servers that are configured using HTTP-based reverse-proxy. A cluster of Mongrel web servers is informally known as a "pack of Mongrels."

The static content is served by the web server, and dynamic content is proxied to a Mongrel web server in the cluster. Rails — and so each Mongrel web server — is single-threaded and can work on only one request at a time. So the number of Mongrel instances required is directly proportional to the number of desired concurrent requests to be handled. Each Mongrel instance runs on a separate port.

To provide load balancing, you must install extension modules for the web server. For example, Apache HTTPD requires such modules as mod_proxy_balancer and mod_rewrite. LightTPD requires the mod_proxy module. A typical deployment architecture is shown in Figure 2.

Figure 2. Traditional Ruby-on-Rails Deployment
 

Finally, the deployment requires a management tool, typically Capistrano, to deploy applications to multiple servers. If you need to redeploy an application, then you must restart all the Mongrel instances using Capistrano. If you introduce another application that needs to be hosted, then you must duplicate the entire configuration.

Creating a JRuby-on-Rails Application

You create a JRuby-on-Rails application with a command like the following:

 
jruby -S rails hello
 

In this example, hello is the application name.

The command to create a Rails application generates a directory structure following CoC and DRY principles. Figure 3 shows the directory structure generated with JRuby 1.0.3, using the jruby -S rails hello command.

Figure 3. Directory Structure of a Ruby-on-Rails Application
 

You can invoke all the standard Rails commands with JRuby, such as the following script/server command that starts the server:

 
jruby script/server
 

You can create a controller and an associated view with a command like the following:

 
jruby script/generate controller home index
 

With the JRuby interpreter, you can easily test any Ruby-on-Rails application, using only pure-Ruby gems and standard Rails commands.

Ruby-on-Rails Plug-Ins

A Ruby-on-Rails plug-in is a self-contained library made specifically for Ruby on Rails. Ruby-on-Rails plug-ins extend or modify the core Ruby-on-Rails framework. They make it easy to reuse someone else's code or to package your own code for reuse. Unlike a gem, a plug-in is installed directly into a specific Ruby-on-Rails application. The plug-in is then deployed remotely along with the application.

One example of a Ruby-on-Rails plug-in is the Goldspike project, formerly known as Rails Integration, which enables you to create a Web ARchive (WAR) from a Ruby-on-Rails application. The WAR format is a standard way to distribute and deploy applications in Java EE-compliant application servers.

About the GlassFish Application Server
 

The GlassFish application server is an open-source, Java EE 5-compliant application server developed by the GlassFish community. The Sun-supported version of GlassFish is Sun Java System Application Server.

In addition to the application server, the GlassFish community develops many other useful components, for example:

The GlassFish community also maintains a Maven repository for all these components.

The current release of the GlassFish application server is GlassFish v2, which has these main features:

  • Metro: A complete web services stack that provides interoperability with .NET 3.0.  
  • Clustering, load balancing, and high availability  
  • Java Business Integration (JBI) support through OpenESB
  • Improved user experience when compared with GlassFish v1
  • Single, smaller download
  • Multiple user profiles
  • Faster startup time
  • Update Center
  • Improved Admin Console
  • Record-setting performance: In July 2007, GlassFish v2 posted the highest-ever score on SPECjAppServer for a single Sun Fire T2000 server, at the time beating competitors by as much as 30 percent.

You can download the GlassFish application server at no cost. See the end of this article for more information about the GlassFish application server.

The GlassFish community is working on the next version of the application server: GlassFish v3. The main features of this version are the following:

  • Smaller footprint — kernel size less than 100 KB.
  • Faster startup time — typically less than one second.
  • Modular — starts up containers only as required.
  • Expanded support for scripting languages — In addition to Java EE and JRuby, development efforts are focused on support for Groovy/Grails, Phobos, PHP, and Jython/Python.

Technology preview builds of GlassFish v3 are available now. Availability of a stable build is scheduled for later in 2008.

Deploying JRuby-on-Rails Applications on the GlassFish Application Server
 

You can deploy a JRuby-on-Rails application in either of two modes: WAR-based or Directory-based.

WAR-Based Mode

Web ARchive (WAR) is a standard packaging format to distribute and deploy applications on Java EE servers. To deploy in WAR-based mode, you must install the Goldspike plug-in, which enables you to create a WAR from the Ruby-on-Rails application. The Goldspike plug-in provides a packaging format and dispatching mechanism for the Ruby-on-Rails application. After you create the WAR file, you can deploy it to GlassFish.

Figure 4 shows the process diagram of a WAR file deployed on the GlassFish application server.

Figure 4. WAR-Based Deployment Process Diagram
 

For connection management, GlassFish uses Grizzly, an implementation of HTTP listener written using Java NIO APIs. The Grizzly listener in the GlassFish application server receives the request and dispatches it to the appropriate web application. The web.xml file in the WAR file contains the servlet org.jruby.webapp.RailsServlet, which translates data from the servlet request to the Rails dispatcher. The JRuby runtime spawns multiple Rails instances, which can be configured through GlassFish.

Warbler, a Ruby gem, provides an alternative packaging mechanism that is minimal, flexible, and more like Ruby. It uses Goldspike for servlet dispatching. More details about Warbler are available on the JRuby wiki.

Directory-Based Mode

In Directory-based deployment mode, you deploy a Rails application directly to GlassFish without any additional plug-ins.

The Grizzly connector receives the request and dispatches it directly to a preconfigured JRuby installation. The JRuby runtime spawns a new Rails instance each time the Grizzly listener receives a request.

Figure 5. Directory-Based Deployment Process Diagram
 

In both WAR- and Directory-based modes, only one Java Virtual Machine * is running as the operating system process for the GlassFish application server. The main advantage of the Directory-based mode is that it bypasses the web application processing and delegates the request directly to the Rails framework.

Deploying JRuby-on-Rails Applications on GlassFish v2

Users of GlassFish v2 can add JRuby capability by downloading a JRuby module through the GlassFish Update Center GUI. The GlassFish Update Center, a utility that is bundled with the GlassFish application server, enables you to update existing functionality or add new functionality. The JRuby module can create either stand-alone or shared WAR files from a JRuby-on-Rails application. The WAR can then be deployed on a GlassFish application server instance.

Figure 6 shows the availability of the JRuby on GlassFish module in the GlassFish Update Center GUI. You can also watch a detailed screencast that provides instructions for installing and using the JRuby-on-GlassFish module.

Figure 6. GlassFish Update Center GUI
 

A stand-alone WAR file is self-contained and bundles all necessary libraries — such as JRuby, Rails, and Goldspike — with the application. A shared WAR file contains only the deployment descriptors for the application. For a shared WAR, you configure the GlassFish application server to provide any necessary libraries.

If you choose to build a stand-alone WAR file to avoid configuring the GlassFish server, you pay a price in the size of the deployed WAR. For a trivial Hello World application, an expanded stand-alone WAR file is 10.6 MB, and a shared WAR file is 202 KB.

Deploying JRuby-on-Rails Applications on GlassFish v3 Gem

If you have already installed JRuby on your system, then you can download the GlassFish v3 gem and install it in a JRuby instance by using the following standard command:

 
jruby -S gem install glassfish
 

This command installs the gem and provides a smooth transition to using GlassFish as an alternative to WEBrick or Mongrel for developing and deploying your applications. Using the gem, you deploy your application in Directory-based mode.

You can find complete instructions for installing and using the GlassFish gem in this blog entry.

Advantages of JRuby-on-Rails With the GlassFish Application Server
 

The following sections explain some of the key concepts of application development and deployment from a Rails and GlassFish perspective.

Identical Development and Deployment Environments

Traditionally, you develop a Ruby-on-Rails application in an environment quite different from the one in which you deploy it. The development environment uses the WEBrick server to test the application, and the deployment environment requires a complex configuration that you manage with Capistrano.

When you use the GlassFish application server, your development environment for a JRuby-on-Rails application is exactly the same as your deployment environment. In the GlassFish environment, one process listens to all requests and processes the responses. In contrast, the traditional Ruby-on-Rails deployment involves multiple processes.

In the GlassFish environment, the migration from development to production requires no extra configuration. You can use the same container for both development and production. GlassFish permits multiple applications to be hosted in the same domain. In short, GlassFish provides a simplified and integrated development and deployment container instead of requiring you to configure multiple tools.

Multiple Applications in One Container

If you are deploying multiple Rails applications with different functionalities, the traditional deployment requires that each must be deployed on a different pack of Mongrels. Essentially, you must replicate the entire setup — with Mongrels behind a lightweight web server that is managed by Capistrano — for each application.

With the GlassFish application server, you can deploy multiple applications in a GlassFish instance that is already running. You deploy each application in a separate context root with its own set of resources, completely isolating each application. You redeploy an application by copying the updated file, whether in WAR-based or Directory-based mode, without the need to explicitly restart GlassFish.

Multiple Requests by a Single Application

In Rails, the number of requests that an application can handle is directly proportional to the number of Mongrels running in the pack. Even though scaling an application is easy — just add more Mongrels — it is expensive in terms of resource use.

The GlassFish application server can handle multiple requests. You determine how many requests when you configure GlassFish for the number of JRuby runtimes that can be spawned for each application. GlassFish maintains these runtimes in a pool. Whenever GlassFish receives a request, it uses a JRuby runtime from the pool to spawn a new Rails instance to process the request. After the response is returned, the JRuby runtime returns to the pool and is available for the next request.

As already mentioned, the WAR-based deployment mode uses the Goldspike plug-in. The first time Goldspike runs, it creates the descriptor file WEB-INF/web.xml under your JRuby-on-Rails application directory. You can edit the following context parameters in the file to configure the number of JRuby-on-Rails instances:

Table 1: Context Parameters That Configure the Number of Instances
 
 
Name
Meaning
Default Value
jruby.pool.maxActive
Maximum number of runtimes
4
jruby.pool.minIdle
Minimum number of runtimes
2
jruby.pool.initialSize
Initial number of runtimes
The value of jruby.pool.minIdle
jruby.pool.checkInterval
Number of milliseconds between checks to determine if more runtimes are needed
1000
 

In Directory-based mode, you use the command-line property -n to control the number of runtimes. For example, the following command starts two JRuby-on-Rails instances:

 
jruby -S glassfish_rails temp -n 2
 
Redeploying an Application

To redeploy a Ruby-on-Rails application in a traditional deployment, you must stop the entire pack of Mongrels, copy the application to the deployment directory, and then start the Mongrels.

To redeploy an application in the GlassFish application server, you copy a new WAR file into the deployment directory. GlassFish recycles all the required resources, including classes and database connections. There is no need to restart the already running instance of GlassFish, so other applications in the same GlassFish instance can continue to serve requests without interruption.

Clustering, Load Balancing, and High Availability

Clustering in a traditional Rails deployment means maintaining a Mongrel cluster — a pack of Mongrels behind a lightweight reverse-proxied server such as Apache, LightTPD, or nginx. You must individually configure each machine in the cluster and then reverse-proxy it with the lightweight web server.

A Ruby-on-Rails application deployed on a pack of Mongrels does not share any state because Ruby on Rails is single-threaded. The only common link between the multiple applications is either the lightweight HTTP server, which acts as the front end for the Mongrel pack, or the database, if one exists, at the back end.

In contrast, Figure 7 shows how the GlassFish application server provides unified management for clustering, load balancing, and high availability.

Figure 7. GlassFish Clustering Architecture
 

In a GlassFish cluster, each node — a physical machine — is running one or more application server instances. Each node also comes with a node agent that communicates with a central administration server. Figure 7 shows several such nodes grouped together as clustered instances.

Figure 7 shows various transports — HTTP, JMS, RMI-IIOP — communicating with the clustered instances through a load-balancing tier. Custom resources, such as enterprise information systems, connect to the load balancer through resource adapters in the Java connector architecture. All of the transports can be load balanced across the cluster, both for scalability and for fault-tolerant strategies implemented by redundant units available upon single-point failure.

At the bottom of the figure is a high-availability application state repository, an abstraction of session-state storage. The repository stores session state, including HTTP session state, Ruby-on-Rails session state, and single sign-on information. This state information can be stored either through memory replication or in a database.

Clustering and high availability are integrated into GlassFish v2. Load balancing is provided by a plug-in that you can easily configure for all clustered instances. See the article Clustering in GlassFish Version 2 for more information.

Database Connection Pooling

In a traditional deployment, every time your Rails application requests database access, the Mongrel server creates a new database connection. But creating a new connection for each request is costly in time and resources.

The GlassFish application server provides database connection pools, which minimize the delay for database-related operations. The database connection pool is available to each deployed application. When a client requests a connection, it is provided from the pool. When the client no longer needs the connection, it is returned to the pool. This strategy allows subsequent database requests to reuse the connection — there is no need to make a new connection at every connection request. Connection pooling thus improves the response time for an application to open, use, and close the connection because the pool manages the actual connections to the data store.

You can find a complete set of instructions to use JNDI-based database connection pools in this blog entry.

Cohosting Ruby-on-Rails and Java EE Applications

The Java EE platform is an industry-grade, time-tested platform for enterprise-level deployments. GlassFish is a Java EE 5-compliant application server that can also host JRuby-on-Rails applications. By allowing Java EE and JRuby-on-Rails code to mix, GlassFish leverages existing investment in Java EE while hosting JRuby-on-Rails applications in the same environment.

Example Project
 

This section describes mediacast.sun.com, a successful deployment of JRuby-on-Rails on the GlassFish application server.

The publicly accessible Sun mediacast web site provides a place for Sun employees to store large media files. The application is written using JRuby on Rails and deployed on the GlassFish application server. The deployment diagram shown in Figure 8 describes two load-balanced Sun Fire T2000 servers running the Solaris 10 Operating Environment and GlassFish v2 — actually, Sun Java System Application Server 9.1 UR1.

Figure 8. Sun Mediacast Deployment Diagram
 

NetBeans IDE 6 and GlassFish v2 were used in the development phase of this application. More details about development, deployment, and lessons learned from this example are available in this blog entry by Igor Minar.

Summary
 

Developing and deploying a web application with JRuby-on-Rails and GlassFish provides many advantages over traditional deployments. Chief among these advantages are the following:

  • You can develop in the same environment in which you deploy. GlassFish makes it easy to use the same server for both activities.
     
  • You can deploy multiple applications in a GlassFish instance that is already running. There is no need to interrupt service for other hosted applications. You can also redeploy an application without restarting GlassFish.
     
  • GlassFish can handle multiple requests by maintaining JRuby runtimes in a pool. After it responds to a request, the JRuby runtime returns to the pool and is available for the next request.
     
  • The GlassFish application server provides database connection pools, which minimize the delay for database-related operations.
     
  • Clustering and high availability are integrated into GlassFish v2. Load balancing is provided by an easily managed plug-in.
     
  • GlassFish leverages existing investment in the Java EE platform while hosting JRuby-on-Rails applications in the same environment.

_______
* As used on this web site, the terms "Java Virtual Machine" or "JVM" mean a virtual machine for the Java platform.

Links in This Article
 
For More Information
 
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.
Left Curve
Popular Downloads
Right Curve
Untitled Document
Left Curve
More Systems Downloads
Right Curve