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.