Sunday, March 30, 2008

Tips for JRuby engine: invokeMethod usage

This is the fourth post of "Tips for JRuby engine" series I've written in this blog and shows how to use javax.script.Invocable#invokeMethod() method defined in JSR 223 APIs. The idea to invoke Ruby's methods from Java is identical to the one described in the former post. It would greatly help you to understand about arguments and retuen values of invokeMethod() method.

As I explained in the former post, invokeMeothd() is used when Ruby's methods to be invoked from Java are resides in classes or modules. Except the first argument, invokeMethod() usage is the same as the one of invokeFunction(). The first argument is an instance of a Ruby class that has a method to be invoked. Consequently, Ruby code must return the instance so that Java can identify whose method it is and then invoke it. Ruby's instance can be get by a returned value when the Ruby script is evaled; therefore, before using invokeMethod(), a programmer must have the line, "Object object = engine.eval(script);", in his or her code to get the instance. The simplest code might be look like this:
String script =
"module SomeModule\n" +
"def say()" +
"puts \"Hi, there!\"" +
"end\n" +
"end\n" +
"class SomeClass\n" +
"include SomeModule;" +
"end\n" +
"SomeClass.new";
Object object = engine.eval(script);
Invocable invocable = (Invocable) engine;
invocable.invokeMethod(object, "say");
script =
"class AnotherClass\n" +
"def say_it_again()" +
"puts \"OK. I said, \'Hi, there.\'\"" +
"end\n" +
"end\n" +
"AnotherClass.new";
object = engine.eval(script);
invocable.invokeMethod(object, "say_it_again");
The first script has a method defined in a module and returns an instance of a class that includes the module as well as the method. The return value of JSR 223 APIs' eval() method should be the Ruby created instance and be the first argument of invokeMethod(). The second script is simpler than the first one - a class has a method and returns an instance. After evaluatig the script, Ruby defined method gets run over invokeMethod() method by using the returned instance.

If a programmer want to get more than one instance from single eval() method of a script, how can he or she get those instacnes from Ruby? We have two possiple ways of doing this; one is to get java.util.List typed object as a return value, and another is to use gobal variables. Ruby allows us to return more than one value at a time, so we can get multiple instances Ruby created by elements of List typed object. The folloing snippet shows how to get multiple instaces and invoke Ruby's method over Java's invokeMethod():
String script = 
"class Flowers\n" +
"@@hash = {\'red\' => \'ruby\', \'white\' => \'pearl\'}\n" +
"def initialize(color, names)" +
"@color = color;" +
"@names = names;" +
"end\n" +
"def comment\n" +
"puts \"#{@names.join(\', \')}. Beautiful like a #{@@hash[@color]}!\"" +
"end\n" +
"def others(index)" +
"print \"If I omit #{@names[index]}, \";" +
"@names.delete_at(index);" +
"print \"others are #{@names.join(\', \')}.\n\"" +
"end\n" +
"end\n" +
"red = Flowers.new(\"red\", [\"cameliia\", \"hibiscus\", \"rose\", \"canna\"])\n" +
"white = Flowers.new(\"white\", [\"gardenia\", \"lily\", \"daisy\"])\n" +
"return red, white";
Object objects = engine.eval(script);
Invocable invocable = (Invocable) engine;
if (objects instanceof List) {
for (Object object : (List)objects) {
invocable.invokeMethod(object, "comment");
invocable.invokeMethod(object, "others", 1);
}
}

The Ruby script above defines two methods, comment and others, in the Flowers class. Just below the class definition, it created two instances whose names are red and white, then returns both instances at a time. In Java code, two instaces must be returned by packing in java.lang.Object typed single instance; thus, we should cast it into java.util.List type and take each instance out from it. Each instance is set to the first argument of invokeMethod().

Another way of getting Ruby created multiple instaces is to use global variables. Instead of returning values, instances are given over to Java by delaring them global variables. The snippet below shows how to do this:
String script = 
"class Flowers\n" +
"@@hash = {\'red\' => \'ruby\', \'white\' => \'pearl\'}\n" +
"def initialize(color, names)" +
"@color = color;" +
"@names = names;" +
"end\n" +
"def comment\n" +
"puts \"#{@names.join(\', \')}. Beautiful like a #{@@hash[@color]}!\"" +
"end\n" +
"def others(index)" +
"print \"If I omit #{@names[index]}, \";" +
"@names.delete_at(index);" +
"print \"others are #{@names.join(\', \')}.\n\"" +
"end\n" +
"end\n" +
"$red = Flowers.new(\"red\", [\"cameliia\", \"hibiscus\", \"rose\", \"canna\"])\n" +
"$white = Flowers.new(\"white\", [\"gardenia\", \"lily\", \"daisy\"])";
engine.eval(script);
Object red = engine.get("red");
Object white = engine.get("white");
Invocable invocable = (Invocable) engine;
invocable.invokeMethod(red, "comment");
invocable.invokeMethod(white, "comment");
invocable.invokeMethod(red, "others", 1);
invocable.invokeMethod(white, "others", 2);

Ruby's class difinition is exactly identical to the one that returns multiple instances. The differences are the last part that global variables, red and white, are used to assign instacnes. In Java code, two instances are get through JRuby engine's context.

Please read my former post to know how to get return value from method invocations or how to use global variables in methods.

Following code is an enitre one to perfome snippets illustrated here:
package canna;

import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class InvokingMethodsExample {
private InvokingMethodsExample()
throws ScriptException, NoSuchMethodException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
invokeSimpleMethod(engine);
invokeMethodWithMultipleInstances(engine);
invokeMethodWithGlobalVariables(engine);
}

private void invokeSimpleMethod(ScriptEngine engine)
throws ScriptException, NoSuchMethodException {
String script =
"module SomeModule\n" +
"def say()" +
"puts \"Hi, there!\"" +
"end\n" +
"end\n" +
"class SomeClass\n" +
"include SomeModule;" +
"end\n" +
"SomeClass.new";
Object object = engine.eval(script);
Invocable invocable = (Invocable) engine;
invocable.invokeMethod(object, "say");
script =
"class AnotherClass\n" +
"def say_it_again()" +
"puts \"OK. I said, \'Hi, there.\'\"" +
"end\n" +
"end\n" +
"AnotherClass.new";
object = engine.eval(script);
invocable.invokeMethod(object, "say_it_again");
}

private void invokeMethodWithMultipleInstances(ScriptEngine engine)
throws ScriptException, NoSuchMethodException {
String script =
"class Flowers\n" +
"@@hash = {\'red\' => \'ruby\', \'white\' => \'pearl\'}\n" +
"def initialize(color, names)" +
"@color = color;" +
"@names = names;" +
"end\n" +
"def comment\n" +
"puts \"#{@names.join(\', \')}. Beautiful like a #{@@hash[@color]}!\"" +
"end\n" +
"def others(index)" +
"print \"If I omit #{@names[index]}, \";" +
"@names.delete_at(index);" +
"print \"others are #{@names.join(\', \')}.\n\"" +
"end\n" +
"end\n" +
"red = Flowers.new(\"red\", [\"cameliia\", \"hibiscus\", \"rose\", \"canna\"])\n" +
"white = Flowers.new(\"white\", [\"gardenia\", \"lily\", \"daisy\"])\n" +
"return red, white";
Object objects = engine.eval(script);
Invocable invocable = (Invocable) engine;
if (objects instanceof List) {
for (Object object : (List)objects) {
invocable.invokeMethod(object, "comment");
invocable.invokeMethod(object, "others", 1);
}
}
}

