Miles to go …

May 5, 2009

Sea Change Affinity – Why JRuby/GlassFish ?

Filed under: web2.0 — arungupta @ 8:46 pm

At Rails Conf 2009, Jay McGaffigan from Sea Change talked about why they choose JRuby/GlassFish for their product Affinity. Here are some of the reasons he quoted:

  • Performance characterisitics (of GlassFish) have been excellent
  • Picked GlassFish based upon the recommendations from the people in industry
  • Dramatically more throughput on our GlassFish installation, 400 requests/sec instead of 100 requests/sec comapred to Tomcat

Watch the interview recorded earlier today:


Read other simiar stories at glassfish+rubyonrails+stories.

Technorati: jruby rubyonrails glassfish stories

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

May 4, 2009

Rails Conf 2009 – Day 1 Trip Report

Filed under: web2.0 — arungupta @ 11:42 pm

Rails Conf 2009 started this morning. The first day consists of morning and afternoon tutorials.

I attended Nick Sieger’s JRuby on Rails tutorial, the slides are available. A survey in the room showed:

  • 95% comfortable with Ruby/Rails
  • 80% have used JRuby
  • 10% use JRuby actively

Here are some of the key points highlighted in the tutorial:

Why JRuby ?

  • JRuby is “Less Bitter Java”, after all Java is a great platform.
  • Concurrency (Native threading)
  • Reliability (well-behaved because of Hotspot compiler, no process monitoring, etc)
  • Encapsulation (take a Rails application, bundle it as a single deployable artifact that is fully contained)
  • Choice (Any Java application server, huge breadth of Java libraries, and can write thin Ruby wrappers around Java libraries)

Download JDK 5 minimum, JDK 6 preferred, MySQL 5.x, JRuby 1.2 (1.3.0 RC1 OK too), GlassFish v2.1 b60e

Common options

  • –server: Run with server VM, better performance
  • –headless: No UI
  • –properties: Show tweaks for compiler, JIT compiling,  thread pooling etc
  • -J<java-opt>: Pass any Java properties
  • -J-Xmx1G: Increase memory to 1G

Drawbacks: No fork(), No native extensions (for example ParseTree, EventMachine, RMagic cannot be used), No tty for subprocesses, Startup time slow for short scripts

Advantages: Improved versions of some Ruby APIs (tempfile, mutex, thread, timeout), 1.8 and 1.9 in a single install (jruby –1.9), Wrap Java libraries and APIs in Ruby

The slides have much more details in terms of deployment options (WAR-based, GlassFish Gem), and many other interesting details Scroll to slide #68 to understand all the guts of kenai.com – a real life application running using JRuby, Rails, and GlassFish.

The afternoon tutorial for me was A Hat Full of Tricks with Sinatra. The tutorial was completely code driven with no slides, just love that format!

The tutorial started with a brief introduction to Rack. A basic Rack application can be “config.ru” or “app.rb”, lets start with “config.ru” Hello World:

run lambda { |env|
  [
    200,
    {
    'Content-Length' => '2',
    'Content-Type' => 'text/html',
    },
    ["hi"]
  ]
}

Run it as …

~/samples/railsconf/sinatra/basic-rack >~/tools/jruby/bin/jruby -S rackup
[2009-05-04 13:40:18] INFO  WEBrick 1.3.1
[2009-05-04 13:40:18] INFO  ruby 1.8.6 (2009-03-16) [java]
[2009-05-04 13:40:18] INFO  WEBrick::HTTPServer#start: pid=90964 port=9292
127.0.0.1 – - [04/May/2009 13:40:27] “GET / HTTP/1.1″ 200 2 0.0160
127.0.0.1 – - [04/May/2009 13:40:27] “GET /favicon.ico HTTP/1.1″ 200 2 0.0060
127.0.0.1 – - [04/May/2009 13:40:30] “GET /favicon.ico HTTP/1.1″ 200 2 0.0100

“config.ru” is the default Rackup script, otherwise need to specify the name. And now “app.rb” ..

App = lambda { |env|
  [
    200,
    {
    'Content-Length' => '2',
    'Content-Type' => 'text/html',
    },
    ["hi"]
  ]
}

And run it as …

