Arun Gupta, Miles to go ...

Arun Gupta is a technology enthusiast, a passionate runner, and a community guy who works for Oracle.
Main | Next page »

http://blogs.sun.com/arungupta/date/20091208 Tuesday December 08, 2009

TOTD #116: GlassFish v3 Administration using JavaFX front-end - JNLP available

As mentioned in TOTD #113, this Tip Of The Day (TOTD) provides a working version of the JavaFX front-end for GlassFish v3 administration.

Please click here to launch the JNLP or click here to a page that provides some introduction along with the link to JNLP. You may like to enable Java Console as explained in TOTD #114 for any log messages.

See a video of the tool in action:

Many thanks to Rajeshwar for providing feedback and helping me understand the RESTful interface better. TOTD #96 explains how the REST interface can be used.

Here is a TODO list in no particular order:

  • Show a splash screen after the startup to indicate server status
  • Allow the administration host/port to be changed
  • Tie the "server stats" with the server uptime instead of fetching once and then binding it locally
  • Provide dynamic updates of the monitoring data, currently its a snapshot
  • Convert the monitoring levels text boxes to radio buttons
  • Provide complete hints on setting monitoring level based upon the engines
  • Enable/Disable the buttons based upon the status of server running (or not)
  • Introduce charts to track dynamic shrink/expand of threads/pools/etc.
  • Probably something else that I'm forgetting :-)

How are you using JavaFX with GlassFish ?

How will you use GlassFish v3 REST interface in your tools ?

Technorati: totd javafx glassfish v3 rest web jruby rubyonrails rest administration monitoring management

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20091111 Wednesday November 11, 2009

TOTD #113: JavaFX front-end for GlassFish v3 Administration - Using REST interface

GlassFish v3 provides a REST interface to management and monitoring information as discussed in TOTD #96. As mentioned in that blog "the REST interface is a lower level API that enables toolkit developers and IT administrators to write their custom scripts/clients using language of their choice". This blog introduces a tool that uses the REST API to provide management and monitoring of GlassFish v3 and is written using JavaFX.

This tool is only a proof-of-concept that demonstrates that GlassFish v3 REST interface is functionally very rich and can indeed be used to write third-party administration tools. The tool uses a subset of the REST interface and exposes only a limited amount of management and monitoring capabilities otherwise exposed. After all this is a proof-of-concept :-)

A screencast of this tool in action along with a downloadable JNLP version will soon be available. For now, here is a snapshot of the main window of this tool:

The main screen allows you to enter a URL for the GlassFish administration. Then the GlassFish instance can be stopped/restarted from the main window using the buttons on top right. There is an animation at the bottom of the screen where the glassfish is swimming in the ocean and is directly related to the state of server running in the background. If the server is running, the animation works. If the server is not running then the animation stops as well.

The main screen has three main buttons:

  • "List Applications" - list all the applications deployed on the running instance
  • "Show Monitoring Levels" - show/Update all the monitoring levels
  • "Server Stats" - show statistics of the running server

Clicking on "List Applications" shows the list of applications deployed on this particular instance. Here is how a snapshot looks like for an instance running on my localhost at port 4848:

As shown in the screen, it shows a radio-bulleted list of all the applications. Each bullet is also accompanied by an image indicating the type of application - Web or Rails for now. Select the application and click on "Monitor" button to monitor that particular application. The REST API exposes a vast amount of monitoring data but a subset of monitoring data is displayed for Web and Rails application for now. Here is a snapshot of the monitoring data published for a Web application:

As evident by the list of engines, this web application has EJBs bundled as well. It also shows total number of Servlets/JSPs loaded, number of requests made to this web application and some other monitoring data.

Here is a snapshot of the monitoring data published for a Rails application:

It shows number of JRuby runtimes configured for the application, number of requests sent to the application, number of responses with different HTTP access codes and some other data.

The monitoring levels of different containers can be easily updated by clicking on "Show Monitoring Levels" as shown below:

And finally some server statistics are shown by clicking on "Server Stats" as shown below:

It shows when the server was started, host/port information, version and finally how long the server has been running for. The dials are an animation that shows the server up time.

Here are other related JavaFX and GlassFish related blogs published earlier:

How are you going to use the REST interface exposed by GlassFish v3 in your environment ?

Are you using JavaFX with GlassFish together in any way ?

Leave a comment on this blog if you do!

Technorati: javafx glassfish v3 rest web jruby rubyonrails rest administration monitoring management

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090918 Friday September 18, 2009

TOTD #104: Popular Ruby-on-Rails applications on GlassFish v3 – Redmine, Typo, Substruct

GlassFish v3 is opening up new frontiers by allowing to easily deploy Rails, Grails and Django applications, in addition to Java EE, without any additional packaging. You can even write a custom container to support new types of applications. Numerous entries on this blog have talked about how to deploy Rails applications on GlassFish v3. This Tip Of The Day (TOTD) will recap them and, once again, demonstrate how to easily get started with deploying some popular open source Rails applications on GlassFish v3.

Lets prepare a GlassFish v3 build for deploying Rails applications. This blog is going to use 9/16 nightly but you should pick the latest nightly or promoted.

  1. Unzip the downloaded bundle as:
    ~/tools/glassfish/v3/9-16 >unzip ~/Downloads/glassfish-v3-b64-09_16_2009.zip
  2. Configure JRuby/Rails in GlassFish v3 - JRuby/rails can be configured three different ways - use a previously installed JRuby/Rails directory, install JRuby/Rails module using the graphical Update Center or the "pkg" binary. This Update Center module comes packaged with JRuby 1.3.1, Rails 2.3.2 and some other useful gems. Pick the option you are most comfortable with and use it for your GlassFish installation.
    1. Configure previously installed JRuby/Rails directory as:
      ~/tools/glassfish/v3/9-16/glassfishv3/bin/asadmin create-jvm-options -Djruby.home=/Users/arungupta/tools/jruby
      Authentication failed with password from login store: /Users/arungupta/.asadminpass
      
      Enter admin password >
      created 1 option(s)
      Command create-jvm-options executed successfully.

      That's it!
    2. Install JRuby/Rails module using graphical Update Tool
      1. The graphical Update Tool tool can be invoked as:
        ~/tools/glassfish/v3/9-16/glassfishv3 >./bin/updatetool
        
        The software needed for this command (updatetool) is not installed.
        
        If you choose to install Update Tool, your system will be automatically
        configured to periodically check for software updates. If you would like
        to configure the tool to not check for updates, you can override the
        default behavior via the tool's Preferences facility.
        
        When this tool interacts with package repositories, some system information
        such as your system's IP address and operating system type and version
        is sent to the repository server. For more information please see:
        
        http://wiki.updatecenter.java.net/Wiki.jsp?page=UsageMetricsUC2
        
        Once installation is complete you may re-run this command.
        
        Would you like to install Update Tool now (y/n): y
        
        Proxy: Using system proxy settings.
        Install image: /Users/arungupta/tools/glassfish/v3/9-16/glassfishv3
        Installing pkg packages.
        Installing updatetool packages.
        Registering notifier: Already registered.
        Initialization complete.
        
        Software successfully installed. You may now re-run this command (updatetool).
      2. The first invocation of the command installs the Update Tool and the second invocation shows the following screen after "JRuby on GlassFish" module is selected:


        Click on green button in the top left to install the module and it picks up the dependencies as well as shown below:


        Click on "Install" to start the installation and click on "Accept" to accept the license.
      3. Close the Update Tool window once the installation is completed. The module creates "glassfish/jruby" directory.
    3. Install JRuby/Rails module using "pkg" binary
      1. Install the JRuby/Rails bits using the "pkg" binary. Invoke the command as:
        ~/tools/glassfish/v3/9-16/glassfishv3 >./bin/pkg

        The software needed for this command (pkg) is not installed. When this tool interacts with package repositories, some system information such as your system's IP address and operating system type and version is sent to the repository server. For more information please see: http://wiki.updatecenter.java.net/Wiki.jsp?page=UsageMetricsUC2 Once installation is complete you may re-run this command. Would you like to install this software now (y/n): y Proxy: Using system proxy settings. Install image: /Users/arungupta/tools/glassfish/v3/9-16/glassfishv3 Installing pkg packages. Initialization complete. Software successfully installed. You may now re-run this command (pkg).
      2. The command "pkg list -a" shows all the modules available for installation and the output looks like:

        ~/tools/glassfish/v3/9-16/glassfishv3 >./bin/pkg list -a
        NAME (PUBLISHER)                              VERSION         STATE      UFIX
        ant (contrib.glassfish.org)                   1.7.1-0.6       known      ----
        felix                                         2.0.0-0         installed  ----
        glassfish-appclient                           3.0-65          installed  ----
        glassfish-cmp                                 3.0-65          installed  ----
        
        . . .
        
        jersey-docs-and-examples                      1.1.2-1.0       known      ----
        jmaki (contrib.glassfish.org)                 1.8.1-2.0       known      ----
        jruby                                         1.3.1-1.1       known      ----
        jruby (contrib.glassfish.org)                 1.2.0-1.1       known      u---
        jruby-gems (contrib.glassfish.org)            2.3.2-1.1       known      ----
        jython-container (contrib.glassfish.org)      0.5.3-1.0       known      ----
        jython-runtime (contrib.glassfish.org)        2.5.0-1.0       known      ----
        metro                                         2.0-19          installed  ----
        
        . . .
        
        updatetool                                    2.3.0-36.2403   known      ----
        updatetool (contrib.glassfish.org)            2.2.2-30.2311   known      u---
        wxpython2.8-minimal                           2.8.10.1-36.2403 known      ----
        wxpython2.8-minimal (contrib.glassfish.org)   2.8.8-30.2311   known      u---
      3. Start the installation of "jruby" module as:

        ~/tools/glassfish/v3/9-17/glassfishv3 >./bin/pkg install jruby
        DOWNLOAD                                  PKGS       FILES    XFER (MB)
        Completed                                  2/2 14810/14810    37.0/37.0
        
        PHASE                                        ACTIONS
        Install Phase                            17273/17273
  3. Redmine on GlassFish - Redmine is an open source project management web application. The simplified steps to deploy Redmine on GlassFish v3 are given below (also on GlassFish Gem and on GlassFish v3 TP2):
    1. Download and unzip Redmine 0.8.5 (latest stable release).
    2. Change the database adapter from "mysql" to "jdbcmysql" as:

      sed s/'adapter: mysql'/'adapter: jdbcmysql'/ <config/database.yml.new >config/database.yml
    3. Create the database manually as "sudo mysqladmin create redmine_development". "db:create" fails because of JRUBY-3502.
    4. Migrate the database as "db:migrate".
    5. Deploy the application as:
      ~/samples/jruby/redmine >~/tools/glassfish/v3/9-16/glassfishv3/bin/asadmin deploy redmine-0.8.5
       Authentication failed with password from login store: /Users/arungupta/.asadminpass
      
      Enter admin password>
      Command deploy executed successfully.
    6. Here are some snapshots from the deployed application:





  4. Typo on GlassFish - Typo is the oldest Ruby on Rails blogware. The simplified steps to deploy Typo on GlassFish v3 are given below (also on GlassFish Prelude):
    1. Download and unzip Typo 5.3 (latest stable release).
    2. Change the database adapter from "mysql" to "jdbcmysql" as:

      sed s/'adapter: mysql'/'adapter: jdbcmysql'/ <config/database.yml.example >config/database.yml
    3. Create the database manually as "sudo mysqladmin create typo_dev". "db:create" fails because of JRUBY-3502.
    4. Typo runs using Rails 2.2.2 so lets install Rails 2.2.2 so lets install Rails 2.2.2 as:
      ~/samples/jruby/typo/typo-5.3 >~/tools/glassfish/v3/9-16/glassfishv3/glassfish/jruby/bin/jruby -S gem install rails -v 2.2.2
      JRuby limited openssl loaded. gem install jruby-openssl for full support.
      http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
      Successfully installed activesupport-2.2.2
      Successfully installed activerecord-2.2.2
      Successfully installed actionpack-2.2.2
      Successfully installed actionmailer-2.2.2
      Successfully installed activeresource-2.2.2
      Successfully installed rails-2.2.2
      6 gems installed
      Installing ri documentation for activesupport-2.2.2...
      Installing ri documentation for activerecord-2.2.2...
      Installing ri documentation for actionpack-2.2.2...
      Installing ri documentation for actionmailer-2.2.2...
      Installing ri documentation for activeresource-2.2.2...
      Installing ri documentation for rails-2.2.2...
      Installing RDoc documentation for activesupport-2.2.2...
      Installing RDoc documentation for activerecord-2.2.2...
      Installing RDoc documentation for actionpack-2.2.2...
      Installing RDoc documentation for actionmailer-2.2.2...
      Installing RDoc documentation for activeresource-2.2.2...
      Installing RDoc documentation for rails-2.2.2...
    5. Migrate the database as "db:migrate".
    6. Deploy the application as:
      ~/samples/jruby/typo >~/tools/glassfish/v3/9-16/glassfishv3/bin/asadmin deploy typo-5.3
      Authentication failed with password from login store: /Users/arungupta/.asadminpass
      
      Enter admin password>
      Command deploy executed successfully.
    7. Here are are some snapshots from the deployed application:





  5. Substruct on GlassFish - Substruct is an open source E-Commerce project in Ruby-on-Rails. The simplified steps to deploy Substruct on GlassFish v3 are given below (also on GlassFish v3 Gem):
    1. Download and unzip substruct 1.0 a6 (latest stable release).
    2. Install the required gems as:
      ~/samples/jruby/substruct >~/tools/glassfish/v3/9-16/glassfishv3/glassfish/jruby/bin/jruby -S gem install RedCloth fastercsv mime-types mini_magick ezcrypto jruby-openssl --no-ri --no-rdoc
    3. Change the database adapter from "mysql" to "jdbcmysql" as:

      ~/samples/jruby/substruct/substruct_rel_1-0-a6>sed s/'adapter: mysql'/'adapter: jdbcmysql'/ <config/database.yml
      >config/database.yml.new
      ~/samples/jruby/substruct/substruct_rel_1-0-a6>mv config/database.yml.new config/database.yml
    4. Create the database manually as "sudo mysqladmin create substruct_development". "db:create" fails because of JRUBY-3502.
    5. Initialize the database as:
      ~/samples/jruby/substruct/substruct_rel_1-0-a6 >~/tools/glassfish/v3/9-16/glassfishv3/glassfish/jruby/bin/jruby -S rake substruct:db:bootstrap
    6. Deploy the application as:
      ~/samples/jruby/substruct >~/tools/glassfish/v3/9-16/glassfishv3/bin/asadmin deploy substruct_rel_1-0-a6
      Authentication failed with password from login store: /Users/arungupta/.asadminpass
      Enter admin password>
      
      Command deploy executed successfully.
    7. Here is a snapshot of the deployed application:

