レベルエンター山本大のブログ

面白いプログラミング教育を若い人たちに

BLOCKVROCKリファレンス目次はこちら

Wicket+Guice

TSSで久々にWicketの記事が出てたので翻訳でもしようかとおもったら、
後輩のid:jyukutyoがすでに訳してくれてたので、
Wicketサンプルから面白そうなサンプルを使ってみることにした。

Wicketのサンプルページ
http://wicketstuff.org/wicket13/index.html
WicketGuiceのサンプル
http://wicketstuff.org/wicket13/guice/

ここでのソースコードはこんな感じ。


GuiceApplication.java

package org.apache.wicket.examples.guice;

import org.apache.wicket.examples.WicketExampleApplication;
import org.apache.wicket.guice.GuiceComponentInjector;

public class GuiceApplication extends WicketExampleApplication
{
    @Override
    protected void init()
    {
        addComponentInstantiationListener(new GuiceComponentInjector(this));
    }

    public Class getHomePage()
    {
        return HomePage.class;
    }
}

GuiceApplication.javaGuiceアプリケーションの起動クラスです。
Applicationクラスについての詳しいことは、以前の日記で翻訳してるのでそちらを参照!
http://d.hatena.ne.jp/iad_otomamay/20070320/p5


Guice連携には、GuiceComponentInjectorをinit()メソッドで呼び出すだけです。
とても簡単ですね。


HomePage.html

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Wicket Examples - guice</title>
    <link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
    <span wicket:id="mainNavigation"/>
    <p>
    This page uses <a href="http://code.google.com/p/google-guice/">Google Guice</a>.
    There is a service interface called <code>IMyService</code>, with an implementation POJO called <code>MyService</code>.
    Guice is used to wire the implementation into the <code>Page</code> using an <code>@Inject</code> annotation. You can use this
    annotation on the fields of any <code>Component</code> subclass.    
    </p>
    <p>
    The value of the <code>Label</code> component below will be updated with the return value from one of the service's methods when you click the link.
    </p>
    <hr />
    <blockquote>
    Value: <b wicket:id="message" id="message">Message goes here</b>
    <br />
    To update the label above, <a href="#" wicket:id="link">click here</a>.
    </blockquote>
    <hr />
    <p>
    The wicket-guice project will take care of proxying the injected beans so that your pages can be serialized safely.
    To configure your application for Guice injection, see the javadoc for <code>GuiceComponentInjector</code>.
    </p>
</body>

WicketのHTMLで大事なのは、「wicket:id」という属性がつけられた要素です。
このページでは、以下の3つが対象です。
これらの要素がWicketによって動的に置き換えられます。

<span wicket:id="mainNavigation"/>

<b wicket:id="message" id="message">Message goes here</b>

<a href="#" wicket:id="link">click here</a>

<span wicket:id="mainNavigation"/>


以下はそれらを置き換えるJavaコードです。
HomePage.htmlとHomePage.javaを同じパッケージに含めるようにします。

HomePage.java

package org.apache.wicket.examples.guice;

import org.apache.wicket.examples.WicketExamplePage;
import org.apache.wicket.examples.guice.service.IMyService;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.model.AbstractReadOnlyModel;

import com.google.inject.Inject;

/**
 * Everybody's favorite example (Hello World), modified to use Guice.
 * 
 * @author Alastair Maw
 */
public class HomePage extends WicketExamplePage
{
    @Inject
    private IMyService service;

    private String labelValue = "<not yet initialized>";

    /**
     * Constructor
     */
    public HomePage()
    {
        add(new Link("link")
        {
            /**
             * @see org.apache.wicket.markup.html.link.Link#onClick()
             */
            @Override
            public void onClick()
            {
                labelValue = service.getHelloWorldText();
            }
        });
        add(new Label("message", new AbstractReadOnlyModel()
        {

            @Override
            public Object getObject()
            {
                return labelValue;
            }

        }));
    }
}

serviceインターフェイスにオブジェクトはセットされていませんが、
インスタンス化されたときに、Guiceによってインジェクトされ、
ラベル表示が可能です。

WicketはSwingの作成者達が参画して作ったフレームワークなので、
Swingライクなコンポーネントモデルが採用されています。
オブジェクト指向のメリットが十分に活かせると思います。


最後、そのサービスオブジェクト。
service/IMyService.javaとservice/MyService.javaは、
Guiceが利用するサービスオブジェクトとサービスインターフェイスです。
Pojoなのであんまり説明するところはないですね。

service/IMyService.java

package org.apache.wicket.examples.guice.service;

import com.google.inject.ImplementedBy;

/**
 * Service interface for a simple "Hello World" app.
 * 
 * @author Alastair Maw
 */
@ImplementedBy(MyService.class)
public interface IMyService
{
    /**
     * Retrieves the text to say "Hello World".
     * 
     * @return "Hello World"
     */
    public String getHelloWorldText();
}

service/MyService.java

package org.apache.wicket.examples.guice.service;

import com.google.inject.Singleton;

/**
 * Implementation of IService.
 * 
 * @author Alastair Maw
 */
@Singleton
public class MyService implements IMyService
{

    /**
     * @see org.apache.wicket.examples.guice.service.IMyService#getHelloWorldText()
     */
    public String getHelloWorldText()
    {
        return "Hello World";
    }

}

今度、GuiceComponentInjectorのソースを読んで見たいと思います。