~/samples/railsconf/sinatra/basic-rack >~/tools/jruby/bin/jruby -S rackup app.rb
[2009-05-04 13:43:57] INFO  WEBrick 1.3.1
[2009-05-04 13:43:57] INFO  ruby 1.8.6 (2009-03-16) [java]
[2009-05-04 13:43:57] INFO  WEBrick::HTTPServer#start: pid=90990 port=9292
127.0.0.1 – - [04/May/2009 13:44:09] “GET / HTTP/1.1″ 200 2 0.0110

In both cases, the application is accessible at “http://localhost:9292″.

Change the basic “config.ru” to convert into a class as …

class BasicRack
     def call(env)
      body = “Hello from a class”
      [
        200,
        {
        'Content-Length' => body.size.to_s,
        'Content-Type' => 'text/html',
        },
        [body]
      ]
    end
end

run BasicRack.new

and run the same way as earlier.

Change body to “env.inspect” to see an output as:

Sinatra allows reloading of application but that “feature” will be removed soon. Instead install shotgun (which does not work with JRuby yet!). Anyway, install the gem:

~/samples/railsconf/sinatra/basic-rack >~/tools/jruby/bin/jruby -S gem install shotgun
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed configuration-0.0.5
Successfully installed launchy-0.3.3
Successfully installed shotgun-0.2
3 gems installed
Installing ri documentation for launchy-0.3.3…
Installing RDoc documentation for launchy-0.3.3…

And run as:

~/samples/railsconf/sinatra/basic-rack >~/tools/jruby/bin/jruby -J-Djruby.fork.enabled=true -S shotgun
[2009-05-04 13:55:46] INFO  WEBrick 1.3.1
[2009-05-04 13:55:46] INFO  ruby 1.8.6 (2009-03-16) [java]
== Shotgun starting Rack::Handler::WEBrick on localhost:9393
[2009-05-04 13:55:46] INFO  WEBrick::HTTPServer#start: pid=91089 port=9393

Process separate bodies depending upon the info:

class BasicRack
     def call(env)
      body = if env["PATH_INFO"] == “/foo”<
br>         “in foo”
      else
       “in other”
      end
      [
        200,
        {
        'Content-Length' => body.size.to_s,
        'Content-Type' => 'text/html',
        },
        [body]
      ]
    end
end

run BasicRack.new

Accessing “http://localhost:9292/foo” shows “in foo” and accessing “http://localhost:9393″ shows “in other”.

Target application is the last application specified by “run”.

Rack supports middleware which are like filters, they can applied before/after a message is processed.

Rack will initialize middleware at load, so hold on to that application as shown:

class BasicRackApp
     def call(env)
      body = “hello from app”
      [
        200,
        {
        'Content-Length' => body.size.to_s,
        'Content-Type' => 'text/html',
        },
        [body]
      ]
    end
end

class MyMiddleware
    def initialize(app)
        @app = app
    end
   
    def call(env)
        @app.call(env)
    end
end

use MyMiddleware

run BasicRackApp.new

@app.call calls the next middleware in the chain.

Rack comes with couple of standard middleware, e.g.:

use Rack::CommonLogger

Example of an after filter:

    def call(env)
        status, headers, body = @app.call(env)
        body.map! { |part| part.upcase}
        [status, headers, body]
    end

Lots of other filters available.

With a basic Rack understanding, lets build a Sinatra app:

require ‘sinatra’

is the simplest Sinatra application. Save it in a file “basic-sinatra.rb” and run it as:

~/samples/railsconf/sinatra/basic-sinatra >~/tools/jruby/bin/jruby -rubygems basic-sinatra.rb
== Sinatra/0.9.1.1 has taken the stage on 4567 for development with backup from WEBrick
[2009-05-04 14:40:14] INFO  WEBrick 1.3.1
[2009-05-04 14:40:14] INFO  ruby 1.8.6 (2009-03-16) [java]
[2009-05-04 14:40:14] INFO  WEBrick::HTTPServer#start: pid=91396 port=4567

The application is now available at “http://localhost:4567″. BTW, this app can easily be run using GlassFish Gem as explained  in TOTD #79. Add a simple GET method and “not_found” handler as:

require ‘rubygems’
require ‘sinatra’