So we deployed Redmine, Typo, and Substruct using JRuby/Rails on GlassFish without any additional packaging. There are several Rails applications deployed in production on GlassFish.

What Rails applications are you deploying on GlassFish ?

Technorati: glassfish v3 rubyonrails jruby redmine typo mephisto substruct

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090812 Wednesday August 12, 2009

TOTD #92: Session Failover for Rails applications running on GlassFish


The GlassFish High Availability allows to setup a cluster of GlassFish instances and achieve highly scalable architecture using in-memory session state replication. This cluster can be very easily created and tested using the "clusterjsp" sample bundled with GlassFish. Here are some clustering related entries published on this blog so far:

  • TOTD #84 shows how to setup Apache + mod_proxy balancer for Ruby-on-Rails load balancing
  • TOTD #81 shows how to use nginx to front end a cluster of GlassFish Gems
  • TOTD #69 explains how a GlassFish cluster can be front-ended using Sun Web Server and Load Balancer Plugin
  • TOTD #67 shows the same thing using Apache httpd + mod_jk
#67 & #69 uses a web application "clusterjsp" (bundled with GlassFish) that uses JSP to demonstrate in-memory session replication state replication. This blog creates a similar application "clusterrails" - this time using Ruby-on-Rails and deploy it on GlassFish v2.1.1. The idea is to demonstrate how Rails applications can leverage the in-memory session replication feature of GlassFish.

Rails applications can be easily deployed as a WAR file on GlassFish v2 as explained in TOTD #73. This blog will guide through the steps of creating the Controller and View to mimic "clusterjsp" and configuring the Rails application for session replication.
  1. Create a template Rails application and create/migrate the database. Add a Controller/View as:

    ~/samples/jruby/session >~/tools/jruby/bin/jruby script/generate controller home index
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
          exists  app/controllers/
          exists  app/helpers/
          create  app/views/home
          exists  test/functional/
          create  test/unit/helpers/
          create  app/controllers/home_controller.rb
          create  test/functional/home_controller_test.rb
          create  app/helpers/home_helper.rb
          create  test/unit/helpers/home_helper_test.rb
          create  app/views/home/index.html.erb

  2. Edit the controller in "app/controllers/home_controller.rb" and change the code to (explained below):

    class HomeController < ApplicationController
      include Java

      def index
        @server_served = servlet_request.get_server_name
        @port = servlet_request.get_server_port
        @instance = java.lang.System.get_property "com.sun.aas.instanceName"
        @server_executed = java.net.InetAddress.get_local_host().get_host_name()
        @ip = java.net.InetAddress.get_local_host().get_host_address
        @session_id = servlet_request.session.get_id
        @session_created = servlet_request.session.get_creation_time
        @session_last_accessed = servlet_request.session.get_last_accessed_time
        @session_inactive = servlet_request.session.get_max_inactive_interval

        if (params[:name] != nil)
          servlet_request.session[params[:name]] = params[:value]
        end

        @session_values = ""
        value_names = servlet_request.session.get_attribute_names
        unless (value_names.has_more_elements)
          @session_values = "<br>No parameter entered for this request"
        else
            @session_values << "<UL>"
            while (value_names.has_more_elements)
                param = value_names.next_element
                unless (param.starts_with?("__"))
                  value = servlet_request.session.get_attribute(param)
                  @session_values << "<LI>" + param + " = " + value + "</LI>"
                end
            end
            @session_values << "</UL>"
        end

      end

      def adddata
        servlet_request.session.set_attribute(params[:name], params[:value])
        render :action => "index"
      end

      def cleardata
        servlet_request.session.invalidate
        render :action => "index"
      end
    end

    The "index" action initializes some instance variables using the "servlet_request" variable mapped from "javax.servlet.http.ServletRequest" class. The "servlet_request" provides access to different properties of the request received such as server name/port, host name/address and others. It also uses an application server specific property "com.sun.aas.instanceName" to fetch the name of particular instance serving the request. In this blog we'll create a cluster with 2 instances. The action then prints the servlet session attributes name/value pairs entered so far.

    The "adddata" action takes the name/value pair entered on the page and stores them in the servlet request. The "cleardata" action clears any data that is storied in the session.
  3. Edit the view in "app/views/home/index.html.erb" and change to (explained below):

    <h1>Home#index</h1>
    <p>Find me in app/views/home/index.html.erb</p>
    <B>HttpSession Information:</B>
    <UL>
    <LI>Served From Server:   <b><%= @server_served %></b></LI>
    <LI>Server Port Number:   <b><%= @port %></b></LI>
    <LI>Executed From Server: <b><%= @server_executed %></b></LI>
    <LI>Served From Server instance: <b><%= @instance %></b></LI>
    <LI>Executed Server IP Address: <b><%= @ip %></b></LI>
    <LI>Session ID:    <b><%= @session_id %></b></LI>
    <LI>Session Created:  <%= @session_created %></LI>
    <LI>Last Accessed:    <%= @session_last_accessed %></LI>
    <LI>Session will go inactive in  <b><%= @session_inactive %> seconds</b></LI>
    </UL>
    <BR>
    <% form_tag "/session/home/index" do %>
      <label for="name">Name of Session Attribute:</label>
      <%= text_field_tag :name, params[:name] %><br>

      <label for="value">Value of Session Attribute:</label>
      <%= text_field_tag :value, params[:value] %><br>

        <%= submit_tag "Add Session Data" %>
    <% end  %>
    <% form_tag "/session/home/cleardata" do %>
        <%= submit_tag "Clear Session Data" %>
    <% end %>
    <% form_tag "/session/home/index" do %>
        <%= submit_tag "Reload Page" %>
    <% end %>
    <BR>
    <B>Data retrieved from the HttpSession: </B>
    <%= @session_values %>

    The view dumps the property value retrieved from the servlet context in the action. Then it consists of some forms to enter the session name/value pairs, clear the session and reload the page. The application is now ready, lets configure it for WAR packaging.
  4. Generate a template "web.xml" and copy it to "config" directory as:

    ~/samples/jruby/session >~/tools/jruby/bin/jruby -S warble war:webxml
    mkdir -p tmp/war/WEB-INF
    ~/samples/jruby/session >cp tmp/war/WEB-INF/web.xml config/
    1. Edit "tmp/war/WEB-INF/web.xml" and change the first few lines from:

      <!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
      <web-app>

      to

      <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

      This is required because the element to be added next is introduced in the Servlet 2.4 specification.
    2. Add the following element:

      <distributable/>

      as the first element, right after "<web-app>". This element marks the web application to be distributable across multiple JVMs in a cluster.
  5. Generate and configure "warble/config.rb" as described in TOTD #87. This configuration is an important step otherwise you'll encounter JRUBY-3789. Create a WAR file as:

    ~/samples/jruby/session >~/tools/jruby/bin/jruby -S warble
    mkdir -p tmp/war/WEB-INF/gems/specifications
    cp /Users/arungupta/tools/jruby-1.3.0/lib/ruby/gems/1.8/specifications/rails-2.3.2.gemspec tmp/war/WEB-INF/gems/specifications/rails-2.3.2.gemspec

    . . .

    mkdir -p tmp/war/WEB-INF
    cp config/web.xml tmp/war/WEB-INF
    jar cf session.war  -C tmp/war .

  6. Download latest GlassFish v2.1.1, install/configure GlassFish and create/configure/start a cluster using the script described here. Make sure to change the download location and filename in the script. This script creates a cluster "wines" with two instances - "cabernet" runing on the port 58080 and "merlot" running on the port 58081.
  7. Deploy the application using the command:

    ~/samples/jruby/session >asadmin deploy --target wines --port 5048 --availabilityenabled=true session.war