private void invokeMethodWithGlobalVariables(ScriptEngine engine)
throws ScriptException, NoSuchMethodException {
String script =
"class Flowers\n" +
"@@hash = {\'red\' => \'ruby\', \'white\' => \'pearl\'}\n" +
"def initialize(color, names)" +
"@color = color;" +
"@names = names;" +
"end\n" +
"def comment\n" +
"puts \"#{@names.join(\', \')}. Beautiful like a #{@@hash[@color]}!\"" +
"end\n" +
"def others(index)" +
"print \"If I omit #{@names[index]}, \";" +
"@names.delete_at(index);" +
"print \"others are #{@names.join(\', \')}.\n\"" +
"end\n" +
"end\n" +
"$red = Flowers.new(\"red\", [\"cameliia\", \"hibiscus\", \"rose\", \"canna\"])\n" +
"$white = Flowers.new(\"white\", [\"gardenia\", \"lily\", \"daisy\"])";
engine.eval(script);
Object red = engine.get("red");
Object white = engine.get("white");
Invocable invocable = (Invocable) engine;
invocable.invokeMethod(red, "comment");
invocable.invokeMethod(white, "comment");
invocable.invokeMethod(red, "others", 1);
invocable.invokeMethod(white, "others", 2);
}

public static void main(String[] args) throws ScriptException, NoSuchMethodException {
new InvokingMethodsExample();
}
}

If this code gets run successfully, it produces outputs below:
Hi, there!
OK. I said, 'Hi, there.'
cameliia, hibiscus, rose, canna. Beautiful like a ruby!
If I omit hibiscus, others are cameliia, rose, canna.
gardenia, lily, daisy. Beautiful like a pearl!
If I omit lily, others are gardenia, daisy.
cameliia, hibiscus, rose, canna. Beautiful like a ruby!
gardenia, lily, daisy. Beautiful like a pearl!
If I omit hibiscus, others are cameliia, rose, canna.
If I omit daisy, others are gardenia, lily.

Sunday, March 09, 2008

Tips for JRuby engine: how to invoke Ruby's methods

This is the third post of "Tips for JRuby engine" series I've written in this blog. This post is focused on how Java can invoke Ruby defined methods. Users of JRuby engine might want to have Ruby as their first language to process complicated issues and use Ruby's methods in Java. Or, they already have a bunch of methods written in Ruby and feel happy if those methods are also available to reuse in Java code without any modification. JSR 223 scripting APIs have javax.script.Invocable interface and invokeFunction/invokeMethod methods defined in it. This interface is designed to enable users to invoke procedures and functions defined by dynamic languages from Java. The method, invokeFunction(), is used when a method is defined outside of classes or modules, which is known as a top-level method in Ruby. On the other hand, invokeMethod() method is applied when the method is defined in a class or module. In this post, I'll write about how to use invokeFunction() method, and the next post will be the one about invokeMethod().

To invoke Ruby defined top-level methods, a programmer need to eval scripts prior to use the invokeFunction() method. JRuby engine doesn't know the method specified in the first argument of invokeFunction() really exists and is ready to use unless it evals the script that has the definition of the method. Therefore, two steps are required to run Ruby's methods over JSR 223 APIs - first, eval(), and second, invokeFunction(). The most simple method invocation would be like this:
String script = 
"def say_something()" +
"puts ¥"I¥'m sleepy since it¥'s spring!¥"" +
"end";
engine.eval(script);
Invocable invocable = (Invocable) engine;
invocable.invokeFunction("say_something");

As for JRuby engine, "new Object[]{}" or "null" can be used as a second argument if Ruby's method doesn't need any argument. Compiler might complain about it, but the code works.

The next snippet shows the way of invoking the method with arguments. If people look at JDK 1.6 API document, they will know that invokeFunction() method can have multiple arguments to give over to Ruby's method. Argumnets are either a simple object array or varargs. A method invocation with arguments would look like:
String script =
"def come_back(type, *list)" +
"print ¥"#{type}: #{list.join(¥',¥')}¥";" +
"print ¥"...¥";" +
"list.reverse_each {|l| print l, ¥",¥"};" +
"print ¥"¥n¥";" +
"end";
engine.eval(script);
Invocable invocable = (Invocable) engine;
invocable.invokeFunction("come_back",
"sol-fa",
"do", "re", "mi", "fa", "so", "ra", "ti", "do");

The first argument of invokeFunction() method is the name of Ruby's method to invoke: rest of all arguments are the ones that Ruby's method needs to execute.

Then, a simple question might be come up with - how can I get return values over a method invocation? The JSR 223 method, invokeFunction() returns a single value whose type is java.lang.Object. This means that a programmer can get any type of Java object after executing Ruby's method if Ruby returns value(s). It is simple to get a single object as the return value since a Ruby’s object is mapped to the same type of a Java object. The perplexities might come from that Ruby’s method can return multiple values, not only one like Java. In this case, return values are elements of an array object; therefore, java.util.List typed object would be returned, and the code would look like the one below:
String script =
"def get_by_value(hash, value)" +
"hash.select { |k,v| v == value }" +
"end";
engine.eval(script);
Invocable invocable = (Invocable) engine;
Map map = new HashMap();
map.put("ruby", "red");
map.put("pearl", "white");
map.put("rhino", "gray");
map.put("rose", "red");
map.put("nimbus", "gray");
map.put("gardenia", "white");
map.put("camellia", "red");
Object object = invocable.invokeFunction("get_by_value", map, "red");
System.out.print( "red: ");
if (object instanceof List) {
for (Object element: (List)object) {
if (element instanceof List) {
for (Object param : (List)element) {
System.out.print(param + " ");
}
}
}
}
System.out.println();

So far, programmers could come to invoke Ruby's method from Java satisfactorily, but should they put all objects along with in the arguments' row of invokeFunction() method? Even if the programmers can put multiple arguments whatever they need to run Ruby's method correctly, it is confusing as the number of arguments increases. Using global variables would help to reduce putting many arguments. Here's a example code that reduced arguments from above snippet by using a global variable:
String script =
"def get_by_value(value)" +
"$hash.select { |k,v| v == value }" +
"end";
engine.put("hash", map);
engine.eval(script);
Invocable invocable = (Invocable) engine;
Object object = invocable.invokeFunction("get_by_value", "white");

The code below is an entire class to perform all of above snippets:
package canna;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class InvokingFunctionsExample {
private InvokingFunctionsExample()
throws ScriptException, NoSuchMethodException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
invokeSimpleFunction(engine);
invokeFunctionWithArguments(engine);
Map map = new HashMap();
map.put("ruby", "red");
map.put("pearl", "white");
map.put("rhino", "gray");
map.put("rose", "red");
map.put("nimbus", "gray");
map.put("gardenia", "white");
map.put("camellia", "red");
invokeFunctionWithReturns(engine, map);
invokeFunctionWithGlobalVariables(engine, map);
}