not_found do
  ‘hi from other’
end

get ‘/foo’ do
    ‘hi from foo’
end

Every time a request comes in, it builds a request context, instance evals lambda and finds the one that hits.

Sinatra takes care of status and headers, the application needs to process the body.

Another one …

require ‘rubygems’
require ‘sinatra’

get ‘/env’ do
    env.inspect
end

And it shows Rack environment hash at ‘http://localhost:4567″.

Another one …

require ‘rubygems’
require ‘sinatra’

get ‘/’ do
end

post ‘/’ do
end 

put ‘/’ do
end

delete ‘/’ do
end

This adds 4 HTTP methods with different routes.

No explicit render method, e.g.

require ‘rubygems’
require ‘sinatra’

get ‘/’ do
  content_type “application/json”
  { “foo” => “goo” }.to_json
end

No “.rhtml.erb” or “.json.erb”, instead it’s just “.erb”. Add “views/index.erb” as:

<html>
  <body>
  Hello form Sinatra + ERB
  </body>
  </html>

And change GET method to:

require ‘rubygems’
require ‘sinatra’

get ‘/’ do
  erb :index
end

And the application now uses ERB templating.

Using HAML templates is simple, change to:

require ‘rubygems’
require ‘sinatra’
require ‘haml’

get ‘/’ do
  haml :index
end

And add “views/index.haml” as:

%html
  %body
    %h1 Hello from HAML

And now the application is using HAML templates.

__END__ is the end of Ruby, can be anything after that and it’ll not barf. Sinatra uses it for in file templates:

body>
require ‘rubygems’
require ‘sinatra’
require ‘haml’

get ‘/’ do
  erb :index
end

use_in_file_templates!

__END__

@@ index

<html>
  <body>
  Hello form Sinatra + ERB in file
  </body>
  </html>

Start with in-file templates, and then move out to separate directory (“views”) once grows big. But no syntax highlighting etc.

Add your custom template as:

require ‘rubygems’
require ‘sinatra’
require ‘haml’

get ‘/’ do
  erb :index
end

get ‘/foo’ do
  erb :foo
end

use_in_file_templates!

__END__

@@ index

<html>
  <body>
  Hello form Sinatra + ERB in file
  </body>
  </html>
 
@@ foo
<h1>FOO!</h1>

With this file “http://localhost:4567/” uses ERB template, and “http://localhost:4567/foo” uses “foo” template.

Sinatra defines on Main. The before filters work before every single request, executed in the same context as lambda. Can be used if every request needs to do some setup.

Helpers can be defined as:

require ‘rubygems’
require ‘sinatra’
require ‘haml’

helpers do
 
end

without defining on Main. Or …

require ‘rubygems’
require ‘sinatra’
require ‘haml’

module helpers
    def self.dosomething(arg)
    end
end

get ‘/’ do
    Helpers.dosomething
end

Don’t define something on Main, it’s a bad practice.

Extension is a nice package that can be shared for other Sinatra developers to use, like Rails plugins but does not have boilerplate, much easier to do.

Rest of tutorial was quite fast paced so the code samples could not be captured. But there is boatload of information available at sinatrarb.com.

Check out the pictures from Day 1:

The evening concluded with dinner at Burger Bar at Mandalay Bay along with Project Kenai team.

And check the evolving album at:

On to GlassFish talk tomorrow, and running with @railsConfRunner in the morning before that :)

Technorati: conf railsconf lasvegas jruby rubyonrails sinatra glassfish

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

May 1, 2009

JRuby, Rails, and GlassFish Bootcamp – San Francisco, May 19/20, 2009

Filed under: web2.0 — arungupta @ 12:46 pm
Would you like to power up your Rails applications using JRuby and GlassFish ? And learn that from the engineers who develop the technology.

If yes, then we have organized a bootcamp for you!

Day 1 (FREE) of this bootcamp provides an introduction to JRuby and GlassFish and how they serve as an excellent development and deployment environment for Rails applications. Starting with clean slate on your laptop, you’ll be able to setup JRuby, Rails, GlassFish and learn about different options available for running your applications.