Now, the screenshots from the two instances are shown and explained below. The two (or more) instances are front-ended by a load balancer so none of this is typically visible to the user but it helps to understand.
Here is a snapshot of this application deployed on "cabernet":



The instance name and the session id is highlighted in the red box. It also shows the time when the session was created in "Session Created" field.

And now the same application form "merlot":



Notice, the session id exactly matches the one from the "cabernet" instance. Similarly "Session Created" matches but "Last Accessed" does not because the same session session is accessed from a different instance.

Lets enter some session data in the "cabernet" instance and click on "Add Session Data" button as shown below:



The session attribute is "aaa" and value is "111". Also the "Last Accessed" time is updated. In the "merlot" page, click on the "Reload Page" button and the same session name/value pairs are retrieved as shown below:



Notice, the "Last Accessed" time is after the time showed in "cabernet" instance. The session information added in "cabernet" is automatically replicated to the "merlot" instance.

Now, lets add a new session name/value pair in "merlot" instance as shown below:



The "Last Accessed" is updated and the session name/value pair ("bbb"/"222") is shown in the page. Click on "Reload page" in "cabernet" instance as shown below:



This time the session information added to "merlot" is replicated to "cabernet".

So any session information added in "cabernet" is replicated to "merlot" and vice versa.

Now, lets stop "cabernet" instance as shown below:



and click on "Reload Page" in "merlot" instance to see the following:



Even though one instance from which the session data was added is stopped, the replicating instance continues to serve both the session values.

As explained earlier, these two instances are front-ended by a load-balancer typically running at port 80. So the user makes a request to port 80 and the correct session values are served even if one of the instance goes down and there by providing in-memory session replication.

Please leave suggestions on other TOTD that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd glassfish clustering rubyonrails jruby highavailability loadbalancer

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090616 Tuesday June 16, 2009

TOTD #84: Using Apache + mod_proxy_balancer to load balance Ruby-on-Rails running on GlassFish


TOTD #81 explained how to install/configure nginx for load-balancing/front-ending a cluster of Rails application running on GlassFish Gem. Another popular approach in the Rails community is to use Apache HTTPDmod_proxy_balancer. A user asked the exact details of this setup on the GlassFish Gem Forum. This Tip Of The Day (TOTD) will clearly explain the steps.

  1. Create a simple Rails scaffold and run this application using GlassFish Gem on 3 separate ports as explained in TOTD #81.
  2. Setup and configure HTTPD and mod_proxy_balancer
    1. Setup and install Apache HTTPD as explained here. I believe mod_proxy_balancer and other related modules comes pre-bundled with HTTPD, at least that's what I observed with Mac OS X 10.5.7. Make sure that the "mod_proxy_balancer" module is enabled by verifying the following line is uncommented in "/etc/apache2/httpd.conf":

      LoadModule proxy_balancer_module libexec/apache2/mod_proxy_balancer.so

      Please note another similar file exists in "/etc/httpd/httpd.conf" but ignore that one.
    2. Setup a mod_proxy_balancer cluster by adding the following fragment in "httpd.conf" as:

      <Proxy balancer://glassfishgem>
      BalancerMember http://localhost:3000
      BalancerMember http://localhost:3001
      BalancerMember http://localhost:3002
      </Proxy>

      The port numbers must exactly match with those used in the first step.
    3. Specify the ProxyPass directives to map the cluster to a local path as:

      ProxyPass / balancer://glassfishgem/
      CustomLog /var/log/glassfishgem.log/apache_access_log combined

      The "/" at the end of "balancer://glassfishgem" is very important to ensure that all the files are resolved correctly.
    4. Optionally, the following directive can be added to view the access log:

      CustomLog /var/log/glassfishgem.log/apache_access_log combined

      Make sure to create the directory specified in "CustomLog" directive.
  3. Now the application is accessible at "http://localhost/runlogs". If a new GlassFish instance is started then update the <Proxy> directive and restart your HTTPD as "sudo httpd -k restart". Dynamic update of BalancerMembers can be configured as explained here.
TOTD #81 started the Rails application in root context. You can alternatively start the application in a non-root context as:

~/tools/jruby/rails/runner >../../bin/jruby -S glassfish -e production -c myapp
Starting GlassFish server at: 10.0.177.178:3000 in production environment...
Writing log messages to: /Users/arungupta/tools/jruby-1.3.0/rails/runner/log/production.log.
Press Ctrl+C to stop.
. . .
~/tools/jruby/rails/runner >../../bin/jruby -S glassfish -e production -c myapp -p 3001
Starting GlassFish server at: 10.0.177.178:3001 in production environment...
Writing log messages to: /Users/arungupta/tools/jruby-1.3.0/rails/runner/log/production.log.
Press Ctrl+C to stop.
. . .
~/tools/jruby/rails/runner >../../bin/jruby -S glassfish -e production -c myapp -p 3002
Starting GlassFish server at: 10.0.177.178:3002 in production environment...
Writing log messages to: /Users/arungupta/tools/jruby-1.3.0/rails/runner/log/production.log.
Press Ctrl+C to stop.

and then the ProxyPass directive will change to:

ProxyPass /myapp/ balancer://glassfishgem/myapp/

The changes are highlighted in bold. And the application is now accessible at "http://localhost/myapp/runlogs".

After discussing on Apache HTTP Server forum, the BalancerMember host/port can be printd in the log file using a custom log format. So add the following log format to "/etc/apache2/httpd.conf":

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" \"%{BALANCER_WORKER_NAME}e\"" custom

And change the format from the default "combined" to the newly defined "custom" format as:

CustomLog /var/log/glassfishgem.com/apache_access_log custom

Three subsequent invocations of "http://localhost/runlogs" then prints the following log entries:

::1 - - [17/Jun/2009:10:53:53 -0700] "GET /runlogs HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.11) Gecko/2009060214 Firefox/3.0.11" "http://localhost:3002"
::1 - - [17/Jun/2009:10:54:04 -0700] "GET /runlogs HTTP/1.1" 200 621 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.11) Gecko/2009060214 Firefox/3.0.11" "http://localhost:3000"
::1 - - [17/Jun/2009:10:54:05 -0700] "GET /runlogs HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.11) Gecko/2009060214 Firefox/3.0.11" "http://localhost:3001"

As evident from the last fragment of each log line, the load is distributed amongst three GlassFish Gem instances. More details on load balancer algorithm are available here.

Feel free to drop a comment on this blog if you are using GlassFish in production for your Rails applications. Several stories are already available at rubyonrails+glassfish+stories.

Technorati: glassfish rubyonrails apache httpd mod_proxy_balancer loadbalancing clustering

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090430 Thursday April 30, 2009

TOTD #81: How to use nginx to load balance a cluster of GlassFish Gem ?

nginx (pronounced as "engine-ex") is an open-source and high-performance HTTP server. It provides the common features such as reverse proxying with caching, load balancing, modular architecture using filters (gzipping, chunked responses, etc), virtual servers, flexible configuration and much more.

nginx is known for it's high performance and low resource consumption. It's a fairly popular front-end HTTP server in the Rails community along with Apache, Lighttpd, and others. This TOTD (Tip Of The Day) will show how to install/configure nginx for load-balancing/front-ending a cluster of Rails application running on GlassFish Gem.
  1. Download, build, and install nginx using the simple script (borrowed from dzone):

    ~/tools > curl -L -O http://sysoev.ru/nginx/nginx-0.6.36.tar.gz
    ~/tools > tar -xzf nginx-0.6.36.tar.gz
    ~/tools > curl -L -O http://downloads.sourceforge.net/pcre/pcre-7.7.tar.gz
    ~/tools > tar -xzf pcre-7.7.tar.gz
    ~/tools/nginx-0.6.36 > ./configure --prefix=/usr/local/nginx --sbin-path=/usr/sbin --with-debug --with-http_ssl_module --with-pcre=../pcre-7.7
    ~/tools/nginx-0.6.36 > make
    ~/tools/nginx-0.6.36 > sudo make install
    ~/tools/nginx-0.6.36 > which nginx
    /usr/sbin/nginx

    OK, nginx is now roaring and can be verified by visiting "http://localhost" as shown below:


  2. Create a simple Rails scaffold as:

    ~/samples/jruby >~/tools/jruby/bin/jruby -S rails runner
    ~/samples/jruby/runner >~/tools/jruby/bin/jruby script/generate scaffold runlog miles:float minutes:integer
    ~/samples/jruby/runner >sed s/'adapter: sqlite3'/'adapter: jdbcsqlite3'/ <config/database.yml >config/database.yml.new
    ~/samples/jruby/runner >mv config/database.yml.new config/database.yml
    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S rake db:migrate
  3. Run this application using GlassFish Gem on 3 separate ports as:

    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S glassfish
    Starting GlassFish server at: 192.168.1.145:3000 in development environment...
    Writing log messages to: /Users/arungupta/samples/jruby/runner/log/development.log.
    Press Ctrl+C to stop.

    The default port is 3000. Start the seond one by explicitly specifying the port using "-p" option ..

    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S glassfish -p 3001
    Starting GlassFish server at: 192.168.1.145:3001 in development environment...
    Writing log messages to: /Users/arungupta/samples/jruby/runner/log/development.log.
    Press Ctrl+C to stop.

    and the last one on 3002 port ...

    ~/samples/jruby/runner >~/tools/jruby/bin/jruby -S glassfish -p 3002
    Starting GlassFish server at: 192.168.1.145:3002 in development environment...
    Writing log messages to: /Users/arungupta/samples/jruby/runner/log/development.log.
    Press Ctrl+C to stop.

    On Solaris and Linux, you can run GlassFish as a daemon as well.
  4. Nginx currently uses a simple round-robin algorithm. Other load balancers such as nginx-upstream-fair (fair proxy) and nginx-ey-balancer (maximum connections) are also available. The built-in algorithm will be used for this blog. Edit "/usr/local/nginx/conf/nginx.conf" to specify an upstream module which provides load balancing:
    1. Create a cluster definition by adding an upstream module (configuration details) right before the "server" module:

      upstream glassfish {
              server 127.0.0.1:3000;
              server 127.0.0.1:3001;
              server 127.0.0.1:3002;
          }

      The cluster specifies a bunch of GlassFish Gem instances running at the backend. Each server can be weighted differently as explained here. The port numbers must exactly match as those specified at the start up. The modified "nginx.conf" looks like:



      The changes are highlighted on lines #35 through #39.
    2. Configure load balancing by specifying this cluster using "proxy_pass" directive as shown below:

      proxy_pass http://glassfish;

      in the "location" module. The updated "nginx.conf" looks like:



      The change is highlighted on line #52.
  5. Restart nginx by using the following commands:

    sudo kill -15 `cat /usr/local/nginx/logs/nginx.pid`
    sudo nginx