private void invokeSimpleFunction(ScriptEngine engine)
throws ScriptException, NoSuchMethodException {
String script =
"def say_something()" +
"puts \"I\'m sleepy because I went to bed three in the morning!\"" +
"end";
engine.eval(script);
Invocable invocable = (Invocable) engine;
invocable.invokeFunction("say_something");
}

private void invokeFunctionWithArguments(ScriptEngine engine)
throws ScriptException, NoSuchMethodException {
String script =
"def come_back(type, *list)" +
"print \"#{type}: #{list.join(\',\')}\";" +
"print \"...\";" +
"list.reverse_each {|l| print l, \",\"};" +
"print \"\n\";" +
"end";
engine.eval(script);
Invocable invocable = (Invocable) engine;
invocable.invokeFunction("come_back",
"sol-fa",
"do", "re", "mi", "fa", "so", "ra", "ti", "do");
}

private void invokeFunctionWithReturns(ScriptEngine engine, Map map)
throws ScriptException, NoSuchMethodException {
String script =
"def get_by_value(hash, value)" +
"hash.select { |k,v| v == value }" +
"end";
engine.eval(script);
Invocable invocable = (Invocable) engine;
Object object = invocable.invokeFunction("get_by_value", map, "red");
printValues("red", object);
object = invocable.invokeFunction("get_by_value", map, "gray");
printValues("gray", object);

}

private void printValues(String value, Object object) {
System.out.print(value + ": ");
if (object instanceof List) {
for (Object element: (List)object) {
if (element instanceof List) {
for (Object param : (List)element) {
System.out.print(param + " ");
}
}
}
}
System.out.println();
}

private void invokeFunctionWithGlobalVariables(ScriptEngine engine, Map map)
throws ScriptException, NoSuchMethodException {
String script =
"def get_by_value(value)" +
"$hash.select { |k,v| v == value }" +
"end";
engine.put("hash", map);
engine.eval(script);
Invocable invocable = (Invocable) engine;
Object object = invocable.invokeFunction("get_by_value", "white");
printValues("white", object);
}

public static void main(String[] args)
throws ScriptException, NoSuchMethodException {
new InvokingFunctionsExample();
}
}

When this code gets run successfully, it will produce following outputs.
I'm sleepy because I went to bed three in the morning!
sol-fa: do,re,mi,fa,so,ra,ti,do...do,ti,ra,so,fa,mi,re,do,
red: rose red camellia red ruby red
gray: rhino gray nimbus gray
white: gardenia white pearl white

Tow methods defined in JSR 223 APIs, invokeFunction() and invokeMethod(), are powerful, but have a little API flaw. We can't give a block over when we invoke Ruby's methods from Java. For example, Ruby allows us to use "yield" in a method and give different blocks needed to run a bit differently:
def search(array)
for item in array
return item if yield(item)
end
end
result = search(["camellia", "gardenia", "nimbus"]) {|str| str[0] ==?c}
print result, "\n"

Unofortunately, we don't have any way of doing this.

Saturday, March 08, 2008

Tips for JRuby engine: how to share objects mutually

This is the second tips for JRuby engine in addition to the first one. In this post, I'll show you how to share the same instances in both Java and Ruby, in other words, referring Java-created objects in Ruby, and contrarily, Ruby-created objects in Java.

To refer the same instances in both languages, a global variable is a key concept. If a coder have experienced Ruby programming, he or she must know what is a Ruby's global variable. In Ruby, a name of a global variable is defined to start with a symbol, '$,' such as $name or $file. An object that Java instantiated is always referred as the global variable in Ruby code; consequently, Java-created object's name must start with '$' in a script. The name of a global variable is exactly the same as the attribute name in Java, but those names don't start with '$'. Instead, the name taken off the beginning '$' character such as "name" or "file" is used for Java's attribute name.

For example, suppose a java.util.List typed instance is created and set to the context of a script engine with the attribute name, "list" by using put() method in Java. Then, Ruby runtime knows that the global variable, $list, and the associated instance exist. Here's code snippets that demonstrates how the instance is created and refered:

List list = new ArrayList();
list.add("What's up?");
list.add("How're you doing?");
list.add("How have you been?");
engine.put("list", list);
String script = "$list.each {|msg| puts msg }";
engine.eval(script);


If a coder created an object in Ruby and wanted to refer it in Java, he or she should name the instance like $something in Ruby and retrieve it from engine's context by the name, "something". Here's another snippets that shows how to do this:

String script = "$seasons = ['spring', 'summer', 'fall', 'winter']";
engine.eval(script);
List seasons = (List) engine.get("seasons");
for (String season : seasons) {
System.out.println(season);
}


Like this, global variables are often used to share the same instance in both languages; moreover, we have one more way to share a Ruby-created instance in Java. This is done by returning a value. In this case, both Ruby and Java don't use any global varibale while Ruby takes local variables, and Java assigns them to whatever it needs. Suppose Ruby code returns an array whose local variable name is colors, then Java receives a java.util.List typed object as a return value by invoking script engine's eval method(). The snippets is shown below:

script = "colors = ['red', 'green', 'white', 'blue'];" +
"colors.reverse";
List colors = (List) engine.eval(script);
for (String color : colors) {
System.out.println(color);
}

Although only the first line of the script is enough to get the return value from Ruby, I added the second line because it is too short for users to understand the script is Ruby code.

As I talked about, we have two ways to share instances between Ruby and Java by using a JSR 223 scripting engine. If you use global variables, you can share multiple instances at a time. On the other hand, you can share only one instance when you do it by returning value. However, sometimes, users need to get a returned value after processing some algorithm, so the choice is on the users. Of course, users can mix two ways to share instances.

The code below is an entire class used for this tips:
package canna;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class ReferringObjectsExample {

private ReferringObjectsExample() throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
createObjectsInJava(engine);
createObjectsInRuby(engine);
}

private void createObjectsInJava(ScriptEngine engine) throws ScriptException {
// giving an object to Ruby as a global variable
List list = new ArrayList();
list.add("What's up?");
list.add("How're you doing?");
list.add("How have you been?");
engine.put("list", list);
String script = "$list.each {|msg| puts msg }";
engine.eval(script);
engine.put("first", 2008);
script = "$first.step(2015, 2) {|i| puts i }";
engine.eval(script);
}

private void createObjectsInRuby(ScriptEngine engine) throws ScriptException {
// referring an object as a global variable
String script = "$seasons = ['spring', 'summer', 'fall', 'winter']";
engine.eval(script);
List seasons = (List) engine.get("seasons");
for (String season : seasons) {
System.out.println(season);
}
// receiving an array object returned from Ruby
script = "colors = ['red', 'green', 'white', 'blue'];"+
"colors.reverse";
List colors = (List) engine.eval(script);
for (String color : colors) {
System.out.println(color);
}
// receiving a hash object returned from Ruby
script = "gpas1 = {\"Alice\" => 3.75, \"Bob\" => 4.0};"+
"gpas2 = {\"Alice\" => 3.92, \"Chris\" => 3.55};"+
"gpas1.merge!(gpas2)";
Map gpas = (Map)engine.eval(script);
for (String name : gpas.keySet()) {
System.out.println(name +": " + gpas.get(name));
}
}

public static void main(String[] args) throws ScriptException {
new ReferringObjectsExample();
}
}
When the code gets run, it outputs like this:

What's up?
How're you doing?
How have you been?
2008
2010
2012
2014
spring
summer
fall
winter
blue
white
green
red
Alice: 3.92
Bob: 4.0
Chris: 3.55

Thursday, March 06, 2008

Tips for JRuby engine: how to get engine's instance

Writing a code by using scripting API introduced in JDK 6 might be enjoyable because it enables us to use both dynamic languages and Java at a time, smoothly. Moreover, it enables to mix multiple dynamic languages without writing any Java code. For example, Rhino can execute Ruby code over scripting API. However, documents are few, unfortunately, and users often confuse how to use the API. In light of this bad situation, I'll try to give users some tips about JRuby engine to possibly help them out from annoying exceptions and errors.

The first tips are how to get an engine's instance, which is a prerequisite to get scripts run. Scripting API has a couple of methods available. As for JRuby engine, following three ways work well for getting javax.script.ScriptEngine typed instance:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
or

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("ruby");
or

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByExtension("rb");

Users can get engine's instance by one of these. Although scripting API defines ScriptEngineManager#getEngineByMimeType() method, no coder can use this method. Since JRuby engine doesn't define its mime types obtainable, users don't have any parameter to pass to.

Here's an entire example code for the first step:
package canna;

import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class GettingEngineExample {
GettingEngineExample() throws ScriptException {
caseOne();
caseTwo();
caseThree();
caseFour();
}

void caseOne() throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
ScriptEngineFactory factory = engine.getFactory();
System.out.println("engine name: " + factory.getEngineName());
System.out.println("version: " + factory.getEngineVersion());
engine.eval("puts 'Case one: getEngineByName(\"jruby\").'");
}

void caseTwo() throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("ruby");
ScriptEngineFactory factory = engine.getFactory();
System.out.println("engine name: " + factory.getEngineName());
System.out.println("version: " + factory.getEngineVersion());
engine.eval("puts 'Case two: getEngineByName(\"ruby\").'");
}

void caseThree() throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByExtension("rb");
ScriptEngineFactory factory = engine.getFactory();
System.out.println("engine name: " + factory.getEngineName());
System.out.println("version: " + factory.getEngineVersion());
engine.eval("puts 'Case three: getEngineByExtension(\"rb\").'");
}

void caseFour() {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByExtension("rb");
ScriptEngineFactory factory = engine.getFactory();
List names = factory.getMimeTypes();
System.out.println("mime types are ...");
for (String name : names) {
System.out.print(name);
}
}

public static void main(String[] args) throws ScriptException {
new GettingEngineExample();
}
}
This code outputs like this:

engine name: JRuby Engine
version: 1.1.1
Case one: getEngineByName("jruby").
engine name: JRuby Engine
version: 1.1.1
Case two: getEngineByName("ruby").
engine name: JRuby Engine
version: 1.1.1
Case three: getEngineByExtension("rb").
mime types are ...

JRuby 1.1 RC3 is about to release

A few days have passed since the version name 1.1RC3 disappeared from issue jira of JRuby. And, Charles Nutter posed what would be showstoppers for final RC verison, RC3 to jruby-dev ml. So, we could know JRuby 1.1RC3 is about to released in a couple of days.
How about JRuby engine? As far as I tested JRuby engine by using trunk version, JRuby engine should not need any bug fixes to catch up with a new release of JRuby. Updating README.TXT would be enough. Easy, this time.

Wednesday, March 05, 2008

Download site just for JRuby engine

Today, I created the download site just for JRuby eninge at scripting.dev.java.net. I've thought this kind of site should have existed since I updated JRuby engine for JRuby 1.1RC1. As for current release style of the scripting project, only one binary archive of each dynamic language is ready to download. This style might have been enough before and easy to release a bunch of engines for individual dynamic languages at a time. However, dynamic languages have had multiple versions which require different implementations of engines recently.
A request from a user made me start working on it yesterday. Looking around links to help pages in the project home, I discovered that creating a new page under the project in dev.java.net was quit easy. Just clicking on the link and filling out a small form. That's it.
From now on, I can update JRuby engine's binary archives compliant to the latest JRuby anytime.

Monday, March 03, 2008

JSR223 JRuby engine update

I fixed one more bug to make JRuby engine work on JRuby 1.1RC2 yesterday, so I updated CVS today. Now, the latest version in CVS repo is compliant to JRuby 1.1RC2.

I figured out that another bug was caused by newly added org.jruby.util.io.ChannelStream class to JRuby. ChannelStream has a sync member which is set to be false by default and flushes the output buffer only when the sync's value is true, or huge strings are set to output buffer. A ChannelStream type instance used in an ordinary eval process has the true value in its sync; however, it has false when it is used from the process starts from IRubyObject#callMethod(). I fixed this by forcibly setting true to the sync since I couldn't figure out when and by whom its value is changed into true in JRuby.

I encountered further bug when I ran examples on Mac OS X. This should be the bug of JDK 1.6 for Max OS X because it never happens on Ubuntu. When a big Ruby script is pared by the parseEval method, a part of script seems to be truncate because JRuby raises a syntax error though Ruby scripts are written in completely correct syntax. JRuby engine has a way of avoiding this bug which is to set a filename of the Ruby script to JRuby engine's context by using a "ScriptEngine.FILENAME" property.

My next work would be to write more examples and tests to know how perfect the engine works with current and future versions of JRuby.

Thursday, February 28, 2008

bug fixing for JSR223 JRuby engine

I started debuggig JSR223 JRuby engine to make this work on JRuby 1.1RC2. Right now, JRuby engine in CVS, the latest version, is compliant to JRuby 1.1RC1 only. Since some internal APIs that JRuby engine uses has changed in JRuby 1.1 RC2, the engine doesn't work correctly.
Today, I fixed an easy bug related to GlobalVariables. Again, GlobalVariables. Many bugs of JRuby engine have found in its own definition to override GlobalVariables. JRuby engine needs to have own GlobalVariables' definition because JRuby engine has to work under mutil-threads environment. JRuby engine wants single JRuby instance to eval many Ruby scripts concurrently, while JRuby basically degined to eval one script only once in single JRuby instance. GlobalVariables' instance might be critical. Therefore, JRuby engine must protect GlobalVariables' instance not to be refered concurrently and should be resposible to restore an original interal state when each eval completes.

They added new member, defaultSeparator, in GlobalVariables, but this new parameter couldn't get from JRuby engine's GlobalVariables. Just adding one small accessor method fixed this bug.

However, invokeFunction and invokeMethod methods haven't work at all without any exceptions nor compile errors. Fixes for these might take longer time.

Monday, January 28, 2008

Exam of Certified Programmer for Ruby in English will start in April

Ruby Association has operated the exam to certify a programmer for Ruby three times since October, 2007. The association has organized the paper based exam only in Japanese and at two cities in Japan so far; however, the exam will be improved vastly from January. According to the article reported about extension of the exam on January 22, 2008, Prometric is responsible to the exam (Press Release in Japanese) from the beginning of the year and the first CBT Ruby exam is scheduled in February. Prometric will start English version of this exam in the end of April this year in 135 countries all over the world.