Day 2 (need $$$) takes a deep dive on each topic and convert you into a power user instantaneously. The topics range from Virtual Machine tuning for JRuby and GlassFish, Warbler tricks, Java EE integration, Deployment strategies, Monitoring applications to Running other Rack-based frameworks. Lunch and beverages will be served on Day 2.

On both days, you get an opportunity to practice everything on your laptop by following the experts along.

Complete details on venue, time, agenda, etc are available at railscamp.eventbrite.com.

Register now before the seats fill out. And get ready to be drenched!

Technorati: conf jruby rubyonrails glassfish netbeans bootcamp sanfrancisco

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

April 30, 2009

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

Filed under: web2.0 — arungupta @ 4:00 am
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/ngin
    x/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

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

April 29, 2009

TOTD #80: Sinatra CRUD application using Haml templates with JRuby and GlassFish Gem

Filed under: web2.0 — arungupta @ 2:00 am

TOTD #79 showed how to run a trivial Sinatra application using GlassFish Gem. Sinatra provides support for Haml, Erb, Builder, Sass, and Inline templates as described here. This TOTD will show how to get started with creating a Sinatra CRUD application using Haml templates.

Haml is based on one primary principle – Markup should be beautiful because beauty makes you faster.

Get started by installing the Haml gem as:

/tools/jruby-1.2.0 >./bin/jruby -S gem install haml –no-ri –no-rdoc
JRuby limited openssl loaded. gem install jruby-openssl for full support.
http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
Successfully installed haml-2.0.9
1 gem installed

And follow the tutorial, documentation, and reference page for more details.

Sinatra is ORM-agnostic and so any Ruby ORM framework such as ActiveRecord, DataMapper, Sequel, and others. DataMapper with JRuby requires work so this TOTD will show how to use ActiveRecord instead. There is sinatras-hat which allows to create RESTy CRUD apps with Sinatra. There probably are mutiple other ways to create this application but I prefer to understanding the wiring so this blog will use a bare minimal structure.

Anyway, lets get started!

  1. Create the database as:

    ~/tools/jruby/samples/sinatra-sample >mysql –user root
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 664
    Server version: 5.1.30 MySQL Community Server (GPL)

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

    mysql> create database hello_development;
    Query OK, 1 row affected (0.00 sec)

    mysql> use hello_development;
    Database changed
    mysql> CREATE TABLE `runners` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `distance` float, `minutes` int(11), `created_at` datetime, `updated_at` datetime);             
    Query OK, 0 rows affected (0.06 sec)

  2. Update “hello.rb” from TOTD #79 such that it looks like:
    require ‘rubygems’
    require ‘sinatra’
    require ‘activerecord’

    ## Setup

    ActiveRecord::Base.establish_connection(
      :adapter  => “jdbcmysql”,
      :host     => “localhost”,
      :username => “root”,
      :password => “”,
      :database => “hello_development”
    )

    ## Models

    class Runner < ActiveRecord::Base
    end

    ## Controller Actions

    get ‘/hi’ do
      “Hello World!”
    end

    get ‘/’ do
      @runner = Runner.find(:all)
      haml :index
    end

    get ‘/new’ do
      haml :new
    end

    get ‘/:id’ do
      @runner = Runner.find(params[:id])
      if (@runner)
        haml :show
      else
        redirect ‘/’
      end
    end

    post ‘/’ do
      @runner = Runner.new(:distance => params[:distance], :minutes => params[:minutes])
      if @runner.save
        redirect “/#{@runner.id}”
      else
        redirect ‘/’
      end
    end

    Firstly, it pulls in the ActiveRecord dependency. Then “ActiveRecord::Base.establish_connection” is used to establish a connection with the previously created database. “Runner” is tagged as a model class by inheriting from “ActiveRecord::Base” and uses the default table name (“runners” in this case). Add four new methods:

    1. Three GET methods to show all the runners, a form to enter new data, and show a particular log entry. Each method requires a HAML template (will be created in next step) to render the information.
    2. One POST method to save the newly created log entry in the database.
  3. Create a new directory “views” and create the following files in that directory. Each file serves as a view and rendered from an action in “hello.rb”.
    1. “index.haml”: Show all the runners

      %h1 Listing all runners …
      %table
        %tr
          %th Distance
          %th Minutes
        – @runner.each do |r|
          %tr
            %td= r.distance
            %td= r.minutes
      %br
      %a{:href=>”/new”}
        New Runner

    2. “new.haml”: Enter a new entry
      %h1 Adding a new runner log …
      %form{:method=>”post”, :action=>”/”}
        Distance:
        %input{:type=>”text”, :name=>”distance”}
        %br
        Minutes:
        %input{:type=>”text”, :name=>”minutes”}
        %br
        %input{:type=>”submit”, :value=>”Submit”}
        %br

    3. “show.haml”: Show a particular log entry
      %h1 Showing a runner log …
      Dis
      tance:
      = @runner.distance
      %br
      Minutes:
      = @runner.minutes
      %br
      %br
      %a{:href=>”/”}= “Show All!”

      The complete directory structure looks like:

      .
      ./hello.rb
      ./views
      ./views/index.haml
      ./views/new.haml
      ./views/show.haml