Now "http://localhost" shows the default Rails page as shown below:



"http://localhost/runlogs" now serves the page from the deployed Rails application.

Now lets configure logging so that the upstream server IP address and port are printed in the log files. In "nginx.conf", uncomment "log_format" directive and add "$upstream_addr" variable as shown:

    log_format  main  '$remote_addr - [$upstream_addr] $remote_user [$time_local] $request '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  logs/access.log  main;

Also change the log format to "main" by uncommenting "access_log logs/access.log main;" line as shown above (default format is "combined"). Accessing "http://localhost/runlogs" shows the following lines in "logs/access.log":

127.0.0.1 - [127.0.0.1:3000] - [29/Apr/2009:15:27:57 -0700] GET /runlogs/ HTTP/1.1 "200" 3689 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3001] - [29/Apr/2009:15:27:57 -0700] GET /favicon.ico HTTP/1.1 "200" 0 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3002] - [29/Apr/2009:15:27:57 -0700] GET /stylesheets/scaffold.css?1240977992 HTTP/1.1 "200" 889 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"

The browser makes multiple requests (3 in this case) to load resources on a page and they are nicely load-balanced on the cluster. If an instance running on port 3002 is killed, then the access log show the entries like:

127.0.0.1 - [127.0.0.1:3000] - [29/Apr/2009:15:28:53 -0700] GET /runlogs/ HTTP/1.1 "200" 3689 "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3002, 127.0.0.1:3000] - [29/Apr/2009:15:28:53 -0700] GET /favicon.ico HTTP/1.1 "200" 0 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"
127.0.0.1 - [127.0.0.1:3001] - [29/Apr/2009:15:28:53 -0700] GET /stylesheets/scaffold.css?1240977992 HTTP/1.1 "200" 889 "http://localhost/runlogs/" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1" "-"

The second log line shows that server running on port 3002 did not respond and so it automatically fall back to 3000, this is nice!

But this is inefficient because a back-end trip is made even for serving a static file ("/favicon.ico" and "/stylesheets/scaffold.css?1240977992"). This can be easily solved by enabling Rails page caching as described here and here.

More options about logging are described in NginxHttpLogModule and upstream module variables are defined in NginxHttpUpstreamModule.

Here are some nginx resources:
Are you using nginx to front-end your GlassFish cluster ?

Apache + JRuby + Rails + GlassFish = Easy Deployment! shows similar steps if you want to front-end your Rails application running using JRuby/GlassFish with Apache.

Hear all about it in Develop with Pleasure, Deploy with Fun: GlassFish and NetBeans for a Better Rails Experience session at Rails Conf next week.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: rubyonrails glassfish v3 gem jruby nginx loadbalancing clustering

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090320 Friday March 20, 2009

TOTD # 76: JRuby 1.2, Rails 2.3, GlassFish Gem 0.9.3, ActiveRecord JDBC Adapter 0.9.1 - can they work together ?


Oh, what a week for the JRuby, Rails, and GlassFish enthusiasts!

JRuby 1.2, Rails 2.3GlassFish Gem 0.9.3, and ActiveRecord JDBC Adapater 0.9.1 - all released earlier this week. This is an opportune moment to run the integration tests to ensure the latest JRuby and GlassFish versions work nicely with each other.

First, lets see whats there to get exicted in each release.

JRuby 1.2 introduces a new versioning scheme by jumping from 1.1.6 -> 1.2. JRUBY-3649 is an important fix for the Windows users. Improved Ruby 1.9 support, 3-6x faster parsing, and preliminary android support are some other highlights. 1052 revisions and 256 bugfixes since 1.1.6 (89 days ago) means close to 12 revisions / day and 3 bugfixes/day!

Rails 2.3 has a bunch of highlights ranging from Rack integration, nested forms, attributes, and transactions, reconnecting lost MySQL connections, Application controller renamed (make sure to "rake rails:update:action_controller" to update from an older version), faster boot time in dev mode using lazy loading, and many others. The Release Notes provide all the detailed information.

The GlassFish Gem with features like running as daemon,  rake-style configuration of JVM options, ability to "sudo install" gem and run as normal user and multi-level logging are all gearing towards adding more production-quality features. My favorite here is running as daemon since that brings the Gem one step closer to the Rails community.

Lets get back to running our tests #1, #2, #3, #4, and #5 for these released versions.

First, lets unzip JRuby 1.2 and install Rails 2.3, GlassFish Gem 0.9.3, and other gems as:

~/tools/jruby-1.2.0 >./bin/jruby -S gem install rails glassfish activerecord-jdbcmysql-adapter
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed activesupport-2.3.2
Successfully installed activerecord-2.3.2
Successfully installed actionpack-2.3.2
Successfully installed actionmailer-2.3.2
Successfully installed activeresource-2.3.2
Successfully installed rails-2.3.2
Successfully installed rack-0.9.1
Successfully installed glassfish-0.9.3-universal-java
Successfully installed activerecord-jdbc-adapter-0.9.1
Successfully installed jdbc-mysql-5.0.4
Successfully installed activerecord-jdbcmysql-adapter-0.9.1
11 gems installed
Installing ri documentation for activesupport-2.3.2...
Installing ri documentation for activerecord-2.3.2...
Installing ri documentation for actionpack-2.3.2...
Installing ri documentation for actionmailer-2.3.2...
Installing ri documentation for activeresource-2.3.2...
Installing ri documentation for rack-0.9.1...
Installing ri documentation for glassfish-0.9.3-universal-java...
Installing ri documentation for activerecord-jdbc-adapter-0.9.1...
Installing ri documentation for jdbc-mysql-5.0.4...
Installing ri documentation for activerecord-jdbcmysql-adapter-0.9.1...
Installing RDoc documentation for activesupport-2.3.2...
Installing RDoc documentation for activerecord-2.3.2...
Installing RDoc documentation for actionpack-2.3.2...
Installing RDoc documentation for actionmailer-2.3.2...
Installing RDoc documentation for activeresource-2.3.2...
Installing RDoc documentation for rack-0.9.1...
Installing RDoc documentation for glassfish-0.9.3-universal-java...
Installing RDoc documentation for activerecord-jdbc-adapter-0.9.1...
Installing RDoc documentation for jdbc-mysql-5.0.4...
Installing RDoc documentation for activerecord-jdbcmysql-adapter-0.9.1...

If you have a previous version of GlassFish gem installed, then update it as:

~/tools/jruby-1.1.6 >./bin/jruby -S gem update glassfish
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Updating installed gems
Updating glassfish
Successfully installed glassfish-0.9.3-universal-java
Gems updated: glassfish

Similarly ActiveRecord gem can be updated as:

~/tools/jruby-1.1.6 >./bin/jruby -S gem update activerecord
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Updating installed gems
Updating activerecord-jdbc-adapter
Successfully installed activerecord-jdbc-adapter-0.9.1
Updating activerecord-jdbcmysql-adapter
Successfully installed activerecord-jdbcmysql-adapter-0.9.1
Updating activerecord-jdbcsqlite3-adapter
Successfully installed jdbc-sqlite3-3.6.3.054
Successfully installed activerecord-jdbcsqlite3-adapter-0.9.1
Updating merb_activerecord
Successfully installed merb_activerecord-1.0.0.1
Gems updated: activerecord-jdbc-adapter, activerecord-jdbcmysql-adapter, jdbc-sqlite3, activerecord-jdbcsqlite3-adapter, merb_activerecord

Running test #1 encounters JRUBY-3502, basically "db:create" is not working with JRuby 1.2.0, Rails 2.3.2 and MySQL ActiveRecord JDBC Adapter. However "db:create" works if JRuby 1.2.0 and Rails 2.2.2 are used. Alternatively SQLite3 ActiveRecord JDBC Adapter may be used. So first lets install SQLite3 JDBC adapter as:

~/tools/jruby-1.2.0 >./bin/jruby -S gem install activerecord-jdbcsqlite3-adapter
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed jdbc-sqlite3-3.6.3.054
Successfully installed activerecord-jdbcsqlite3-adapter-0.9.1
2 gems installed
Installing ri documentation for jdbc-sqlite3-3.6.3.054...
Installing ri documentation for activerecord-jdbcsqlite3-adapter-0.9.1...
Installing RDoc documentation for jdbc-sqlite3-3.6.3.054...
Installing RDoc documentation for activerecord-jdbcsqlite3-adapter-0.9.1...

Now lets recreate our application without specifying "-d mysql" switch as:

~/tools/jruby-1.2.0/samples/rails >../../bin/jruby -S rails runner
      create 
      create  app/controllers
      create  app/helpers
. . .
      create  log/production.log
      create  log/development.log
      create  log/test.log

In the generated "config/database.yml", change the database adapter from:

development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

to

development:
  adapter: jdbcsqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

The changes are highlighted in bold. Run the remainder of test #1.

The supported Rails version on GlassFish v3 Prelude is Rails 2.1 so we'll stick with running a Rails 2.1 (instead of Rails 2.3.2) simple scaffold application but will use the latest JRuby 1.2.0. Running a Rails 2.3.2 on GlassFish v3 Prelude will encounter issue #7384. Please add your comments to the bug report if you are running GlassFish v3 Prelude in production and would like this bug to be fixed!

Rails 2.3.2 require workaround for a WAR-based deployment of a Rails application as expained here. This workaround is required only if you are using JRuby-Rack 0.9.1 or lower. A newer version of JRuby-Rack may solve these problems making these steps optional. The steps are anyway outlined below for convenience:
  1. Uncomment the following line from "config/initializers/session_initializers.rb":

    ActionController::Base.session_store = :active_record_store
  2. Do "jruby -S warble config" to generate the template "config/warble.rb", edit it and add the following line:

    config.webxml.jruby.session_store = 'db'
  3. In "config/environment.rb", add the following code:

     if defined?(JRUBY_VERSION)
     # hack to fix jruby-rack's incompatibility with rails edge
     module ActionController
       module Session
         class JavaServletStore
           def initialize(app, options={}); end
           def call(env); end
         end
       end
     end
    end 

    just above the line "Rails::Initializer.run do |config|".