Paper based old exam of a certified programmer for Ruby had fifty multiple-choice questions for ninty minutes. This web site(Japanese only) has helped examinees from the first exam and advices them to study with the book , Programming Ruby: The Pragmatic Programmer's Guide, 2nd Ed.

Saturday, January 26, 2008

Matz objected to the article about PHP's string processing

Note: Here's my version of translation without any permission nor consent of an original author. This is done just for my English training. But I'm happy if this is a good source to know what's going on in Japanese community.


In his blog (http://www.rubyist.net/~matz/20080125.html), Matz, the creator of Ruby, objected to the on-line article that explained about PHP's string processing. Matz quoted the author's view:
"One of the current topics is we'll be in trouble when we use both binary-safe and binary-unsafe functions at a time (http://www.atmarkit.co.jp/fsecurity/rensai/httpbasic04/httpbasic03.html)."

and argued that the existence of these two kinds of functions itself was unacceptable. Matz even thought this should be an architectural flaw.

Although Matz admitted the necessity of C-string, he asserted that string processing functions must be independent of the factor binary-safe or not. For example, a null character is never fit in a file path; therefore, runtime should raise an error when a null character is detected while examination is going on.

As he wrote in his blog, Matz regarded it as a bug when imperfect examination failed to find null string in a wrong place. He insisted Ruby has his idea now.

Wednesday, August 29, 2007

ActiveRecord Migration: how to write and the results

Recently, I started learning Ruby on Rails which is getting more and more popular than a Java based web application framework. Ideas and cultures are quite different from those of Java, so I have struggled to understand them. What I figured out first was that Ruby on Rails programming is tightly coupled to database tables. Creating a table in a database is the first step of every programming. To cope with a database, Rails provides us a tool, ActiveRecord, to connect to the database, and to create tables in the database. ActiveRecord enables us to migrate from a table definition written by ruby to the database schema. This is the memo how a migration can be defined and what tables in databases I got as a result of the migration.

When I wrote a database table definition for a migration, I referred to the web pages listed below.
For example, from this table definition in SQL, I defined following ruby file.
CREATE TABLE items (
id smallint(5) unsigned NOT NULL auto_increment,
done tinyint(1) unsigned NOT NULL default '0',
priority tinyint(1) unsigned NOT NULL default '3',
description varchar(40) NOT NULL default '',
due_date date default NULL,
category_id smallint(5) unsigned NOT NULL default '0',
node_id smallint(5) unsigned default NULL,
private tinyint(3) unsigned NOT NULL default '0',
created_on timestamp(14) NOT NULL,
updated_on timestamp(14) NOT NULL,
PRIMARY KEY (id)
) TYPE=MyISAM COMMENT='List of items to be done';

class CreateItems < ActiveRecord::Migration
def self.up
create_table :items do |t|
t.column :done, :integer, :null => false, :default => 0
t.column :priority, :integer, :null => false, :default => 3
t.column :description, :string, :limit => 40, :null => false, :default =>''
t.column :due_date, :date, :null => true, :default => nil
t.column :category_id, :integer, :null => false, :default => 0
t.column :note_id, :integer, :null => true, :default => nil
t.column :private, :integer, :null => false, :default => 0
t.column :created_on, :timestamp, :null => false
t.column :updated_on, :timestamp, :null => false
end
end

def self.down
drop_table :items
end
end
According to the API documentation of ActiveRecord::ConnectionAdapters::TableDefinition, data type must be one of primary_key, string, text, integer, float, decimal, datetime, timestamp, time, date, binary, and boolean. Therefore, I mapped both smallint and tinyint types to a integer type. I could write the size of integer precisely by adding :limit, but I didn't do that. There's no unsigned integer type, and I have to care not to have negative values.

What I didn't mapped to the ruby file at all was “TYPE=MyISAM COMMENT='List of items to be done';” in the last line of SQL. I could have written like this:
create_table :items, :options => 'engine=MyISAM' do |t|
However, this MySQL specific parameter doesn't have any special effect because my DBMS is Apache Derby that comes with NetBeans.

Here's another mapping example. This shows how I can define UNIQUE KEY in a ruby file.
CREATE TABLE 'categories' (
id smallint(5) unsigned NOT NULL auto_increment,
category varchar(20) NOT NULL default ''
created_on timestamp(14) NOT NULL,
updated_on timestamp(14) NOT NULL,
PRIMARY KEY ('id'),
UNIQUE KEY 'category_key' ('category')
) TYPE=MyISAM COMMENT='List of categories'

class CreateCategories < ActiveRecord::Migration
def self.up
create_table :categories do |t|
t.column :category, :string, :limit => 20, :default => '', :null => false
t.column :created_on, :timestamp, :null => false
t.column :updated_on, :timestamp, :null => false
end
add_index :categories, :category, :unique => true, :name => 'category_key'
end

def self.down
drop_table :categories
end
end

Executing migration is the next step after defining the database table in ruby. Before doing it, I edited config/databse.yml and config/environment.rb to set up a connection to the database as follows:
databse.yml(exerpt)
development:
adapter: jdbc
driver: org.apache.derby.jdbc.ClientDriver
url: jdbc:derby://localhost:1527/todos
username: foo
password: bar
encoding: utf8

evironment.rb(excerpt)
RAILS_GEM_VERSION = '1.2.3' unless defined? RAILS_GEM_VERSION

require File.join(File.dirname(__FILE__), 'boot')

if RUBY_PLATFORM =~ /java/
require 'rubygems'
RAILS_CONNECTION_ADAPTERS = %w(jdbc)
end

Rails::Initializer.run do |config|
end

To make it happen, I chose “Migrate Database” from menus provided by NetBeans IDE(Go to the Projects window, right click on the project name, choose“Migrate Database” from a popup menu then select “To Current Version”). This is equivalent to run “rake db:migrate” command. NetBeans showed some messages on Output window, and create the table in the database. Though I can see what table was created on NetBeans, I dared check it interactively by running ij command of Apache Derby because outputs in interactive mode was more familiar than properties in the
popup window.

$ java -jar lib/derbyrun.jar ij
ij> connect 'jdbc:derby://localhost:1527/todos' user 'foo' password 'bar';
ij> describe items;
COLUMN_NAME |TYPE_NAME|DEC&|NUM&amp;amp;|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
ID |INTEGER |0 |10 |10 |GENERATED&|NULL |NO
DONE |INTEGER |0 |10 |10 |0 |NULL |NO
PRIORITY |INTEGER |0 |10 |10 |3 |NULL |NO
DESCRIPTION |VARCHAR |NULL|NULL|40 |'' |80 |NO
DUE_DATE |DATE |0 |10 |10 |NULL |NULL |YES
CATEGORY_ID |INTEGER |0 |10 |10 |0 |NULL |NO
NOTE_ID |INTEGER |0 |10 |10 |NULL |NULL |YES
PRIVATE |INTEGER |0 |10 |10 |0 |NULL |NO
CREATED_ON |TIMESTAMP|6 |10 |26 |NULL |NULL |NO
UPDATED_ON |TIMESTAMP|6 |10 |26 |NULL |NULL |NO

ij> describe categories;
COLUMN_NAME |TYPE_NAME|DEC&|NUM&amp;amp;|COLUM&|COLUMN_DEF|CHAR_OCTE&|IS_NULL&
------------------------------------------------------------------------------
ID |INTEGER |0 |10 |10 |GENERATED&|NULL |NO
CATEGORY |VARCHAR |NULL|NULL|20 |'' |40 |NO
CREATED_ON |TIMESTAMP|6 |10 |26 |NULL |NULL |NO
UPDATED_ON |TIMESTAMP|6 |10 |26 |NULL |NULL |NO

ij> show indexes from categories;
TABLE_NAME |COLUMN_NAME |NON_U&|TYPE|ASC&amp;amp;|CARDINA&|PAGES
----------------------------------------------------------------------------
CATEGORIES |CATEGORY |0 |3 |A |NULL |NULL
CATEGORIES |ID |0 |3 |A |NULL |NULL

For comparison, I tried the migration in the same way by using well-used MySQL. On MySQL, the table was created like this:
mysql> describe items;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| done | int(11) | NO | | 0 | |
| priority | int(11) | NO | | 3 | |
| description | varchar(40) | NO | | NULL | |
| due_date | date | YES | | NULL | |
| category_id | int(11) | NO | | 0 | |
| note_id | int(11) | YES | | NULL | |
| private | int(11) | NO | | 0 | |
| created_on | datetime | NO | | NULL | |
| updated_on | datetime | NO | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
10 rows in set (0.01 sec)

We can see small differences in length of an integer type, a mapping of a timestamp type and default value of a varchar type.

Every time I try to run Rails samples, I'm often puzzled how I can write schema definitions in ruby and how the migration works from definitions to real tables on database. This memo would help me not to be confused next time.

Tuesday, June 12, 2007

Four Days on Rails by NetBeans

Recently, I have been intent on learning (J)Ruby on Rails. Many books are in bookstores, and so many tutorials are on the Internet. I had a bit hard time what was the good one to start learning. Wondering around the Internet, I found "Four Days on Rails"(http://rails.homelinux.org/) is one of the best tutorials though it is a little bit old. It is based on a command line interface and older version of Rails. However, I successfully got the examples in tutorials work on NetBeans after struggling with both NetBeans and Rails. Here's a memo how I could run the first example and get an output on my browser.

The example ran on...
  • Ubuntu 6.10
  • JDK 1.6.0
  • JRuby 1.0
  • NetBeans 6.0M9
  • Java DB(a.k.a. Apache Derby) included in NetBeans
Before I create Ruby on Rails project, I updated JRuby from 0.9.8 to 1.0 as in my previous blog. I think updating JRuby might be optional, but the latest version would be better because it is the best version so far.
  1. Creating the ToDo project
    • Click File -> select New Project -> click Ruby -> click Ruby on Rails Application -> type "ToDo" in the Project Name box -> click Next -> click the Install Rails button if Rails is not installed and click Close button after Rails is installed -> click Finish
  2. Setting up the database
    • As in the tutorial, "Creating a Ruby Weblog in 10 Minites," edit database.yml and envitonment.rb to make Java DB available from a Rails Application.
    • Goto Projects window and expand Configuration folder -> open database.yml and edit lines after the "development:" so as to be in followings
    • development:
      adapter: jdbc
      driver: org.apache.derby.jdbc.ClientDriver
      url: jdbc:derby://localhost:1527/todos
      username: foo
      password: bar
    • Open environment.rb and add a following snippet before the line "Rails::Initializer.run do |config|" to plug in the JDBC adaptor.
      if RUBY_PLATFORM =~ /java/
      require 'rubygems'
      RAILS_CONNECTION_ADAPTERS = %w(jdbc)
      end
  3. Creating the todos database on Java DB
    • Click Tools -> select Java DB Database -> click Create Java DB Database... -> type the database name, user name, and password in the boxes as follows:
      Database Name: todos
      User Name: foo
      password: bar
  4. Connecting the todos database
    • Go to the Runtime window -> expand Databases -> right-click the todos database -> select Connect...
  5. Creating the category model
    • Go to the Projects window -> right-click the Models node under the ToDo project -> select Generate... -> type the model name, Category, in the box -> click OK
      Arguments: Category
  6. Creating the categories table in the todos database
    • Open the generated file, 001_create_categories.rb, and edit it to be shown below.
      class CreateCategories < ActiveRecord::Migration
      def self.up
      create_table :categories do |t|
      t.column :category, :string, :limit => 20, :default => '', :null => false
      t.column :created_on, :timestamp, :null => false
      t.column :updated_on, :timestamp, :null => false
      end
      add_index :categories, :category, :unique => true, :name => 'category_key'
      end

      def self.down
      drop_table :categories
      end
      end
    • Go to Projects window -> right-click the ToDo project node -> select Migrate Database -> select To Current Version
    • If this completes successfully, the table, categories, is created in the todos database.
    • You might have problems on this stage. For me, restarting NetBeans was the good solution. You can find other solutions on the tutorial, "Creating a Ruby Weblog in 10 Minites."
  7. Creating the script controllers
    • Go to Projects window -> right-click the Controllers node under the ToDo project -> select Generate... -> type the controller name, Script, in the Name box and leave the View box blank -> click OK
      Name: Script
      Views:
    • Open the generated file, script_controller.rb, and edit it. The following code is the script_controller.rb after editing.
      class ScriptController < ApplicationController
      scaffold :category
      end
    • Expand the Configuration node under the ToDo project -> open route.rb and add following line just before the last "end" line.
      map.connect '', :controller => "script"
    • Expand the Public node under the ToDo project -> delete index.html
  8. Running the application
    • Right-click the ToDo project node -> select Run Project or click the Run Main Project button if the ToDo project is a main one.
    • In the browser, you see the page created by the Rails application.

Monday, June 11, 2007

Using JRuby 1.0 on NetBeans

Congratulations on JRuby 1.0 release! Right after the release, I successfully updated JRuby of my NetBeans. Here's what I did.
  1. Install JDK 1.6.0 or later. Ubuntu(and probably other Linux) users *must* use JDK 1.6.0(never use 1.6.0_01) to avoid the problem that some dialog windows of NetBeans don't open.
  2. Download a JRuby 1.0 binary version of archive from http://jruby.codehaus.org/ and extract files.
  3. If you use Java DB for a Ruby on Rails Application, make symbolic link to jdk1.6.0/db/lib/derbyclient.jar in the directory, jruby-1.0/lib or copy it in this directory.
  4. Download Full version of NetBeans 6.0M9 from http://bits.netbeans.org/download/6.0/milestones/latest/ and install it.
  5. Start up NetBeans.
  6. Click Tools in the tool bar, select Options, click Miscellaneous, and open Ruby Installation. Type full path to jruby command or click Browse button and select jruby command from extracted JRuby 1.0 files.
  7. Click Tools in the tool bar, select Ruby Gems, and click Update all button.
  8. Install Rails when you create Ruby on Rails project for the first time by clicking Next button in the dialog window in which you typed the project name. Install Rails button shows up to allow us to click it.
After updating JRuby from 0.9.8 to 1.0, I tried the 10 minutes example introduced at http://www.netbeans.org/kb/60/rapid-ruby-weblog.html. The example worked fine.

Sunday, March 18, 2007

Guice made a good start in Japan

A DI container Guice, which is written in Java and released from Google, has fascinated Japanese Java programmers since its 1.0 release in March 8, 2007. Everyday, they write blogs about Guice and shows how much they are zealous to explore Guice. It is clear that Guice made a good start in Japan. I'll introduce what they have written in their blogs.

Many bloggers refer to the online magazine article that explains what is Guice and how we write code using Guice. This article, http://journal.mycom.co.jp/articles/2007/03/14/googleguice/, was publishd in March 14, 2007, just six days after the release. The title might be "It is just like Google to think much of the sense of balance" in English. The author emphasizes Guice would be an effective DI container to innovate into Java based system because it realizes DI by API only.

Among bloggers, committers of Seasar2, which is a de facto DI container in Japan, express concerns for Guice. One of them wrote the result of the benchmark test including Guice, Spring and Seasar2 on the web site, http://d.hatena.ne.jp/arumani/20070316 . The code used for the benchmark test is based on PerformanceComparison class distributed with other Guice source code, and its patch to the original code can be seen at http://docs.google.com/Doc?id=dd3xcjm8_6ddtd3k . According to the result, we know Guice works far faster than Spring, while Seasar2's performance is very close to Guice. The Seasar2 committer analyzes the delay might have come from the slow start of an OGNL library.

Another blogger has trasnlated the User's Guide of Guice into Japanese for a couple of days, which can be read on the blog site, "http://d.hatena.ne.jp/iad_otomamay/ ." The blogger's activity would help to accelerate increasing Guice users in Japan because most Japanese programmers are reluctant to read English documents. Of course, there are some bloggers writing code snippets by using Guice. These would also help to swell up the number of Guice users since how to make a program is interpretted in Japanese.

Current situation would be the first Guice boom raised by skilled programmers who are good at reading source code; therefore, it might take more time for ordinary Java programmers to start to use Guice. Probably, the ordinary programmers would need more documents and articles to decide to embrace it so that they don't lose the way while they are writing code. However, Guice will surely thrive after gaining large amount of users.

Thursday, March 15, 2007

A complement to the example of Guice struts plugin


A Struts plugin provided by Guice has been my big concern because Sturts is used for web applications commonly. This would be one of the most attractive features in Guice. Today, I tried the counter example included in source code directory and explained in the user's guide. However, it was not easy to get the example to work. The explanation in the user's guide covers princepal parts but is not perfect. Working on the struts plugin example for a couple of hours on netbeans, I finally succeeded in running the Guice example. This is a complement to the example of Guice struts plugin.

All files that must be edited and created to work the counter example are
web.xml, struts.xml, Counter.java, Count.java, Counter.jsp. Each of all is as follows:
  • web.xml
    User's Guide doesn't refer to web.xml, but Counter class uses @SessionScoped annotation. GuiceFilter is necessary.

<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Struts Guice Test</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter>
<filter-name>guice</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guice</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

  • struts.xml
    The path defined in a result tag doesn't seem to be correct. WEB-INF is not needed.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.objectFactory" value="guice" />
<package name="strutsguicetest" extends="struts-default">
<action name="Count" class="com.google.inject.struts2.example.Count">
<result>/Counter.jsp</result>
</action>
</package>
</struts>

  • Counter.java
    I just added packge and import declarations

package com.google.inject.struts2.example;

import com.google.inject.servlet.SessionScoped;

@SessionScoped
public class Counter {
private int count = 0;

public synchronized int increment() {
return count++;
}

public Counter() {
}
}

  • Count.java
    I added package and import declarations and modified a static parameter SUCCESS

package com.google.inject.struts2.example;

import com.google.inject.Inject;
import com.opensymphony.xwork2.ActionSupport;

public class Count {
private final Counter counter;

@Inject
public Count(Counter counter) {
this.counter = counter;
}

public String execute() throws Exception {
return ActionSupport.SUCCESS;
}

public int getCount() {
return counter.increment();
}
}

  • Counter.jsp
    I edited netbeans generated jsp file, so nothing has changed in the main part.

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h1>JSP Page</h1>
<h2>Counter Example</h2>
<h3>
<b>Hits in this session:</b>
<s:property value="count"/>
</h3>
</body>
</html>

All libraries I set in the libraries directory are guice-1.0.jar, guice-servlet-1.0.jar, guice-struts2-plugin-1.0.jar, struts2-core-2.0.6.jar, xwork-2.0.1.jar, ognl-2.6.11.jar, freemarker-2.3.8.jar, commons-logging-1.0.4.jar, 8 jars in total. A file structure in my strutsguicetes project is shown in the above image.

The URL to make the example to run is http://localhost:8084/strutsguicetest/Count.action. Since netbeans assigns 8084 port to Tomcat 5.5.17, and my project name is strutsguicetest, I tried this URL. When I clicked a reload button, the number shown on my browser increased one by one.

Tuesday, March 13, 2007

Simple comparison with the two DI containers, Seasar and Guice

Lightweight DI container, Guice 1.0 has been released. This news draws remarkable attention of Japanese Java developers who use DI container in their products. While Seasar(http://www.seasar.org/en/), which has been developed by Japanese Java programmers, is a de fact DI container and is used broadly in Japan. To study how I can write a code using Guice, I rewrote the example introduced in Seasar's quick start tutorial(http://s2container.seasar.org/en/DIContainer.html#Quickstart) and compaired two types of programs reinforced by a DI containter.

The two programs I wrote show a simple well-known message, "Hello World!" and inject two implemented classes in each series of codes. In my programs, a GreetingClient type object uses a Greeting type object, and the implementation classes of Greeting and GreetingClient are injected. When I wrote codes for Guice, Paul Barry's blog(http://paulbarry.com/articles/2007/03/12/guice-hello-world) helped me a lot.

First three codes, Greeting.java, GreetingImpl.java and GreetingClinet.java are identical for both Seasar and Guice are utilized.

//Greeting.java
public interface Greeting {
String greet();
}

//GreetingImpl.java
public class GreetingImpl implements Greeting {

public GreetingImpl() {
}

public String greet() {
return "Hello World!";
}
}

//GreetingClient.java
public interface GreetingClient {
void execute();
}

However, the implementation class of GreetingClient for Guice has an @Inject annotation to inject the implementation for the Greeting type class, while it is still POJO as a Seasar's code.

//GreetingClientImpl.java for Guice
import com.google.inject.Inject;

public class GreetingClientImpl implements GreetingClient {
private Greeting greeting;

public GreetingClientImpl() {
}

public void execute() {
System.out.println(greeting.greet());
}

@Inject
public void setGreeting(Greeting greeting) {
this.greeting = greeting;
}
}

//GreetingClientImpl.java for Seasar
public class GreetingClientImpl implements GreetingClient {

private Greeting greeting;

public void setGreeting(Greeting greeting) {
this.greeting = greeting;
}

public void execute() {
System.out.println(greeting.greet());
}
}

Besides, I wrote the class to inject the implementation of GreetingClient, whereas the role of this class might be performed by a Dicon file for Seasar. The Dicon is an XML file and defines dependencies, adds intercepting classes and more.

//GreetingController.java for Guice
import com.google.inject.Inject;

public class GreetingController {
private GreetingClient greetingClient;

public GreetingController() {
}

public void execute() {
greetingClient.execute();
}

@Inject
public void setGreetingClient(GreetingClient greetingClient) {
this.greetingClient = greetingClient;
}
}

//GreetingMain2.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC
"-//SEASAR//DTD S2Container 2.3//EN"
"http://www.seasar.org/dtd/components23.dtd">
<components>
<component name="greeting"
class="examples.di.impl.GreetingImpl"/>
<component name="greetingClient"
class="examples.di.impl.GreetingClientImpl">
<property name="greeting">greeting
</component>
</components>

Main classes for Guice and Seasar are as follows.

// Main.java for Guice
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Guice;

public class Main {

public Main() {
Injector injector = Guice.createInjector(new GreetingModule());
GreetingController controller = new GreetingController();
injector.injectMembers(controller);
controller.execute();
}

public static void main(String[] args) {
new Main();
}

private class GreetingModule extends AbstractModule {
protected void configure() {
bind(Greeting.class).to(GreetingImpl.class);
bind(GreetingClient.class).to(GreetingClientImpl.class);
}
}
}

// Main.java for Seasar
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;

public class GreetingMain2 {

private static final String PATH =
"examples/di/dicon/GreetingMain2.dicon";

public static void main(String[] args) {
S2Container container =
S2ContainerFactory.create(PATH);
GreetingClient greetingClient = (GreetingClient)
container.getComponent("greetingClient");
greetingClient.execute();
}
}

Comparting two series of code powered by Guice and Seasar, I assured Guice is configuration free DI container. It is convenient, flexible and easy to understand. However, today's DI containers are not merely a DI container. They have additional useful features such as utility classes of logging, exception handling, integration to other products and etc. I wonder people who are accustomed to other DI container and have many codes depends on it can start to use Guice soon.

Anyway, Guice programming dosen't require to write XML based configuration file and is probably easy to use(I'm note sure because I just wrote one simple application).At least, it is a great advantage for users who newly started to use DI containers.

Thursday, March 08, 2007

Jar Archive setting of NetBeans Ruby Pack

Recently, NetBeans Ruby Pack has been released, so I tried it immediately. It's very sweat and exciting except one problem. How can I set a classpath to a jdbc diver jar archive? I googled again and again putting various key words in the box, which ended up vain efforts. Instead keep searching, I looked carefully each directory related to NetBeans because JUnit tests seem to work in Ruby on Rails project on NetBeans as in the demo video. Class names of JUnit don't start with java or javax, but JUnit classes seem to be available in Ruby project. I figured out. Jar archives used in Ruby and Ruby on Rails projects exist in the directory /home/username/.netbeans/dev/jruby-0.9.2/lib. When I made a link to derby.jar in that directory, I could get my JRuby code work successfully.
Released Ruby Pack is the very first version and might have bugs and lack of convenient features. By the time those would be fixed and improved, I will avoid the jar-archive-setting problem by making links to necessary jar archives.

Friday, February 09, 2007

Still now, Jini and JavaSpaces are sluggish in Japan

When I wrote about JavaSpaces a few days ago, I got the comment which pointed out my out-of-date knowledge. The real cases based on JavaSpaces (or Jini) have worked already, though my awareness was opposite. I should have researched American Web sites. Now, I know JavaSpaces and Jini have been improving steadily. On the contrary, the situation in Japan remains the same that I wrote in my blog from my old information. Jini and JavaSpaces are sluggish in Japan still now.

I googled to find out recent entries about Jini and JavaSpaces from Japanese Web sites. Many sites were listed; however, most articles were written in 1999 and 2000. Many of them has gone. Besides, I found one article written in 2002 which said Jini based application wasn't developed anymore. In this article(http://www.atmarkit.co.jp/news/200211/12/upnp.html) about UPnP, the writer said that Microsift's UPnP thrived while Jini technology was struggling to find the way. The writer also said that topics on Jini seldom showed up in those days. It is true. Everything I could find on the Japanese Internet sites was just two articles about Jini after 2002.

I don't know the reason why Jini and JavaSpaces have been depressed in Japan. I guess a simple web application would have been effective enough in the early 2000s. J2EE products would have been sold well thanks to the vendors' efforts or Japanese character that they love to act same as others. Since JEE has become too big, recently, there is obvious tendency amid Japanese Java developers to go over to lightweight language such as Ruby. This would be negative elements to popularize Jini or JavaSpaces.

I think big obstacles exist in Japan to make Jini or JavaSpaces technology be adopted into a real case right now.

Wednesday, February 07, 2007

Is XUL obscure? That's OK.

The article of XUL appeared on XML.com this February. It's a very recent article, which is a bit strange. I mean it is the least likely appearing one. As the writer describes XUL as "a little-known use," it is obscure technology. I like XUL, and feel happy to support it; however, I admit XUL application has been slowed its development speed for more than a couple of years except products from Mozilla foundation. Accordingly, I wondered why XUL was up in this time of period. Exciting, I read the article.

This article introduces XUL, supposedly, to readers who don't know it. The writer tries to impress the readers superiority of XUL by comparing with DHTML. The tree example successfully achieved this scheme. Rendering speed is fast; appearance is good. On the contrary, the writer says DHTML is more convenient than XUL implicitly. DHTML works on every browser including Firefox. This, of course, isn't the purpose, but his concern to DHML would help the readers' interest turn to DHTML. That he introduces the utility available for both XUL and DHTML might spur the readers on. I know the writer wanted to defend from a counter-argument. The number of users of XUL-enabled browsers is very small, so programmers are reluctant to support XUL. I mind the readers conclude they don't choose XUL because they need to write not only XUL but also DHTML.

I like XUL, for its programming is simple. It has rich UI, besides, works fast. An XML file is all I need to make UI. I like to write XML, so XUL is fun for me. I think it isn't necessary for XUL to fit into the world all browsers reside. It's all right that XUL is for XUL-lovers' obscure UI. Let's pursuit fun to create own UI by XUL.

Tuesday, February 06, 2007

Does JavaSpaces have a possibility to become major?

I found an article about JavaSpaces in TheServerSide.com a couple of days ago. I remembered this name well. I had worked for it for about a year before JINI was released. Since it was almost ten years ago, I'm interested in today's situation.
In this article, the writer explains about the definition and the feature of JavaSpaces. In addition, he introduces a small example with describing how to get it work. Every part of this article is familiar to the programmer who once got involved to JavaSpaces. However, how does JavaSpaces sound to Java programmers who don't know this technology?
In the same domain, distributed processing, Web Services technology grew to become eminent. Real Web Services applications have been in action these days. Why JavaSpaces couldn't develop like Web Services? I think the concept of JavaSpaces was too innovative to be understood easily and broadly. Strict to say, JavaSpaces isn't the server-client model. It adopts the peer-to-peer communication model. The "space" provides a place to communicate; therefore, the "space" doesn't control or manage any entries. On the other hand, the concept of Web Services follows the traditional server-client model. Newly added idea was less than that of JavaSpaces. Moreover, as an internet based application, Web Services technology well suited to today's network system.
The writer shows we already have enough tools to make JavaSpaces application. It is true, but JavaSpaces might need innovative application that only JavaSpaces can realize. This would be the most difficult and effective answer JavaSpaces leaps.
What changed is that implementations have been released in public and free. What not changed is that decisive application hasn't created yet.