JRuby Language Basics

Sang Shin, sang.shin@sun.com, Sun Microsystems, www.javapassion.com/j2ee



JRuby is a 100% pure-Java implementation of the Ruby programming language. Almost complete support for all Ruby constructs work, and the idea is that you should be able to just use your Ruby scripts with JRuby instead of MRI (Matz' Ruby Implementation, the original Ruby, written in C). But the goal goes beyond that. Java is a powerful platform and there are millions of lines of Java code being written each month, that the world will have to live with for a long time from now. By leveraging Java the platform with the power of the Ruby programming language, programmers get the best from both worlds.

 In this lab, you are going to learn various ways of how you can use Ruby and Java programming language together in your application.


Expected duration: 150 minutes (excluding homework)




Software Needed

Before you begin, you need to install the JDK and NetBeans IDE software on your computer as described in  here.


OS platforms you can use

Change Log


Things to be done (By Sang Shin)

 

Lab Exercises


Exercise 1: Build JRuby applications using Java classes


In this exercise, you are going exercise how to use built-in Java clasess in your JRuby applications.
  1. Open, build, and run "JRuby_ImportJavaClass" sample application
  2. Open, build, and run "JRuby_UseJavaJFrameClass" sample application
  3. Open, build, and run "JRuby_UseJavaJFrameClass2" sample application
  4. Open, build, and run "JRuby_UseJavaTreeSetClass" sample application
  5. Open, build, and run "JRuby_UseJavaArrayListClass" sample application

(1.1) Open, build, and run "JRuby_ImportJavaClass" sample application


1. Open "JRuby_ImportJavaClass" sample application.
2. Study the code paying special attention to the bold-fonted code fragments.

# You have to include Java if you are using Java class
include Java

puts "----Import a Java class, java.lang.System"
import java.lang.System

puts "----Display Java version using java.lang.System Java class"
version = System.getProperties["java.runtime.version"]
puts "Java verion used is #{version}"

3. Run the project.
4. Study the result displayed in the Output window.

----Import a Java class, java.lang.System
----Display Java version using java.lang.System Java class
Java verion used is 1.6.0_04-b12

                                                                                                                                                 return to top of exercise


(1.2) Open, build, and run "JRuby_UseJavaJFrameClass" sample application


1. Open "JRuby_UseJavaJFrameClass" sample application.
2. Study the code.

# This is the 'magical Java include line'.
include Java
  
# With the 'include Java' above, we can now refer to things that are part of the
# standard Java platform via their full paths.
frame = javax.swing.JFrame.new("Passion!") # Creating a Java JFrame.
label = javax.swing.JLabel.new("Hello World!")
  
# We can transparently call Java methods on Java objects, just as if they were
# defined in Ruby.
frame.getContentPane.add(label)  # Invoking the Java method 'getContentPane'.
frame.setDefaultCloseOperation(javax.swing.JFrame::EXIT_ON_CLOSE)
frame.pack
frame.setVisible(true)

3. Run the project.
4. Observe that a JFrame window is displayed.


                                                                                                                                                 return to top of exercise


(1.3) Open, build, and run "JRuby_UseJavaJFrameClass2" sample application


1. Open "JRuby_UseJavaJFrameClass2" sample application.
2. Study the code.

# Code is orginally written by Daniel Spiewak
# http://www.codecommit.com/blog/java/rapid-prototyping-with-jruby

include Java
 
JFrame = javax.swing.JFrame
JComponent = javax.swing.JComponent
GradientPaint = java.awt.GradientPaint
Color = java.awt.Color
 
class CustomComponent < JComponent
 
  def initialize
    @paint = GradientPaint.new(0, 0, Color::RED, 0, 200, Color::WHITE)
  end
 
  def paintComponent(g)
    g.setPaint @paint
    g.fillRect(0, 0, 200, 200)
  end
 
end

# Create JFrame
frame = JFrame.new 'Test Frame'
frame.setSize(200, 200)

# Create CustomComponent
@comp = CustomComponent.new

# Add custom component to the frame
frame.add @comp
frame.defaultCloseOperation = JFrame::EXIT_ON_CLOSE
frame.visible = true

3. Run the project.
4. Observe that a JFrame window is displayed.



                                                                                                                                                 return to top of exercise


(1.4) Open, build, and run "JRuby_UseJavaTreeSetClass" sample application


1. Open "JRuby_UseJavaTreeSetClass" sample application.
2. Study the code.

include Java

include_class 'java.util.TreeSet'

puts "----Create an object from TreeSet Java class"
set = TreeSet.new

puts "----Add entries to the TreeSet"
set.add "foo"
set.add "Bar"
set.add "baz"

puts "----Display TreeSet"
set.each do |v|
  puts "value: #{v}"
end

3. Run the project.
4. Study the result displayed in the Output window.

----Create an object from TreeSet Java class
----Add entries to the TreeSet
----Display TreeSet
value: Bar
value: baz
value: foo

                                                                                                                                                 return to top of exercise


(1.5) Open, build, and run "JRuby_UseJavaArrayListClass" sample application


1. Open "JRuby_UseJavaArrayListClass" sample application.
2. Study the code.

include Java

include_class 'java.util.ArrayList'

puts "----Create an object from ArrayList Java class"
list = ArrayList.new

puts "----Add entries to the ArrayList"
list.add "foo"
list.add "Bar"
list.add "baz"

puts "----Add an entry using an index"
list.add(2, "Sang Shin")

puts "----Display ArrayList"
list.each do |v|
  puts "value: #{v}"
end

puts "----Display an entry using an index"
puts list.get(2)

3. Run the project.
4. Study the result displayed in the Output window.

----Create an object from ArrayList Java class
----Add entries to the ArrayList
----Add an entry using an index
----Display ArrayList
value: foo
value: Bar
value: Sang Shin
value: baz
----Display an entry using an index
Sang Shin

                                                                                                                                                 return to top of exercise

Exercise 2: Create Ruby Module from Java Packages


In this exercise, you are going to learn how to create Ruby module from Java pacakges.  Use include_package "<package_name>" in a Ruby Module to support namespaced access to the Java classes in the package. It is also legal to use import "<package_name>".

(2.1) Open, build, and run "JRuby_CreateModuleFromJavaPackage" sample application


1. Open "JRuby_CreateModuleFromJavaPackage" sample application.
2. Study the code.

include Java

puts "----Create a module from Java package"
module JavaLang
  include_package "java.lang"
end

puts "----Create a string"
s = JavaLang::String.new("This is my string from java.lang package")
puts s

3. Run the project.
4. Study the result displayed in the Output window.

----Create a module from Java package
----Create a string
This is my string from java.lang package

                                                                                                                                                 return to top of exercise


(2.2) Open, build, and run "JRuby_CreateModuleFromJavaPackage2" sample application


1. Open "JRuby_CreateModuleFromJavaPackage2" sample application.
2. Study the code.

include Java

puts "----Create a Ruby Module from Java package"
module JavaLang
    include_package "java.lang"
end

puts "----Get Java version information"
version = JavaLang::System.getProperties["java.runtime.version"]
puts version

3. Run the project.
4. Study the result displayed in the Output window.

----Create a Ruby Module from Java package
----Get Java version information
1.6.0_04-b12

                                                                                                                                                 return to top of exercise






Exercise 3: Use "FreeTTS" Speech Synthesizer 3rd-party Java Library


In this exercise, you are going to use FreeTTS speech synthesizer java library in your JRuby application.  The FreeTTS is a speech synthesis system written entirely in the Java programming language.  For more information on the FreeTTS, please go to FreeTTS homesite.


(3.1) Open, build, and run "JRuby_UseJavaSpeechLibrary" sample application


1. Open "JRuby_UseJavaSpeechLibrary" sample application.
2. Configure FreeTTS Java library.






3. Study the code.

include Java

import com.sun.speech.freetts.Voice
import com.sun.speech.freetts.VoiceManager

puts "----Allocate a voice"
voice = VoiceManager.getInstance.getVoice('kevin')
voice.allocate   
 
puts "----Speak out"
speech1 = "I love you!"
voice.speak(speech1)
voice.speak "Life is worth living with Passion!"

4. Run the project and observe that the text are spoken out.

                                                                                                                                                 return to top of exercise



Exercise 4: Use "JFreeChart" 3rd-party Java Library


In this exercise, you are going to use FreeChart Java library in your JRuby application.  JFreeChart is a free 100% Java chart library that makes it easy for developers to display professional quality charts in their applications. JFreeChart's extensive feature set includes: 
For more information on the JFreeChart, please go to JFreeChart homesite.


(4.1) Open, build, and run "JRuby_UseFreeChartLibrary" sample application


1. Open "JRuby_UseFreeChartLibrary" sample application.
2. Configure FreeChart library.





3. Study the code.

# Code is from http://kfahlgren.com/blog/2007/04/13/jruby-jfreechart-sparklines/

# Mostly inspired by http://left.subtree.org/2007/01/15/creating-sparklines-with-jfreechart/
# have JFreeChart in your classpath, obviously, as well as jcommon.jar

# FreeChart homesite is
# http://www.jfree.org/jfreechart/

include Java

module Graph
  class Sparkline
    include_class 'java.io.File'
    include_class 'org.jfree.chart.ChartUtilities'
    include_class 'org.jfree.chart.JFreeChart'
    include_class 'org.jfree.chart.axis.NumberAxis'
    include_class 'org.jfree.chart.plot.XYPlot'
    include_class 'org.jfree.chart.renderer.xy.StandardXYItemRenderer'
    include_class 'org.jfree.data.xy.XYSeries'
    include_class 'org.jfree.data.xy.XYSeriesCollection'
    include_class 'org.jfree.chart.plot.PlotOrientation'

    def initialize(width=200, height=80, data=[])
      @width = width
      @height = height
      dataset = create_sample_data() if data.empty?
      @chart = create_chart(dataset)
    end

    def render_to_file(filename, format="png")
      javafile = java.io.File.new(filename)
      ChartUtilities.saveChartAsPNG(javafile, @chart, @width, @height)
    end

    private
    def create_sample_data
      series = XYSeries.new("Sparkline")
      data = [20]
      (1..99).each {|x|
        y = (data.last + (rand(x) + 1)) / 2
        data << y
        series.add(x, y)
      }

      dataset = XYSeriesCollection.new
      dataset.addSeries(series)
      return dataset
    end

    def create_chart(dataset)
      x = NumberAxis.new
      x.setTickLabelsVisible(false)
      x.setTickMarksVisible(false)
      x.setAxisLineVisible(false)
      x.setNegativeArrowVisible(false)
      x.setPositiveArrowVisible(false)
      x.setVisible(false)

      y = NumberAxis.new
      y.setTickLabelsVisible(false)
      y.setTickMarksVisible(false)
      y.setAxisLineVisible(false)
      y.setNegativeArrowVisible(false)
      y.setPositiveArrowVisible(false)
      y.setVisible(false)

      plot = XYPlot.new
      plot.setDataset(dataset)
      plot.setDomainAxis(x)
      plot.setDomainGridlinesVisible(false)
      plot.setDomainCrosshairVisible(false)
      plot.setRangeGridlinesVisible(false)
      plot.setRangeCrosshairVisible(false)
      plot.setRangeAxis(y)
      plot.setOutlinePaint(nil)
      plot.setRenderer(StandardXYItemRenderer.new(StandardXYItemRenderer::LINES))

      chart = JFreeChart.new(nil, JFreeChart::DEFAULT_TITLE_FONT, plot, false)
      chart.setBorderVisible(false);
      return chart   
    end
  end # class Sparkline 
end # class Graph

sp = Graph::Sparkline.new
puts "Rendering sparkline"
sp.render_to_file("sparkline.png")

4. Run the project.


                                                                                                                                                 return to top of exercise

Exercise 5: Use your own Java library


In this exercise, you are going to build a simple Java library which contains a single Java class first and then use it in your JRuby application.
  1. Create a Java library
  2. Create, build, and run JRuby application

(5.1) Create a Java library


1. Creare a NetBeans project.





2. Add a new Java class to the library.



/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package mypackage;

/**
 *
 * @author sang
 */
public class Hello {
   
    public String sayHello(String name){
        return "Hello " + name + "!";
    }

}



3. Build the library.




(5.2) Create, build, and run JRuby application


1. Create a NetBeans project.




2. Modify the main.rb.
#
# To change this template, choose Tools | Templates
# and open the template in the editor.
 

include Java

include_class 'mypackage.Hello'

puts "----Create an object from Hello Java class"
h = Hello.new

puts "----Invoke a method of from Hello object"
s = h.sayHello("Message from Hello Java Class!")
puts s



3. Configure Java library.





4. Build and run the project.






Exercise 6: Naming Convention


In this exercise, you are going to learn how Java class and Java method can be represented in Ruby naming convention.
  1. Open, build, and run "JRubyNaming_JavaClass" sample application
  2. Open, build, and run "JRubyNaming_JavaMethod" sample application

(6.1) Open, build, and run "JRubyNaming_JavaClass" sample application


1. Open "JRubyNaming_JavaClass" sample application.
2. Study the code.

# This is the 'magical Java include line'.
include Java
  
# Java class naming convention in JRuby
#   Java: org.foo.department.Widget
#   Ruby: Java::OrgFooDepartment::Widget
#  
#frame = javax.swing.JFrame.new("Passion!")           # Creating a Java JFrame.
frame = Java::JavaxSwing::JFrame.new("Passion!")      # Same as above
#label = javax.swing.JLabel.new("Hello World!")       # Creating a Java JLabel
label = Java::JavaxSwing::JLabel.new("Hello World!")  # Same as above
  
# We can transparently call Java methods on Java objects, just as if they were
# defined in Ruby.
frame.getContentPane.add(label)  # Invoking the Java method 'getContentPane'.
frame.setDefaultCloseOperation(javax.swing.JFrame::EXIT_ON_CLOSE)
frame.pack
frame.setVisible(true)

3. Run the project.
4. Observe that the dialog box below gets displayed.



                                                                                                                                                 return to top of exercise

(6.2) Open, build, and run "JRubyNaming_JavaMethod" sample application


1. Open "JRubyNaming_JavaMethod" sample application.
2. Study the code.

# You have to include Java if you are using Java class
include Java

puts "----Import a Java class, java.lang.System"
import java.lang.System

puts "----Display Java version using java.lang.System Java class"
version = System.getProperties["java.runtime.version"]
puts "Java verion used is #{version}"

puts "----Use Ruby method naming convention"
version2 = System.get_properties["java.runtime.version"]
puts "Java verion used is #{version2}"

3. Run the project.
4. Study the result displayed in the Output window.

----Import a Java class, java.lang.System
----Display Java version using java.lang.System Java class
Java verion used is 1.6.0_04-b12
----Use Ruby method naming convention
Java verion used is 1.6.0_04-b12

                                                                                                                                                 return to top of exercise


Homework Exercise (for people who are taking Sang Shin's "Ruby/JRuby/Rails Development online course")


1. The homework is to write your own Java library and a JRuby application that uses it as described below.  The goal of this homework is to test your understanding on how to use your own Java library in your JRuby application as showcased the in Exercise 5 above.
public int add(int x, int y){
      return x+y;
}

public int subtract(int x, int y){
      return x-y;
}
2. Send the following files to railshomeworks@sun.com with Subject as RailsHomework-ruby_jruby.

                                                                                                                                       return to the top