That’s it, now run the application as:

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

The main page is available at “http://localhost:3000/” and looks like:

Clicking on “New Runner” gives …

Enter the data, and click on “Submit” to show …

Click on “Show All!” to see all the entries added so far …

And after adding few entries the main page looks like …

This application shows Create and Read from the CRUD, it’s fairly easy to add Update and Delete functionality as well but that’s an excercise left for the readers :-)

You’ll hear all about it at Develop with Pleasure, Deploy with Fun: GlassFish and NetBeans for a Better Rails Experience at Rails Conf next week.

Technorati: totd glassfish jruby sinatra crud

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

April 28, 2009

TOTD #79: Getting Started with Sinatra applications on JRuby and GlassFish Gem

Filed under: web2.0 — arungupta @ 6:00 am


Sinatra is a DSL for quickly creating web-applications in Ruby with minimal effort. Like Rails and Merb, Sinatra is not an MVC framework and basically follows a flat-file structure instead. The framework define conventions such as location of static files and views, bootstrap, dev/production/test environment variables, filters, helpers, TDD, and much more.  Read Getting Started for complete details. Even though Sinatra is not a MVC framework but sinatra-gen may be used to generate new Sinatra projects.

GlassFish Gem can easily run Rails, Merb, Sinatra, and any other Ruby framework applications based upon Rack. TOTD #70 shows how to run Rails applications and TOTD #53 shows to run Merb applications. This TOTD will explain how to run a trivial Sinatra application. A later blog will describe how to plug a generic Rack-based framework.

Lets see how to get started with Sinatra using JRuby and GlassFish gem.

  1. Install Sinatra gem as:

    ~/tools/jruby >./bin/jruby -S gem install sinatra
    JRuby limited openssl loaded. gem install jruby-openssl for full support.
    http://wiki.jruby.org/wiki/JRuby_Builtin_OpenSSL
    Successfully installed sinatra-0.9.1.1
    1 gem installed
    Installing ri documentation for sinatra-0.9.1.1…
    Installing RDoc documentation for sinatra-0.9.1.1…

  2. Create a directory “sinatra-sample”, create a file “hello.rb” in that directory with the contents shown below:
    require ‘rubygems’
    require ‘sinatra’
    get ‘/hi’ do
      “Hello World!”
    end

  3. Run your sample using GlassFish gem as:
    ~/tools/jruby/samples/sinatra-sample >../../bin/jruby -S glassfish
    Log file /Users/arungupta/tools/jruby-1.2.0/samples/sinatra-sample/log/development.log does not exist. Creating a new one…
    Starting GlassFish server at: 192.168.1.145:3000 in development environment…
    Writing log messages to: /Users/arungupta/tools/jruby-1.2.0/samples/sinatra-sample/log/development.log.
    Press Ctrl+C to stop.

    And then the output is available at “http://localhost:3000/hi” and looks like:

Neat and simple!

You’ll hear all about it at Develop with Pleasure, Deploy with Fun: GlassFish and NetBeans for a Better Rails Experience at Rails Conf next week.

Here is the order in which I’ll seek any help:

The next blog will show how to create a Sinatra CRUD application and run it using GlassFish.

Please leave suggestions on other TOTD (Tip Of The Day) that you’d like to see. A complete archive of all the tips is available here.
Technorati: totd glassfish jruby sinatra

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

April 22, 2009