Always refer to JRuby/Rails 2.3.2 wiki for the latest information on these steps.

The deployment goes fine after making the changes but bringing up the scaffold page in the browser shows the following error message:


So commented the "jndi" and "driver" entry from "config/database.yml" such that the bundled MySQL JDBC Adapter is used instead. And then the test passes.

Here is a status report after running all the tests:

Test # Description Status
#1 Simple Scaffold using GlassFish Gem PASS (with workaround in JRUBY-3502)
#2 Simple Scaffold using GlassFish v3 Prelude PASS
#3 Simple Scaffold using GlassFish v3 FAIL (used workaround mentioned in JRUBY-3502,  issues #7266, #7270, #7271 still need to be fixed). PASS if the Application and Controller name are different.
#4 Simple Scaffold as WAR-based application on GlassFish v2.1 FAIL (issue #7385), PASS (with workaround in issue JRUBY-3515)
#5 Redmine using GlassFish Gem PASS

It's certainly exciting to know that @grantmichaels is already using the latest version of GlassFish Gem and Rails in production :)

JRuby/GlassFish Wiki provide a list of other known JRuby/Rails/GlassFish deployments in production. Leave a comment on this blog if you are using it as well and we'll be happy to add your name!

The complete set of tests are available using the tags rubyonrails+glassfish+integrationtest. So to answer the title of this blog - YES, JRuby 1.2.0, Rails 2.3.2, GlassFish Gem 0.9.3, ActiveRecord JDBC Adapater 0.9.1 all work together with the restrictions stated above. GlassFish v3 is a moving target and the bugs will be fixed soon. JRUBY-3515 is what delayed this entry otherwise would've posted it much earlier ;-)

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd rubyonrails glassfish v3 gem jruby sampleapp activerrecord redmine integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090316 Monday March 16, 2009

TOTD # 74: JRuby and GlassFish Integration Test #5: JRuby 1.2.0 RC2 + Rails 2.x.x + GlassFish + Redmine


TOTD #70, #71, #72, #73 shows four integration tests that can ensure that the latest JRuby and GlassFish versions work nicely with each other.

#70 showed how to create a trivial Rails application and run it using GlassFish Gem#71 showed how the same application can be deployed on GlassFish v3 Prelude#72 showed how to deploy the same application on GlassFish v3. #73 showed how to deploy a Rails application as WAR file and use the JDBC connection pooling framework available in GlassFish.

The next set of tests ensure that some commonly used open source Rails applications can be easily run using this setup. The first one is Redmine - 0.8 is the stable release now. Redmine was first tried on GlassFish a few months ago. The steps have simplified since then :)

Lets begin integration test #5.

  1. Download Redmine 0.8 ...

    /samples/jruby/redmine >svn co http://redmine.rubyforge.org/svn/branches/0.8-stable redmine-0.8
    A    redmine-0.8/test
    A    redmine-0.8/test/unit
    A    redmine-0.8/test/unit/document_test.rb
    A    redmine-0.8/test/unit/token_test.rb
    . . .
    A    redmine-0.8/public/stylesheets/scm.css
    A    redmine-0.8/public/stylesheets/application.css
    A    redmine-0.8/public/favicon.ico
     U   redmine-0.8
    Checked out revision 2580.
  2. Copy "config/database.yml.example" to "config/database.yml" and then generate/migrate the database:

    ~/samples/jruby/redmine/redmine-0.8 >../jruby-1.2.0RC2/bin/jruby -S rake db:create
    (in /Users/arungupta/samples/jruby/redmine/redmine-0.8)
    ~/samples/jruby/redmine/redmine-0.8 >../jruby-1.2.0RC2/bin/jruby -S rake db:migrate
    (in /Users/arungupta/samples/jruby/redmine/redmine-0.8)
    == 1 Setup: migrating =========================================================
    -- create_table("attachments", {:force=>true})
       -> 0.0880s
    -- create_table("auth_sources", {:force=>true})
       -> 0.1430s
    . . .
    == 100 AddChangesetsUserId: migrating =========================================
    -- add_column(:changesets, :user_id, :integer, {:default=>nil})
       -> 0.0980s
    == 100 AddChangesetsUserId: migrated (0.0990s) ================================

    == 101 PopulateChangesetsUserId: migrating ====================================
    == 101 PopulateChangesetsUserId: migrated (0.0030s) ===========================

  3. Redmine is a Rails 2.1.x application so install Rails 2.1.x using JRuby 1.2 and run the application as:

    ~/samples/jruby/redmine/redmine-0.8 >../jruby-1.2.0RC2/bin/jruby -S glassfish
    Mar 13, 2009 11:14:59 AM com.sun.enterprise.glassfish.bootstrap.ASMainStatic findDerbyClient
    INFO: Cannot find javadb client jar file, jdbc driver not available
    Mar 13, 2009 11:14:59 AM APIClassLoaderService createAPIClassLoader
    INFO: APIClassLoader = java.net.URLClassLoader@59fb8de1
    . . .
    Mar 13, 2009 11:15:10 AM com.sun.grizzly.pool.DynamicPool$1 run
    INFO: New instance created in 10,175 milliseconds
    Mar 13, 2009 11:15:10 AM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3  startup time : Static(356ms) startup services(11456ms) total(11812ms)

    Very simple and seamless!
The application is now accessible at "http://locahost:3000". The following screen dumps are captured by traversing through different parts of the application:















The next blog will show the last test in this series. The current set of tests are available using the tags rubyonrails+glassfish+integrationtest.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd rubyonrails glassfish v3 gem jruby sampleapp redmine integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090311 Wednesday March 11, 2009

TOTD # 73: JRuby and GlassFish Integration Test #4: JRuby 1.2.0 RC2 + Rails 2.2.x + GlassFish v2 + Warbler


TOTD #70, #71, #72 shows the first three integration tests that I typically run to ensure that the latest JRuby and GlassFish versions work nicely with each other.  #70 showed how to create a trivial Rails application and run it using GlassFish Gem#71 showed how the same application can be deployed on GlassFish v3 Prelude#72 showed how to deploy the same application on GlassFish v3.

The next test in the series is to ensure WAR-based deployment of a Rails application continue to work on GlassFish v2. It also shows that JNDI database connection pooling also work as expected. The latest publicly available build is GlassFish v2.1.

