Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

PIVOTAL LABS
Visualizing Garbage Collection by Pat Shaughnessy

Visualizing Garbage Collection in Rubinius, JRuby and Ruby 2.0

Watch live streaming video from pivotallabs at livestream.com

In this talk we’ll dive into Ruby internals and take a close look at an ugly topic: garbage collection. How do these Ruby VM’s allocate memory for new objects?

Read more »

LABS
Upgrading to JRuby 1.7.0

Why Upgrade?

Two weeks ago, JRuby 1.7.0 was officially released. Here are a few reasons why you might want to upgrade:

  • Bug fixes

    JRuby 1.7.0 fixes many compatibility issues with ruby 1.9. Also, JRuby 1.6.8 is no longer being maintained so fixes from 1.7.0 are not getting backported.

  • Support for invokedynamic

    JRuby 1.7.0 supports the invokedynamic instruction, a new feature in Java 7 which allows the compiler to use duck typing. This means dynamic languages on the JVM will be compiled to faster code.

  • Kernel#exec

    JRuby 1.7.0’s exec function is now a true system exec that replaces the current process, while previously it spawned a new process and waited until the process exited.

Overview

I just upgraded my project from 1.6.8 to 1.7.0. It was fairly easy - I took about a day to upgrade our project.

  1. Install JRuby 1.7.0
  2. Bundle
  3. Tweak
  4. Profit!

Detailed How-To

  1. Install jruby-1.7-0. It's as simple as:

    $ rbenv install jruby-1.7.0
    

    If ruby-build complains that definition not found, you'll need to upgrade ruby-build.

    Note that if you're using ruby 1.8.7, you'll need to install that separately since JRuby 1.7.0 by default uses ruby 1.9.3.

    Drop the new version into your project .rbenv-version file.

  2. Bundle

    $ bundle
    

    Some gems may fail to install because JRuby 1.7.0 by default doesn't enable C extensions since they are deprecating this feature. You can turn it back on with the command line option -Xcext.enabled=true - add this to your .rbenv-vars file.

  3. Tweak

    $ rake spec
    

    If you're lucky, everything will pass and you can skip straight to step 4.

    Otherwise, here’s a list of the changes I made to port our project over. This is by no means an exhaustive list, so please feel free to comment below.

    • An interesting change in JRuby 1.7.0 is that Java exceptions no longer inherit from ruby Exception. This means that they will not be caught by a standard global rescue. I.e., executing the code below will print 'Rescued' under 1.6.8 but will blow up under 1.7.0.

      begin
          java.lang.Integer.parse_int("asdf")
      rescue
          puts "Rescued"
      end
      

    If you're doing a global rescue from Java code, you'll need to change your code to specifically catch a Java exception class or explicitly rescue Exception (at your own risk).

    • Another change is the behavior of Kernel#exec, which unexpectedly broke one of our dependencies with an unhelpful error message Error: Unable to access jarfile start.jar. In our case, the fix was to change the Kernel#exec call to Kernel#system instead.
  4. Profit!

    Once we finished tweaking it, our application loaded and behaved normally.

Further Notes

You may want to experiment with enabling invokedynamic. It’s turned off by default because some versions of the JDK 7.0 are not fully compatible. To enable it, add -Xcompile.invokedynamic=true into your .rbenv-vars file.

Unfortunately, on my project, we’re sticking with Java 6 due to our dependencies, so no invokedynamic for us - but let me know how that works out if you try it.

PIVOTAL LABS
[Standup][SF] 06/27/12: JRuby Forks

Helps

  • fork in jruby

we'd like to use a gem (rescue-pool) that uses 'fork' in jruby. Right now the gem raises when fork is unavailable in jruby. Is there a pattern for replacing a ruby fork with a java Thread?

  • Suggestions were made to use Thread.fork instead.

Interestings

  • Javascript and window.matchMedia

For implementing responsive layout, browsers support the use of event handlers that are tied to state changes of media queries. It means that you can have JavaScript events triggered in a manner similar to how CSS rule changes are implemented.

LABS
New Tech Talk: JRuby on AppEngine

John Woodell, a JRuby developer from Google, describes the state of JRuby on Google's AppEngine.

App Engine version 1.4.0. is here! It’s our most significant release of the year for the App Engine SDK, including a number of very big features that we know developers have been eagerly awaiting. App Engine's infrastructure can now anticipate the need for more resources and warm up new application instances (in the background) before routing user traffic to them.

See all our talks at http://pivotallabs.com/talks

PIVOTAL LABS
JRuby on AppEngine

John Woodell, a JRuby developer from Google, describes the 1.4.0 release of Google's AppEngine, which includes JRuby support. John focuses on the how AppEngine differs from other managed cloud hosting environments for Ruby web apps.

PIVOTAL LABS
SF Standup 3/1/2010: JRuby skips ensure blocks when killed

When you kill a JRuby process (e.g. with a SIGINT) you can't bank on ensure blocks being executed. Of course, this is worrisome - file handles and other connections won't be closed. The problem boils down to this example:

$ cat kill_me.rb
begin
  sleep
ensure
  puts 'executed ensure'