LOTD #21: Production Deployment Tips for running Rails on GlassFish v2 using Windows

Filed under: web2.0 — arungupta @ 2:26 pm

SeaChange Affinity uses Rails and GlassFish as their deployment platform. One of their core developers posted tips based upon their experience so far and they are available at:

Rails on GlassFish v2 using Windows

Here are some of the quotes:

Glassfish can really handle a heavy load

and

handling 400 simultaneous users under a supremely heavy load, the memory was holding great

All previous links in this series are archived at LOTD.

Technorati: lotd glassfish jruby rubyonrails windows

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

April 8, 2009

TOTD #78: GlassFish, EclipseLink, and MySQL efficient pagination using LIMIT

Filed under: web2.0 — arungupta @ 4:00 am

EclipseLink JPA replaces TopLink Essentials as the JPA implementation in GlassFish v3. One of the benefits of using EclipseLink is that it provides efficient pagination support for the MySQL database by generating native SQL statements such as “SELECT … FROM <table> LIMIT <offset>, <rowcount>”.

The MySQL LIMIT clause definition says:

The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be non-negative integer constants (except when using prepared statements).

With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

So instead of fetching all rows from the database and then filtering from row 6-15, only rows 6 through 15 are fetched.

This TOTD (Tip Of The Day) explains how to create a JPA Persistence Unit for sakila (MySQL sample database) using NetBeans, use EclipseLink as the Persistence Provider, and then write a JPA query to leverage the pagination support – all on GlassFish v3.

  1. Create a Persistence Unit for “sakila” as explained in this blog using bullets #1 – 3. The differences are explained below:
    1. In 2.1, choose “GlassFish v3 Prelude” as the server. Even though “GlassFish v3 Prelude” is chosen as the server but it will be replaced with a recent promoted build because pagination feature is not implemented in the Prelude. Alternatively you can use NetBeans 6.7 M3 and GlassFish v3 as explained here.
    2. In 3.3, EclipseLink is shown as the default Persistence Provider as shown below:

    3. In 3.5, there is no need to specify the properties for “user” and “password as the JDBC resource is stored in the server configuration. Instead specify the following property:
      <properties>
          <property name=”eclipselink.logging.level” value=”FINE”/>
      </properties>

      This will log any SQL statement sent by JPA to the underlying persistence provider (EclipseLink in this case).

  2. If GlassFish v3 was configured using NetBeans 6.7 M3, then the JDBC Connection Pool and JDBC resource were created in the server directly. If not, then download and unzip the latest GlassFish v3 latest promoted build (b43 as of this writing). Create the JDBC Connection Pool as:
    ./asadmin create-jdbc-connection-pool –datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource –property user=duke:password=glassfish:ServerName=localhost:portNumber=3306:databaseName=sakila jdbc-mysql-pool

    and the JDBC resource:

    ./asadmin create-jdbc-resource –connectionpoolid jdbc-mysql-pool jndi/sakila

    GlassFish v3 b43 bundles ”Eclipse Persistence Services – 2.0.0.r3652-M1″. A later blog will explain how to replace the bundled EclipseLink version with a newer/different EclipseLink version.

  3. Create a new Servlet “QueryServlet”. Inject the javax.persistence.EntityManagerFactory resource:
        @PersistenceUnit
        EntityManagerFactory emf;

    and change the “processRequest” operation to:

            EntityManager em = emf.createEntityManager();

            response.setContentType(“text/html;charset=UTF-8″);
            PrintWriter out = response.getWriter();
            try {
                int startRow = Integer.valueOf(request.getParameter(“start_row”));
                int howMany = Integer.valueOf(request.getParameter(“how_many”));
                Query q = em.createNamedQuery(“Film.findAll”);

                q.setFirstResult(startRow);
                q.setMaxResults(startRow + howMany);
                for (Object film : q.getResultList()) {
                    out.print(((Film)film).toString() + “<br/>”);
                }
            } finally {
                out.close();
            }

    This Servlet reads two parameters from the request and sets parameters on the JPA Query to enable pagination.

  4. Deploy the application on GlassFish v3.
    1. Using NetBeans 6.7 M3, select “Deploy” from the context-sensitive menu.
    2. Using NetBeans 6.5.1, select “Clean and Build” and then manually deploy the WAR file using “asadmin deploy dist/Pagination.war”.

