The primary advantage of developing with JRuby is that you have access to Java libraries from a Rails application. For example, say you want to create an image database and a web application that allows processing of the images. You can use Rails to set up the database-backed web application and use the powerful Java 2DTM API for processing the images on the server-side.
This section shows you how to get started using Java libraries in a Rails application while stepping you through building a simple Rails application that does basic image processing with the Java 2D API.
This application demonstrates the following concepts involved in using Java libraries in a Rails application:
Giving your controller access to Java libraries
Creating constants to refer to Java classes
Performing file input and output using the java.io and javax.imageio packages
Assigning Java objects to Ruby objects
Calling Java methods and using variables
Converting arrays from Java language arrays to Ruby arrays
Streaming files to the client
For simplicity's sake, this application does not use a database. You will need a JPEG file to run this application.
Change to the directory you want to create an application.
/apps/jruby-apps/
Create an application by running this command:
jruby -S rails imageprocess |
Open the imageprocess/config/environment.rb file in a text editor, and modify the file as described in To Use Rails Without a Database.
Change to the imageprocess directory you just created.
Create a controller and default view for the application by running this command:
jruby script/generate controller home index |
Change to the imageprocess/app/views/home directory.
Create a second view by copying the default view to seeimage.html.erb:
cp index.html.erb seeimage.html.erb |
In this task, you will perform the following actions:
Load an image on which you want to perform image processing with Java2D.
Make the initial view show the original image and provide a link that the user clicks to perform the ColorConvertOp image processing operation.
Make the other view display the processed image.
Find a JPEG image that you can use with this application.
Add the image to imageprocess/public/image file.
Change to imageprocess/app/views/home directory.
Open the index.html.erb file in a text editor.
Replace the contents of this file with the following HTML markup:
<html> <body> <img src="../../images/kids.jpg"/><p> <%= link_to "Perform a ColorConvertOp on this image", :action => "seeimage" %> </body> </html> |
This page loads an image from imageprocess/public/images and provides a link that references the seeimage action. The seeimage action maps to the seeimage view, which shows the processed image.
Replace kids.jpg in the index.html.erb with the name of your image that you saved earlier in this procedure.
Save the index.html.erb file.
Open the seeimage.html.erb file in a text editor.
Replace the contents of this file with the following HTML markup:
<html> <body> <img src="/home/processimage"/><p> <%= link_to "Back", :action => "index" %> </body> </html> |
The img tag on this page accesses the processimage action in HomeController. The processimage action is where you will put the Java2D code to process the image that you loaded into index.html.erb.
With this task, you will add the code to process your JPEG image.
Add the following line to HomeController, right after the class declaration:
include Java |
This line is necessary for you to access any Java libraries from your controller.
Create a constant for the BufferedImage class so that you can refer to it by the shorter name:
BI = java.awt.image.BufferedImage |
Add an empty action, called seeimage, at the end of the controller:
def seeimage end |
This action is mapped to the seeimage.html.erb view.
Give controller access to your image file using java.io.File, making sure to use the name of your image in the path to the image file. Place the following line inside the seeimage action:
filename = "#{RAILS_ROOT}/public/images/kids.jpg" imagefile = java.io.File.new(filename) |
Notice that you do not need to declare the types of the variables, filename or imagefile. JRuby can tell that filename is a String and imagefile is a java.io.File instance because that is what you assigned them to be.
Read the file into a BufferedImage object and create a Graphics2D object from it so that you can perform the image processing on it. Add these lines directly after the previous two lines:
bi = javax.imageio.ImageIO.read(imagefile) w = bi.getWidth() h = bi.getHeight() bi2 = BI.new(w, h, BI::TYPE_INT_RGB) big = bi2.getGraphics() big.drawImage(bi, 0, 0, nil) bi = bi2 biFiltered = bi |
Refer to The Java Tutorial for more information on the Java 2D API.
The important points are :
You can call Java methods in pretty much the same way in JRuby as you do in Java code.
You do not have to initialize any variables.
You can just create a variable and assign anything to it. You do not need to give it a type.
Add the following code to convert the image to grayscale:
colorSpace = java.awt.color.ColorSpace.getInstance( java.awt.color.ColorSpace::CS_GRAY) op = java.awt.image.ColorConvertOp.new(colorSpace, nil) dest = op.filter(biFiltered, nil) big.drawImage(dest, 0, 0, nil); |
Stream the file to the browser:
os = java.io.ByteArrayOutputStream.new javax.imageio.ImageIO.write(biFiltered, "jpeg", os) string = String.from_java_bytes(os.toByteArray) send_data string, :type => "image/jpeg", :disposition => "inline", :filename => "newkids.jpg" |
Sometimes you need to convert arrays from Ruby to Java code or from Java code to Ruby. In such cases, you need to use the from_java_bytes routine to convert the bytes in the output stream to a Ruby string so that you can use it with send_data to stream the image to the browser. JRuby provides some other routines for converting types, such as to_java to convert from a Ruby Array to a Java String. See Conversion of Types.
Deploy the application on the GlassFish v3 Gem:
asadmin deploy imageprocess |
Run the application by entering the following URL into your browser:
http://localhost:3000/home/index |
You should now see an image and a link that says, “Perform a ColorConvertOp on this image.”
Click the link.
You should now see a grayscale version of the image from the previous page.