end
$
$ ruby -v
ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
$
$ ruby kill_me.rb
^Cexecuted ensure
kill_me.rb:2:in `sleep': Interrupt
    from kill_me.rb:2
$
$ jruby -v
jruby 1.4.0 (ruby 1.8.7 patchlevel 174) (2009-11-02 69fbfa3) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_13) [x86_64-java]
$
$ jruby kill_me.rb
^C$

PIVOTAL LABS
Standup 08/05/2009: BugMash this weekend

Interesting Things

  • RailsBridge is organizing a global BugMash to help knock down some of the bugs on the Rails lighthouse this weekend. If your interested in helping out there is more information on their wiki

  • We started using JRuby for a project and wanted to use JRuby to run our specs. If you install RSpec 1.2.7 or higher you can specify the ruby command used to run your SpecTask in rspec.rake like this:

  desc "Run all specs in spec directory (excluding plugin specs)"
  Spec::Rake::SpecTask.new(:spec) do |t|
    t.spec_opts = ['--options', ""#{File.dirname(__FILE__)}/../../spec/spec.opts""]
    t.spec_files = FileList['spec/**/*/*_spec.rb']
    t.ruby_cmd = 'jruby'
  end

PIVOTAL LABS
New York Standup 11/24/2008

Interesting

  • Rails 2.2.2 is released!

  • Even Rails 2.2.2 isn't always threadsafe. I found this out by running a script with JRuby from the command line. The script loaded the Rails environment and then launched two threads that simply tried to resolve an ActiveRecord class constant. Fireworks (in the form of LoadError) ensued deep inside of const_missing. I'll post the full example later today.

  • Tsearch2 is now built into Postgres (as of 8.3). This means you must remove the metadata from your tables, since Postgres now stores it in a separate place.

LABS
Java Functional Testing with JRuby and RSpec

One of our client Java projects is pioneering the use of RSpec Story Framework for functional tests.

Overview

RSpec provides two frameworks for writing and executing examples of how your application should behave:

  • a Story Framework for describing behaviour at the application level
  • a Spec Framework for describing behaviour at the object level

JRuby is an 100% pure-Java implementation of the Ruby programming language.

How can Java projects benefit from RSpec Story Framework? Let's consider an example.

Example

There is a Java back-end application server with proprietary remote interface. The server manages current states of all patents reviewed by multiple patent offices. Close to real life examples below have no proprietary information and object names has been changed. RSpec can help describe how server works and should be used, also what happens in special conditions.

stories/councilReview.txt

one of stories from the server specification:

Story: patent review by counsel



  A Council review of a patent should change the patent review state

  and affect rolled up state of the patent application case.



   Scenario: legal counsel reviews patent

    Given a patent

    And the patent roll up state is ACTIVE

    When the legal council reviews the patent

    Then patent state should be ON_HOLD

    And patent case rolled up state should be SUSPENDED



   Scenario: legal counsel releases patent from the review bin

    Given a patent

    And the patent roll up state is ON_HOLD

    When the legal council release the patent from the review bin

    Then the patent state should be ACTIVE

    And the patent case rolled up state should be ACTIVE

How it works with Java

steps/patentstateoperations.rb

Steps define our Domain Specific Language or DSL

steps_for(:patent_state_operations) do



 Given "a patent" do

   $patent_state_action_stub = PatentStateActionManager.new("local")

   $patent_id = Random.new

  end



 Given "the patent roll up state is '$state'" do |state|

   patent_state_action_stub.setState(patent_id, state);

 end



 When "a '$reviewer' releases the patent from the review bin" do |type|

    newState = patent_state_action_stub.releaseFromBin(patent_id, reviewer);

 end



 When "a '$reviewer' reviews the patent" do |type|

    newState = patent_state_action_stub.addToBin(patent_id, reviewer);

 end



 Then "patent state should be '$state'" do |state|

   newState.should be state

 end

end

helpers/helper.rb

loads required Java classes using JRuby:

 require 'rubygems'

 require 'spec'

 require 'spec/story'

 require 'java'



 include_class 'client.project.functionaltests.PatentStateActionManager'



 class Spec::Story::Runner::ScenarioRunner

   def initialize

    @listeners = []

  end

end



Dir[File.dirname(__FILE__) + "/../steps/*.rb"].uniq.each { |file| require file }

all.rb

JRuby runs all the stories for the project:

 dir = File.expand_path(File.dirname(__FILE__))

 require "#{dir}/helpers/helper"



 with_steps_for :patent_state_operations do

   run "#{dir}/stories/councilReview.txt"

 end

And since we are on Java Project developers use the above Ruby steps to delegate most of the calls to some Java manager, which serves as a fixture for the functional tests.

PatentStateActionManager.java

This is a Java fixture to pass data to the application via RPC

 public class PatentStateActionManager {



  public PatentStateActionManager(String instanceType) {

  ... // get connection to server via RPC

  }



  public String addToBin(long patentId, String review) {

  ... // call RPC method

  }



  public String releaseFromBin(long patentId, String review) {

  ... // another RPC call

  }



  public void setState(long patentId, String newState) {

  ... // java land, Java developers do what they want

  }

}

Results

As a result we have a executable text specification described in close to English language. Majority of the boiler-plate code contained in Java fixtures and Ruby steps.

Project Managers and Quality Engineers can use RSpec stories to define and exercise the behavior of the application.

Java Developers implemented a few stories to demonstrate the use of all steps for Quality Engineers. In addition to Java unit tests that cover the project code, functional tests cover the application use cases.

Next steps

Quality Engineers will fill the story book with more stories covering many conditions and states.

Java Developers will provide support for fixtures as interfaces evolves over the time.

Customers will define future stories as Pending stories.

And Test Valentines are moving to wider adoption of RSpec including:

  • continuous build integration
  • test results publishing
  • common steps for widely used interfaces:
    • Remote Control of Web apps using Selenium-RC
    • Command line and shell
  • interactive console introduction
  • functional point coverage