If the project name was “Pagination”, then the Servlet is accessible at “http://localhost:8080/Pagination/QueryServlet?start_row=1&how_many=10″ and shows ten rows starting at index “1″. The output looks like:

The log file in “domains/domain1/logs/server.log” show the following SQL query generated by EclipseLink:

[#|2009-04-07T14:01:12.815-0700|FINE|glassfish|org.eclipse.persistence.session.file: /Users/arungupta/tools/glassfish/v3/b43/glassfishv3/glassfish/domains/domain1/applications/Pagination/WEB-INF/classes/-PaginationPU.sql| _ThreadID=15;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT film_id AS film_id1, special_features AS special_features2, last_update AS last_update3, rental_duration AS rental_duration4, release_year AS release_year5, title AS title6, description AS description7, replacement_cost AS replacement_cost8, length AS length9, rating AS rating10, rental_rate AS rental_rate11, language_id AS language_id12, original_language_id AS original_language_id13 FROM film LIMIT ?, ?
        bind => [1, 11]|#]

As you can see, the query uses the LIMIT clause which optimizes the data returned from the table.

If a different database, for example Derby, is used then the generated SQL query looks like as:

[#|2009-04-07T17:00:34.210-0700|FINE|glassfish|org.eclipse.persistence.session.file: /Users/arungupta/tools/glassfish/v3/b43/glassfishv3/glassfish/domains/domain1/applications/Pagination/WEB-INF/classes/-PaginationPU.sql| _ThreadID=15;_ThreadName=Thread-1;ClassName=null;MethodName=null;|SELECT film_id, special_features, last_update, rental_duration, release_year, title, description, replacement_cost, length, rating, rental_rate, language_id, original_language_id FROM film|#]

In this case, the entire table is fetched and the rows are filtered based upon the critieria specified on the client side.

If the number of rows is huge (a typical case for enterprise) then MySQL provides efficient fetching of records. And GlassFish v3, with EclipseLink JPA integrated, makes it much seamless for you.

Thanks to Mr GlassFish Persistence (aka Mitesh :) for helping me understand the inner workings.

Discuss this more at Creating Quick and Powerful Web Applications with MySQL, GlassFish, and NetBeans technical session in the upcoming MySQL Users Conference!

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

Technorati: totd glassfish v3 eclipselink jpa mysql

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

April 2, 2009

Silicon Valley Rails Meetup, Mar 2009 – Slides & Pics

Filed under: web2.0 — arungupta @ 4:00 am

I presented at Silicon Valley Rails Meetup yesterday. The official attendance says 79 and the kitchen area (for the presentation) was indeed packed!

The demo gods were hovering very much around and required me to reboot the machine – live during the presentation. Have you ever rebooted Mac because of a slow performance, smack in the middle of a demo ? ;-)

Here is a quote from the meetup:

The big win with glassfish is that it gives you the same environment in deployment and development.

The slides are available here. And some pointers to get more information:

And another one …

Thanks to Michael and Jerry for being the wonderful hosts!

Drop a comment on this blog if you are using GlassFish for your Rails/Merb/Sinatra/… deployments.

Technorati: conf glassfish rubyonrails jruby netbeans meetup

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot

April 1, 2009

LOTD #18: Campus Ambassadors presenting on GlassFish – France & India

Filed under: web2.0 — arungupta @ 12:00 pm

Agnieszka and Julien, the Sun Campus Ambassadors at INSA Lyon presented on GlassFish. Read the complete report here and enjoy a picture:

Here is another report on Hibernate/NetBeans/GlassFish presentation – again at INSA Lyon.

Dwarkanath, the Campus Ambassador at Sastra, presented on GlassFish as part of Student Technology Camp. Read the complete report here and enjoy a picture:

If you are interested in learning/talking about GlassFish at your university, spotlight.dev.java.net/start provides a comprehensive set of slides (with speaker notes), demos, screencasts, training materials and other resources to get you started!

All previous links in this series are archived at LOTD.

Technorati: lotd glassfish students campusambassadors france india spotlight

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • email
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
« Newer PostsOlder Posts »

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Powered by WordPress