Lets begin integration test #4.

  1. Install Warbler gem ...

    ~/tools/jruby-1.2.0RC2/samples/rails/runner >../../../bin/jruby -S gem install warbler
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
    Successfully installed warbler-0.9.12
    1 gem installed
    Installing ri documentation for warbler-0.9.12...
    Installing RDoc documentation for warbler-0.9.12...
  2. Edit "config/database.yml" and change the production database adapater from:

    production:
      adapter: mysql
      encoding: utf8
      database: runner_production
      pool: 5
      username: root
      password:
      socket: /tmp/mysql.sock

    to

    production:
      adapter: jdbcmysql
      encoding: utf8
      database: runner_production
      pool: 5
      username: duke
      password: glassfish
      socket: /tmp/mysql.sock
      jndi: jdbc/runner_production
      driver: com.mysql.jdbc.Driver

    The changes are highlighted in bold.

    Notice "jndi" key/value pair is specified along with "username" and "password". The JNDI reference is created for the GlassFish domain later. The reference is not resolved when this adapter is used with the JRuby CLI and so it falls back to username/password. However this JNDI reference is correctly resolved during runtime when the application is deployed as a WAR file in GlassFish.
  3. Create and migrate the production database as:

    ~/tools/jruby-1.2.0RC1/samples/rails/runner >../../../bin/jruby -S rake db:create RAILS_ENV=production
    (in /Users/arungupta/tools/jruby-1.2.0RC1/samples/rails/runner)
    ~/tools/jruby-1.2.0RC1/samples/rails/runner >../../../bin/jruby -S rake db:migrate RAILS_ENV=production
    (in /Users/arungupta/tools/jruby-1.2.0RC1/samples/rails/runner)
    ==  CreateRunners: migrating ==================================================
    -- create_table(:runners)
       -> 0.1150s
       -> 0 rows
    ==  CreateRunners: migrated (0.1170s) =========================================

    Note, how "RAILS_ENV=production" is specified at the command-line to ensure the production environment.
  4. Copy MySQL Connector/J jar in GLASSFISH_HOME/lib as:

    ~/tools/glassfish/v2.1/glassfish/ >cp ~/tools/mysql-connector-java-5.1.6/mysql-connector-java-5.1.6-bin.jar ./lib

    This is required for connection to the MySQL database.
  5. Fire up GlassFish v2.1 as:

    ~/tools/glassfish/v2.1/glassfish/bin >./asadmin start-domain
    Starting Domain domain1, please wait.
    Default Log location is /Users/arungupta/tools/glassfish/v2.1/glassfish/domains/domain1/logs/server.log.
    Redirecting output to /Users/arungupta/tools/glassfish/v2.1/glassfish/domains/domain1/logs/server.log
    Domain domain1 started.
    Domain [domain1] is running [Sun GlassFish Enterprise Server v2.1 (9.1.1) (build b60e-fcs)] with its configuration and logs at: [/Users/arungupta/tools/glassfish/v2.1/glassfish/domains].
    Admin Console is available at [http://localhost:4848].
    Use the same port [4848] for "asadmin" commands.
    User web applications are available at these URLs:
    [http://localhost:8080 https://localhost:8181 ].
    Following web-contexts are available:
    [/web1  /__wstx-services runner ].
    Standard JMX Clients (like JConsole) can connect to JMXServiceURL:
    [service:jmx:rmi:///jndi/rmi://Macintosh-187.local:8686/jmxrmi] for domain management purposes.
    Domain listens on at least following ports for connections:
    [8080 8181 4848 3700 3820 3920 8686 ].
    Domain supports application server clusters and other standalone instances.

    The logs are created in "domains/domain1/logs/server.log". Optionally, you can specify "--verbose" on the command-line to dump the log on the console itself.
  6. Create JDBC connection pool as:

    ~/tools/glassfish/v2.1/glassfish/bin >./asadmin create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource --restype javax.sql.DataSource --property "User=duke:Password=glassfish:URL=jdbc\:mysql\://localhost/runner_production" jdbc/runner_pool
    Command create-jdbc-connection-pool executed successfully.

  7. Create JDBC resource as:

    ~/tools/glassfish/v2.1/glassfish/bin >./asadmin create-jdbc-resource --connectionpoolid jdbc/runner_pool jdbc/runner_production
    Command create-jdbc-resource executed successfully.
  8. Create Warbler config file as:

    ~/tools/jruby-1.2.0RC2/samples/rails/runner >../../../bin/jruby -S warble config
    cp /Users/arungupta/tools/jruby-1.2.0RC2/lib/ruby/gems/1.8/gems/warbler-0.9.12/generators/warble/templates/warble.rb config/warble.rb
  9. Edit "config/warble.rb" to bundle the required gems by adding the following fragment:

     # Include all gems which are used by the web application
      require "#{RAILS_ROOT}/config/environment"
      BUILD_GEMS = %w(warbler rake rcov)
      for gem in Gem.loaded_specs.values
        next if BUILD_GEMS.include?(gem.name)
        config.gems[gem.name] = gem.version.version
      end

    as specified here. And then explicitly specify the runtime gem dependency by adding the following line:

    config.gems += ["activerecord-jdbc-adapter"]

    right after the previous code fragment. The "activerecord-jdbc-adapter" dependency needs to be explicitly included because this is required only at the runtime and so not resolved correctly by the previous code fragment.
  10. And create the WAR file as:

    ~/tools/jruby-1.2.0RC2/samples/rails/runner >../../../bin/jruby -S warble
    mkdir -p tmp/war/WEB-INF/gems/specifications
    cp /Users/arungupta/tools/jruby-1.2.0RC2/lib/ruby/gems/1.8/specifications/rails-2.2.2.gemspec tmp/war/WEB-INF/gems/specifications/rails-2.2.2.gemspec
    mkdir -p tmp/war/WEB-INF/gems/gems
    . . .
    cp public/javascripts/prototype.js tmp/war/javascripts/prototype.js
    cp public/stylesheets/scaffold.css tmp/war/stylesheets/scaffold.css
    mkdir -p tmp/war/WEB-INF
  11. Deploy the WAR file ...

    ~/tools/jruby-1.2.0RC2/samples/rails/runner >~/tools/glassfish/v2.1/glassfish/bin/asadmin deploy runner.war
    Command deploy executed successfully.

    After adding few entries the page at "http://localhost:8080/runner/runners" looks like:


So we are able to deploy a trivial Rails application as WAR file on GlassFish v2.1 and also leverage the JDBC connection pooling, that passes Test# 4.

Later blogs will show the remainder of tests. The current set of tests are available using the tags rubyonrails+glassfish+integrationtest.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd rubyonrails glassfish v2 jruby warbler connectionpooling jdbc jndi integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090309 Monday March 09, 2009

TOTD # 72: JRuby and GlassFish Integration Test #3: JRuby 1.2.0 RC2 + Rails 2.2.x + GlassFish v3


TOTD #70 and #71 shows the first two integration tests that I typically run to ensure that the latest JRuby and GlassFish versions work nicely with each other.  #70 showed how to create a trivial Rails application and run it using GlassFish Gem. #71 showed how the same application can be deployed on GlassFish v3 Prelude.

The third test (explained in this blog) ensures that the same application can be easily deployed using GlassFish v3. GlassFish v3 will be available later this year with full support for Java EE 6.

JRuby 1.2.0 RC2 is now released. Test #1 passed, Test #2 gives the following error:

Caused by: java.lang.NumberFormatException: For input string: "0RC2"
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
        at java.lang.Integer.parseInt(Integer.java:456)
        at java.lang.Integer.parseInt(Integer.java:497)
        at com.sun.grizzly.jruby.RailsAdapter$JRubyVersion.<init>(RailsAdapter.java:137)
        at com.sun.grizzly.jruby.RailsAdapter$JRubyVersion.<init>(RailsAdapter.java:131)
        at com.sun.grizzly.jruby.RailsAdapter.<init>(RailsAdapter.java:110)
        at com.sun.grizzly.jruby.RubyRuntime.<init>(RubyRuntime.java:48)
        ... 22 more

However running the same application using JRuby trunk (rev 9372) shows the following output:



So test #2 passes with trunk but fails with RC2 bits. The final release of 1.2 will not have any characters and so this test will pass with the final JRuby 1.2 bits.

Now, lets begin the integration test #3.
  1. Download and unzip the latest GlassFish v3, b39 is the latest at time of this writing. Fire up GlassFish v3 as:

    ~/tools/glassfish/v3/b39/glassfishv3/glassfish >./bin/asadmin start-domain
    Name of the domain started: [domain1] and
    its location: [/Users/arungupta/tools/glassfish/v3/b39/glassfishv3/glassfish/domains/domain1].
    Admin port for the domain: [4848].
  2. Add JRUBY_HOME as "jvm-option" using the following command:

    ~/tools/glassfish/v3/b39/glassfishv3/glassfish >./bin/asadmin create-jvm-options -DJRUBY_HOME="/Users/arungupta/tools/jruby-1.2.0RC2"
    created 1 option(s)

    Command create-jvm-options executed successfully.

    This tells the GlassFish runtime to pick JRuby and related libraries from the directory specified in JRUBY_HOME.
  3. Deploy the application as:

    ~/tools/jruby-1.2.0RC1/samples/rails >~/tools/glassfish/v3/b39/glassfishv3/bin/asadmin deploy runner

    Command deploy executed successfully.
  4. Accessing "http://localhost:8080/runner/runners" gives the error:

    ActionController::RoutingError (No route matches "s" with {:method=>:get}):
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/routing/recognition_optimisation.rb:66:in `recognize_path'
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/routing/route_set.rb:386:in `recognize'
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/dispatcher.rb:182:in `handle_request'
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/dispatcher.rb:110:in `dispatch_unlocked'
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/dispatcher.rb:123:in `dispatch'
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/dispatcher.rb:122:in `dispatch'
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/dispatcher.rb:132:in `dispatch_cgi'
        /Users/arungupta/tools/jruby-1.2.0RC1/lib/ruby/gems/1.8/gems/actionpack-2.2.2/lib/action_controller/dispatcher.rb:39:in `dispatch'
        file:/Users/arungupta/tools/glassfish/v3/b39/glassfishv3/glassfish/modules/grizzly-jruby.jar!/rack/adapter/rails.rb:82:in `serve_rails'
        file:/Users/arungupta/tools/glassfish/v3/b39/glassfishv3/glassfish/modules/grizzly-jruby.jar!/rack/adapter/rails.rb:109:in `call'
        file:/Users/arungupta/tools/glassfish/v3/b39/glassfishv3/glassfish/modules/grizzly-jruby.jar!/jruby/rack/rails.rb:81:in `call'
        file:/Users/arungupta/tools/glassfish/v3/b39/glassfishv3/glassfish/modules/grizzly-jruby.jar!/rack/handler/grizzly.rb:55:in `call'
        :1

    This resulted in filing issue #7266.
  5. GlassFish v3 allows an application to be deployed/redeployed on a different context root by specifying "--contextroot" switch. Lets try to deploy the app using a different context root as shown below:

    ~/tools/jruby-1.2.0RC1/samples/rails >~/tools/glassfish/v3/b39/glassfishv3/bin/asadmin deploy --contextroot runlog --force=true runner

    Command deploy executed successfully.

    Even though the application is deployed successful, but now "http://localhost:8080/runlog/runners" and "http://localhost:8080/runner/runners" give a 404. This resulted in filing issue #7270 and issue# 7271. The context root strippping does not happen correctly if a Rails application is deployed. But the good news is that a fix is already in progress. A workaround is to create exactly the same application with a different name.
  6. Recreate the application using a name different from the controller. Lets use the name "runlog" and redeploy the application as:

    ~/tools/jruby-1.2.0RC2/samples/rails >~/tools/glassfish/v3/b39/glassfishv3/bin/asadmin deploy runlog

    Command deploy executed successfully.

    After adding few entries the page at "http://localhost:8080/runlog/runners" looks like:


So test #3 fails if the Application and Controller name are same but passes if they are different. Our original application did not run so test #3 failed.

Later blogs will show the remainder of tests. The current set of tests are available using the tags rubyonrails+glassfish+integrationtest.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd rubyonrails glassfish v3 jruby gem integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090305 Thursday March 05, 2009

TOTD # 71: JRuby and GlassFish Integration Test #2: JRuby 1.2.0 RC1 + Rails 2.2.x + GlassFish v3 Prelude


TOTD #70 shows the first integration integration tests that I typically run to ensure that the latest JRuby and GlassFish versions work nicely with each other.  The second test (explained in this blog) ensures that the same application can be deployed using GlassFish v3 Prelude.

GlassFish v3 Prelude allows Rails applications to be deployed natively, i.e. without any packaging.

Lets begin integration test #2.

  1. Download and unzip GlassFish v3 Prelude. Fire up GlassFish v3 Prelude as:

    ~/tools/glassfish/v3/glassfishv3-prelude/glassfish >./bin/asadmin start-domain
    Name of the domain started: [domain1] and
    its location: [/Users/arungupta/tools/glassfish/v3/glassfishv3-prelude/glassfish/domains/domain1].
    Admin port for the domain: [4848].
  2. Add JRUBY_HOME as "jvm-option" using the following command:

    ~/tools/glassfish/v3/glassfishv3-prelude/glassfish >./bin/asadmin create-jvm-options -DJRUBY_HOME="/Users/arungupta/tools/jruby-1.2.0RC1"
    created 1 option(s)

    Command create-jvm-options executed successfully.

    This tells the GlassFish runtime to pick JRuby and related libraries from the directory specified in JRUBY_HOME.
  3. Deploy the application as:

    ~/tools/jruby-1.2.0RC1/samples/rails >~/tools/glassfish/v3/glassfishv3-prelude/bin/asadmin deploy runner

    Command deploy executed successfully.

  4. The application should now be accessible on "http://localhost:8080/runner/runners". But instead the logs (located in "domains/domain1/logs/server.log) shows the following exception:

    Caused by: java.lang.NumberFormatException: For input string: "0RC1"
            at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
            at java.lang.Integer.parseInt(Integer.java:456)
            at java.lang.Integer.parseInt(Integer.java:497)
            at com.sun.grizzly.jruby.RailsAdapter$JRubyVersion.<init>(RailsAdapter.java:137)
            at com.sun.grizzly.jruby.RailsAdapter$JRubyVersion.<init>(RailsAdapter.java:131)
            at com.sun.grizzly.jruby.RailsAdapter.<init>(RailsAdapter.java:110)
            at com.sun.grizzly.jruby.RubyRuntime.<init>(RubyRuntime.java:48)
            ... 30 more

    This is filed as issue #7235 in GlassFish Issue Tracker.
  5. Lets try with the JRuby trunk.
    1. Check out JRuby trunk and build the workspace as shown below

      ~/workspaces >svn co http://svn.codehaus.org/jruby/trunk/jruby/
      A    jruby/bench
      A    jruby/bench/bench_tak.rb
      A    jruby/bench/bench_struct.rb

      . . .

      A    jruby/.settings/org.eclipse.jdt.core.prefs
      A    jruby/.settings/org.eclipse.jdt.ui.prefs
       U   jruby
      Checked out revision 9347.
      ~/workspaces >cd jruby/
      ~/workspaces/jruby >ant
      Buildfile: build.xml

      init:

      jar:

      . . .

      _update_scm_revision_:
            [jar] Building jar: /Users/arungupta/workspaces/jruby/lib/jruby.jar
            [jar] Warning: selected jar files include a META-INF/INDEX.LIST which will be replaced by a newly generated one.

      BUILD SUCCESSFUL
      Total time: 1 minute 21 seconds
    2. Install Rails

      ~/workspaces/jruby >./bin/jruby gem install rails
      JRuby limited openssl loaded. gem install jruby-openssl for full support.
      http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
      Successfully installed rake-0.8.4
      Successfully installed activesupport-2.2.2
      Successfully installed activerecord-2.2.2
      Successfully installed actionpack-2.2.2
      Successfully installed actionmailer-2.2.2
      Successfully installed activeresource-2.2.2
      Successfully installed rails-2.2.2
      7 gems installed
      Installing ri documentation for rake-0.8.4...
      Installing ri documentation for activesupport-2.2.2...
      Installing ri documentation for activerecord-2.2.2...
      Installing ri documentation for actionpack-2.2.2...
      Installing ri documentation for actionmailer-2.2.2...
      Installing ri documentation for activeresource-2.2.2...
      Installing RDoc documentation for rake-0.8.4...
      Installing RDoc documentation for activesupport-2.2.2...
      Installing RDoc documentation for activerecord-2.2.2...
      Installing RDoc documentation for actionpack-2.2.2...
      Installing RDoc documentation for actionmailer-2.2.2...
      Installing RDoc documentation for activeresource-2.2.2...
  6. Delete the previously added jvm-option as

    ~/tools/glassfish/v3/glassfishv3-prelude/glassfish >./bin/asadmin delete-jvm-options -DJRUBY_HOME="/Users/arungupta/tools/jruby-1.2.0RC1"
    deleted 1 option(s)

    Command delete-jvm-options executed successfully.

    and add a new jvm-option pointing to the the new JRUBY_HOME as

    ~/tools/glassfish/v3/glassfishv3-prelude/glassfish >./bin/asadmin create-jvm-options -DJRUBY_HOME="/Users/arungupta/workspaces/jruby"
    created 1 option(s)

    Command create-jvm-options executed successfully.
  7. Deploy the application as:

    ~/tools/jruby-1.2.0RC1/samples/rails >~/tools/glassfish/v3/glassfishv3-prelude/bin/asadmin deploy --force=true runner

    Command deploy executed successfully.

    The "NumberFormatException" as seen above is shown again in this case.

    If the application is deployed correctly then "http://localhost:8080/runner/runners" will show the scaffold page. The final JRuby 1.2 release will not have any text letters in the version and so you'll be able to deploy a Rails application using JRuby 1.2 (final release) on GlassFish v3 Prelude.
But for now our test #2 has failed.

Subsequent blogs will show the remainder of tests. The current set of tests are available using the tags rubyonrails+glassfish+integrationtest.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd rubyonrails glassfish v3 jruby gem integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090303 Tuesday March 03, 2009

TOTD # 70: JRuby and GlassFish Integration Test# 1: JRuby 1.2.0 RC1 + Rails 2.2.x + GlassFish Gem


JRuby 1.2.0 RC1 is out for a while!

I typically run a series of tests to ensure that any publicly released version of JRuby works nicely with GlassFish. The main goal of running these tests is to discover any blocking bugs before users do. This particular set of tests are being run little late as RC1 was released on Feb 24th. But I'll describe all the steps clearly in the next few blog entries so that you can try them out yourself.

JRuby team runs a whole slew of tests before releasing any bits. Similarly we run a bunch of tests before releasing GlassFish Gem. These tests, as mentioned earlier, are only to ensure that the latest release of JRuby works nicely with the latest bits of GlassFish.

The first basic test is to check if a simple Rails application can be run using the latest GlassFish Gem. The steps are described next.

First, lets create a database user and grant privileges required by our application:

~/tools >sudo mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 30
Server version: 5.1.30 MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> create user duke@localhost identified by 'glassfish';
Query OK, 0 rows affected (0.00 sec)

mysql> grant all on runner_development.* to duke@localhost identified by 'glassfish';
Query OK, 0 rows affected (0.03 sec)

mysql> grant all on runner_production.* to duke@localhost identified by 'glassfish';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> exit;
Bye

The "runner_development" and "runner_production" databases will be created later. And the database are dropped and created fresh for every test run.

Now lets try to create our first Rails application using JRuby and run it using GlassFish gem:
  1. Download and unzip JRuby 1.2.0 RC1.
  2. Install Rails and GlassFish Gem as:

    ~/tools/jruby-1.2.0RC1 >./bin/jruby -S gem install rails glassfish
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
    Successfully installed activesupport-2.2.2
    Successfully installed activerecord-2.2.2
    Successfully installed actionpack-2.2.2
    Successfully installed actionmailer-2.2.2
    Successfully installed activeresource-2.2.2
    Successfully installed rails-2.2.2
    Successfully installed rack-0.9.1
    Successfully installed glassfish-0.9.2-universal-java
    8 gems installed
    Installing ri documentation for activesupport-2.2.2...
    Installing ri documentation for activerecord-2.2.2...
    Installing ri documentation for actionpack-2.2.2...
    Installing ri documentation for actionmailer-2.2.2...
    Installing ri documentation for activeresource-2.2.2...
    Installing ri documentation for rack-0.9.1...
    Installing ri documentation for glassfish-0.9.2-universal-java...
    Installing RDoc documentation for activesupport-2.2.2...
    Installing RDoc documentation for activerecord-2.2.2...
    Installing RDoc documentation for actionpack-2.2.2...
    Installing RDoc documentation for actionmailer-2.2.2...
    Installing RDoc documentation for activeresource-2.2.2...
    Installing RDoc documentation for rack-0.9.1...
    Installing RDoc documentation for glassfish-0.9.2-universal-java...
  3. Create a new app as:

    ~/tools/jruby-1.2.0RC1/samples/rails >../../bin/jruby -S rails runner -d mysql
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
          create 
          create  app/controllers
          create  app/helpers
          . . .
          create  log/server.log
          create  log/production.log
          create  log/development.log
          create  log/test.log
  4. Install MySQL JDBC ActiveRecord adapter as:

    ~/tools/jruby-1.2.0RC1/samples/rails >../../bin/jruby -S gem install activerecord-jdbcmysql-adapter
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
    Successfully installed activerecord-jdbc-adapter-0.9
    Successfully installed jdbc-mysql-5.0.4
    Successfully installed activerecord-jdbcmysql-adapter-0.9
    3 gems installed
    Installing ri documentation for activerecord-jdbc-adapter-0.9...
    Installing ri documentation for jdbc-mysql-5.0.4...
    Installing ri documentation for activerecord-jdbcmysql-adapter-0.9...
    Installing RDoc documentation for activerecord-jdbc-adapter-0.9...
    Installing RDoc documentation for jdbc-mysql-5.0.4...
    Installing RDoc documentation for activerecord-jdbcmysql-adapter-0.9...

    More details on configuring this adapter here.
  5. Create a simple scaffold:

    ~/tools/jruby-1.2.0RC1/samples/rails/runner >../../../bin/jruby script/generate scaffold runner distance:float time:integer
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
          exists  app/models/
          exists  app/controllers/
          . . .
          create    test/fixtures/runners.yml
          create    db/migrate
          create    db/migrate/20090226171752_create_runners.rb
  6. Edit "config/database.yml" to use the JDBC adapter and specify database username/password. Change:

    development:
      adapter: mysql
      encoding: utf8
      database: runner_development
      pool: 5
      username: root
      password:
      socket: /tmp/mysql.sock

    to

    development:
      adapter: jdbcmysql
      encoding: utf8
      database: runner_development
      pool: 5
      username: duke
      password: glassfish
      socket: /tmp/mysql.sock

    The change is highlighted in bold letters.
  7. Create and migrate the database as:

    ~/tools/jruby-1.2.0RC1/samples/rails/runner >../../../bin/jruby -S rake db:create
    (in /Users/arungupta/tools/jruby-1.2.0RC1/samples/rails/runner)
    ~/tools/jruby-1.2.0RC1/samples/rails/runner >../../../bin/jruby -S rake db:migrate
    (in /Users/arungupta/tools/jruby-1.2.0RC1/samples/rails/runner)
    ==  CreateRunners: migrating ==================================================
    -- create_table(:runners)
       -> 0.1330s
       -> 0 rows
    ==  CreateRunners: migrated (0.1340s) =========================================

    The default RAILS_ENV is DEVELOPMENT so there is no need to specify any addtional arguments.
  8. And then run the application as:

    ~/tools/jruby-1.2.0RC1/samples/rails/runner >../../../bin/jruby -S glassfish
    Feb 26, 2009 10:30:10 AM com.sun.enterprise.glassfish.bootstrap.ASMainStatic start
    INFO: Cache not present, will revert to less efficient algorithm
    Feb 26, 2009 10:30:10 AM com.sun.enterprise.glassfish.bootstrap.ASMainStatic findDerbyClient
    INFO: Cannot find javadb client jar file, jdbc driver not available
    Feb 26, 2009 10:30:10 AM APIClassLoaderService createAPIClassLoader
    INFO: APIClassLoader = java.net.URLClassLoader@14a66e3f
    no resource bundle found for version, using default GlassFish version
    Feb 26, 2009 10:30:11 AM AppServerStartup run
    INFO: [Thread[GlassFish Kernel Main Thread,5,main]] started
    Feb 26, 2009 10:30:11 AM com.sun.enterprise.v3.services.impl.GrizzlyProxy start
    INFO: Listening on port 3000
    Feb 26, 2009 10:30:11 AM com.sun.enterprise.v3.admin.adapter.AdminEndpointDecider setGuiContextRoot
    INFO: Admin Console Adapter: context root: /_____admingui
    Feb 26, 2009 10:30:11 AM com.sun.enterprise.v3.admin.adapter.AdminConsoleAdapter setStateMsg
    INFO: The Admin Console Application is not yet installed.
    Feb 26, 2009 10:30:11 AM com.sun.enterprise.v3.admin.adapter.AdminEndpointDecider setGuiContextRoot
    INFO: Admin Console Adapter: context root: /_____admingui
    Feb 26, 2009 10:30:11 AM org.glassfish.scripting.rails.RailsDeployer load
    INFO: Loading application runner at /
    Feb 26, 2009 10:30:11 AM com.sun.grizzly.jruby.RailsAdapter <init>
    INFO: Jruby version is: 1.2.0RC1
    Feb 26, 2009 10:30:11 AM com.sun.grizzly.jruby.rack.RackApplicationChooser detectRails
    INFO: Detected Rails application
    Feb 26, 2009 10:30:11 AM com.sun.grizzly.jruby.rack.RackApplicationChooser detectRails
    INFO: Rails not in thread-safe mode, starting in single-thread mode
    Feb 26, 2009 10:30:11 AM com.sun.grizzly.pool.DynamicPool logDynamicStatus
    INFO: Pool started without dynamic resizing enabled. Pool will not attempt to determine the upper and lower bounds that it should be using, and will stay at 1
    Feb 26, 2009 10:30:16 AM  
    SEVERE: JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
    Feb 26, 2009 10:30:18 AM  
    INFO: RAILS_ROOT /Users/arungupta/tools/jruby-1.2.0RC1/samples/rails/runner
    Feb 26, 2009 10:30:18 AM  
    INFO: PUBLIC_ROOT /Users/arungupta/tools/jruby-1.2.0RC1/samples/rails/runner/public
    Feb 26, 2009 10:30:19 AM com.sun.grizzly.pool.DynamicPool$1 run
    INFO: New instance created in 7,074 milliseconds
    Feb 26, 2009 10:30:19 AM com.sun.enterprise.v3.server.AppServerStartup run
    INFO: GlassFish v3  startup time : Static(525ms) startup services(7962ms) total(8487ms)
    Feb 26, 2009 10:30:19 AM com.sun.enterprise.glassfish.bootstrap.ASMainStatic start
    INFO: Started cache creation
    Feb 26, 2009 10:30:20 AM com.sun.enterprise.glassfish.bootstrap.ASMainStatic start
    INFO: Finished cache creation
    Feb 26, 2009 10:30:34 AM sun.reflect.NativeMethodAccessorImpl invoke0
    INFO: 

    After adding few entries, the output at "http://localhost:3000/runners" looks like:



    So we are able to create a trivial Rails application and run it using GlassFish Gem, that passes Test#1.
The subsequent blogs will show the remainder of tests.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd rubyonrails glassfish v3 jruby gem integrationtest

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090114 Wednesday January 14, 2009

TOTD #65: Windows 7 Beta 1 Build 7000 on Virtual Box: NetBeans + Rails + GlassFish + MySQL


Microsoft released Windows 7 Beta 1 - the next major version of Vista, download here. There are tons of improvments mostly centered around making the content easily & intuitively accessible. But hey, Mac OSX already serves that purpose well for quite some time ;-)

But I still want to make sure that our Rails stack (NetBeans, GlassFish, and MySQL) work fine on it. And it very well do, without any issues, as you'll realize at the end of this blog :)

Lets first get started with installing Windows 7 Beta as a Virtual Box image. Few points to note here:

  • Only IE can be used for downloading Windows 7 Beta, FireFox & Safari on Mac do nothing (confirmed). With a growing share of both Mac and Firefox (TODO: add a link), I think this combination needs to be at least included on their testing matrix. There was no clear way to file bugs but sent feedback using "Send Feedback" button that is omnipresent on top-right corner of each window.
  • The 64-bit Windows 7 installer do not work on Virtual Box 2.1 installed on a 64-bit MacBook Pro. So had to download the 32-bit installer instead :( This seems to be a Virtual Box bug so filed #3027.
  • The 32-bit and 64-bit files are named "7000.0.081212-1400_client_en-us_Ultimate-GB1CULFRE_EN_DVD-32bit.iso" and "7000.0.081212-1400_client_en-us_Ultimate-GB1CULXFRE_EN_DVD.iso" respectively. If you noticed the only difference is the letter "X" before "FRE" . This required a deep look to spot the difference and very non-intuitive. Frankly, I had to put the two names above each other to spot the difference ;-)
Here are my Virtual Box VM settings:


Anyway, after that the install process was pretty simple. Anybody who has previous Windows install experience can vouch the installation mostly  goes seamless, as was the case here. The complete installation using screen snapshots is shown here. Some of the snapshots from my install process are shown below:









Ta da ... after multiple boots during installation, the final welcome screen shows up as following:



Even the beta install required an activation key. The key is shown on the screen after the download. A freshly installed Windows 7 Beta shows the following disk properties:



Lets install our Rails stack.

Download JDK 6 U11 (TODO: check with or w/o NetBeans), MySQL 5.1, NetBeans 6.5 (which includes GlassFish v3 Prelude, JRuby 1.1.4, Rails 2.1, and other goodies)! Alternatively, you can also download JDK 6 U11 + NetBeans 6.5 co-bundle here.

Install them in the same order by double-clicking on the downloaded bundle and taking all default values.

First MySQL installation ...



MySQL is automatically started and registered with Windows as a service.

And then NetBeans installation ...



Because of the default access controls setup in Windows 7 (as in Vista as well), NetBeans need to be run as an administrator by right-clicking, selecting "Run as administrator". Screencast #26 shows to develop, run, and debug a Rails application on GlassFish v3 Prelude. Here are some screen snapshots as the steps outlined in that screencast are performed.

Here is a snapshot that shows how a simple Rails application can be created:



Running the Rails application on GlassFish v3 Prelude ...



And now debugging using the NetBeans IDE ...



Overall, I'm happy with the first experience of Windows 7 Beta 1. The install process was smooth and it was nice to see the picture of a fish on the welcome screen. They can even consider swapping it with a glassfish ;-)

TOTD #64 showed how to install OpenSolaris 2008/11 using Virtual Box and run the same stack there. So be it Windows 7 or Open Solaris 2008/11, you can develop, run, and debug your Rails application with pleasure using NetBeans and GlassFish. And of course, Mac OS X :)

What is your primary Operating System for development ?

Do you use any Virtualization software for trying multiple Operating Systems ? Which one ?

Technorati: totd windows windows7 virtualbox netbeans glassfish mysql rubyonrails jruby

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090112 Monday January 12, 2009

TOTD #64: OpenSolaris 2008/11 using Virtual Box

Here is a blog entry that was sitting in my Drafts folder for a long time (just because I didn't realize :). Anyway, it shows how to install Open Solaris 2008/11 on Virtual Box. The original install was done using Virtual Box 2.0.6. I installed Virtual Box 2.1 this morning and the image was easily recognized by the updated Virtual Box.

Here are the basic steps.


Create a new VM ...



As part of the previous step, create a new Virtual Disk mapping to the downloaded Open Solaris image ...




The generated VM settings are shown as below:



Click on "Start" and configure for the first run as:




Boot the Virtual Macine from the LiveCD shows the following GRUB:



Take the default for Language and Keyboard and then the following screen is shown after the boot:



Click on "Install OpenSolaris" ...



Clicking on "Install" starts the installation ...



And finally the install is completed.



Click on "Reboot", select "Boot from Hard Disk" and press Enter ...



And then select if "full boot" or "text boot" is required as shown:




And the welcome screen is shown as:



Now you can develop your Rails applications using the NetBeans IDE and deploy them on GlassFish and MySQL easily as explained here. There are multiple updates to the stack described earlier - JRuby 1.1.6, Rails 2.2, MySQL Alpha 6.0.x, GlassFish v3 Prelude, and Virtual Box 2.1.

So go ahead and develop, deploy, and debug your Rails applications as described in screencast #26. You can even manage your Rails applications using JMX as described in TOTD #61, #62, and #63.

Hwo do you follow the latest on each technology:

And, of course, this blog talks about all of them :)

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd opensolaris virtualbox glassfish netbeans jruby rubyonrails mysql

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090109 Friday January 09, 2009

TOTD #63: jmx4r gem - How to manage/monitor your Rails/Merb applications on JRuby/GlassFish ?


TOTD #61 and TOTD #62 shows how to use JMX APIs to locally/remotely manage/monitor your Rails/Merb applications. This Tip Of The Day extends TOTD #62 and shows how remote management can be done using jmx4r gem.

This gem provides a clean mapping between JMX APIs and Ruby. It allows to write pure Ruby code to manage/monitor any Rails application. As a result it removes all dependency on the Java code used in TOTD #62.

Lets first install the gem!

~ >gem install jmx4r
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed jmx4r-0.0.6
1 gem installed
Installing ri documentation for jmx4r-0.0.6...
Installing RDoc documentation for jmx4r-0.0.6...

Here is the equivalent Ruby code to flush the class cache (as in TOTD #62):

require 'rubygems'
require 'jmx4r'

JMX::MBean.establish_connection :host => "129.145.133.163", :port => 8686

beans = JMX::MBean.find_all_by_name "org.jruby:*"
beans.each { |bean|
  service = bean.object_name["service"]
  case service
  when "ClassCache"
    @cc_mbean = bean
  when "Config"
    @c_mbean = bean
  end
}

# clear the cache if it's full
if @cc_mbean.full
  printf "JIT Max: %d, JIT Threshold: %d, Class load count: %d\n", @c_mbean.jit_max,
    @c_mbean.jit_threshold, @cc_mbean.class_load_count
    @cc_mbean.flush
else
  puts "Class Cache is not full"
  printf "Loaded: %d, Reused: %d, Live: %d\n", @cc_mbean.class_load_count,
    @cc_mbean.class_reuse_count, @cc_mbean.live_class_count
end

As with all Ruby code, really clean and simple!

The key parts of the code are highlighted in bold. "JMX::MBean.establish_connection" establishes a connection with a JMX agent running on a remote machine identified by the IP address and port number specified. "JMX::MBean.find_all_by_name" queries the agent for all the MBeans in "org.jruby" domain. And then the code is self explanatory.

Just dump this code in a file and run it as:

jruby main.rb

to see the output similar to:

Class Cache is not full
Loaded: 76, Reused: 0, Live: 76

Make sure Rails/Merb application is running after setting JAVA_OPTS as described in TOTD #62. For this blog, the JMX agent/Rails application ran on a Mac and the JMX client on a Solaris box.

The jmxr examples provides some more ways to use the gem.

There is also jmx gem that provides similar functionality. It even allows to create MBeans and provides a simple server where they can be registered. Tom's blog provide more details on usage and there is even a sample included.

Subsequent blogs in this series will discuss:
  • How to remotely manage your Rails/Merb applications using JMX API ?
  • How to publish your own metrics that can be managed using JMX API ?
  • How to use jmx gem to manage/monitor ?
  • How to use VisualVM to get more information about the underlying VM ?
  • How to use NewRelic/FiveRuns to manage/monitor an application ?
Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd glassfish jruby rubyonrails merb jmx jmx4r manage monitor

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.