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

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

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

Wicket Examples ■StockQuote Component


WicketのStockQuote Componentサンプルのチュートリアル

カスタムコンポーネント: 株式相場


Custom Component: StockQuote
This example shows how to create a custom Wicket component: a stock quote component. We assume you already are familiar with the basics of a Wicket application. If not, then please take a look at the Hello, World example first.


カスタムコンポーネント StockQuote(株式相場)
このサンプルは、「株式相場コンポーネント」によってWicketのカスタムコンポーネントの作り方を紹介します。すでに、Wicketの基礎的なアプリケーションに慣れた人を対象としています。
もしまだ慣れていなければ、Hello Worldサンプルを先に参照してください。


・Introduction
POJO Solution
・Reuse Component Solution
・New Component Solution
・Discussion


・導入
POJOソリューション
コンポーネント再利用ソリューション
・新しいコンポーネントのソリューション
・議論


Introduction
The Stock Quote component should take a symbol and display the value of the stock obtained through a webservice in its body.
I've used some code from devx.com for calling a stock quote webservice provided by xmethods.com.
In order to keep it simple, I've not included this code here, but you can see it in our CVS.
The webservice calling code is not the prettiest around, but it suffices.
So: <span wicket:id="stockquote">Price of IBM goes here</span>

should replace its body contents with the actual value of IBM stock.
In the next sections we will show you several solutions for solving the Stock Quote problem. First we will provide a POJO based solution, without creating a custom component.
Next we will reuse the existing label component to build the stock quote label,
and finally we will write the component from scratch and show how to let the component play nicely in the Wicket stack of components.

導入
株式相場コンポーネントは、証券コード(symbol)を受け取るでしょう、そして、内容としてWebサービスを介して取得した株価の値を表示します。 
私は「xmethods.com」によって提供されている株式相場のWebサービスを呼び出すために「devx.com」からのいくつかのコードを利用しました。
シンプルさを保つために、そのコードをここには含みませんがCVSで参照することができます。
Webサービスを呼出すコードは、整形の余地はありますが十分です。
さて、

<span wicket:id="stockquote">Price of IBM goes here</span>

というタグは、IBMの実際の株価の内容によって置き換えられます。
次のセクションでは、株式相場問題に対するいくつかのソリューション(解決法)を紹介しましょう。まず、カスタムコンポーネントを使わないPOJOベースのソリューションを紹介します。
次に、株式相場ラベルを作るために、既にできあがっているラベルコンポーネントを再利用します。
そして、最後には、そのコンポーネントを0から書き、Wicketコンポーネント群の中でうまく動かせるようにコンポーネントを配置する方法を教えます。


POJO Solution
Usually you don't need to create a specialized component and can the problem at hand be solved using stuff you already know: normal Java objects.
This part shows the most easy way of using the web service, using a POJO.
The POJO we introduce here, is also used by the other examples below, instead of reinventing the wheel.
The actual code for calling the service is not presented here, but can be found in the Wicket examples project.


POJO ソリューション
普通、特別なコンポーネントを作る必要はありません。そしてその問題は、既にご存知の方法である「普通のJavaオブジェクト」を使うことで、すぐに解決できます。
このパートは、Webサービスを使うための最も簡単な方法である、POJOを使う方法を紹介します。
ここで紹介するPOJOは、下の他の例でも使われています。車輪の再発明はしないことにしましょう。
サービスを呼び出す具体的なコードは、ここでは表しません。しかし、Wicketサンプルプロジェクトにあがっています。

package wicket.examples.stockquote;

public class StockQuote
{
    private static final String serviceUrl = "http://64.124.140.30:9090/soap";
    
    private String symbol;
    
    public StockQuote()
    {
    }
    
    public StockQuote(String symbol)
    {
        this.symbol = symbol;
    }
    
    public void setSymbol(String symbol)
    {
        this.symbol = symbol;
    }
    
    public String getSymbol()
    {
        return symbol;
    }

    public String getQuote()
    {
        // ... do SOAP thingy
    }
}

Now, when we want to show a stock quote on a page, then we have to define a label, and bind it to the quote.

さて、株式相場をページに表示したいならば、ラベルを定義して相場に関連づけなければなりません。

public PojoStockQuotePage()
{
    StockQuote quote = new StockQuote("IBM");
    add(new Label("stockIBM", new PropertyModel(quote, "quote"));
}

And in the markup:

そして、これがマークアップです。

<html>
<body>
<p>
    Stock of IBM: <span wicket:id="stockIBM">some value</span>
</p>
</body>
</html>It is also easy to use this in a form, or listview, or anything you want. 


Reuse Component Solution
In this section we will reuse the existing functionality of the label component.
As the stock quote component will replace the body with the quote, we can utilize the label component.

コンポーネント再利用ソリューション
このセクションでは、すでに存在する機能的なラベルコンポーネントを再利用しましょう。
この株式相場コンポーネントが相場を使って内容を置き換えるときに、ラベルコンポーネントを活用することができます。

public class StockQuoteLabel2 extends Label
{
    public StockQuoteLabel2(String id, final String symbol)
    {
        super(id, new AbstractReadOnlyModel()
        {
            public Object getObject(Component component)
            {
                final StockQuote quote = new StockQuote(symbol);
                return quote.getQuote();
            }
        });
    }
}

In the constructor we provide the label with a specific model, giving the label the quote to display.

コンストラクターの中で、紹介するラベルは相場を表示するための特別なモデル(オブジェクト)をラベルに渡します。 

New Component Solution
In this solution we will create a new component that will render itself, instead of reusing an existing component.
Because our component needs to replace the (read only) body with the stockquote, it is natural to look at the Label component.


新しいコンポーネントソリューション
このソリューションでは、既存のコンポーネントを再利用するかわりに、自分自身で描画を行う新しいコンポーネントを作ります。
なぜなら我々のコンポーネントは内容を株式相場によって置き換える必要があるからです。それは、ラベルコンポーネントを考察するのに適しています。

The idea is to attach to a <span>, <div>, or <p> tag, and replace the enclosed body with the quote. </span>

そのアイデアとは、<span>, <div>タグまたは<p> タグを使い、囲まれた内容を相場で置き換えることです。

Component Class
Since we are just replacing the component body with some text, we don't have a need for our own markup files.
So we don't have to extend Panel. Our component also doesn't have nested markup inside the tags,
so we also don't need to extend WebMarkupContainer. Instead, we'll extend WebComponent.
This is the base class for all HTML markup components. This is also the base class for the label component.


Component Class
いくつかのテキストでコンポーネントの内容を置き換えるだけなので、マークアップファイルは必要ではありません。
ですから、パネルを拡張する必要はありません。我々のコンポーネントは、タグの子要素としてネストされたマークアップも必要としません、
さらに、WebMarkupContainerを拡張する必要もありません。かわりに、WebComponentを拡張します。
これはすべてのHTMLマークアップコンポーネントのベースクラスです。また、ラベルコンポーネントのベースクラスでもあります。

package wicket.examples.stockquote;

import wicket.markup.html.WebComponent;

public class StockQuoteLabel extends WebComponent
{
}

Construction
First lets take a look at the model of the component. The component will receive through some means the symbol to look for.
This will be bound to the components model. So the first, for the user simple StockQuoteLabel constructor just takes a string for the symbol:


Construction(構築)
まず、モデルコンポーネントを見ていきましょう。コンポーネント証券コード(symbol)を探すために、いくつかの方法で受信を行うでしょう。
これは、コンポーネントモデルに結びつけられます。そして、初めにユーザーに簡単に利用してもらうために、株式相場ラベルコンストラクター証券コードのための文字列だけをとります。

public StockQuoteLabel(String id, String symbol)
{
    super(id, new Model(symbol));
}


Wicket uses models in order to be flexible with respect to where the data comes from. Using the string parameter, directly binds the component to the symbol at construction time.
This doesn't allow people to bind using the OGNL expression language easily. Sometimes the data isn't available (yet) at construction time,
so we should provide a constructor taking an IModel as well, in order to make the component fit nicely into the Wicket framework:


Wicketは、データの出所に関して柔軟性をもつために、モデルを使います。
文字列のパラメータを使うことで、初期化時にコンポーネント証券コードを直接ひも付けます。
利用者が、簡単にOGNL式言語を使うことでバインドすることをゆるしません。コンストラクション時にでさえ、時々データが届かないことがあります。
そこでコンストラクターにIModelを提供するべきです。おまけに、コンポーネントを作るという目的はWicketフレームワークによく合います
したがって、また、うまくWicketフレームワークコンポーネントが合うように作りかえるために、IModelを取るコンストラクターを提供するべきです。

public StockQuoteLabel(String id, IModel model)
{
    super(id, model);
}


Rendering
When the component is rendered, we have to replace the body contents of the span tag with the stock quote value for the given symbol. So here is the code for doing just that:


描画
コンポーネントが描画されるとき、シンボルによって与えられた株式相場の値でSpanタグの内容が置き換えられなくてはなりません。以下は、それをやるためのコードのみを記載さます。

protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
{
    String symbol = getModelObjectAsString();
    StockQuote quote = new StockQuote(symbol);
    replaceComponentTagBody(markupStream, openTag, quote.getQuote());
}

Ready
The StockQuoteLabel is now ready for usage:


準備
これで株式相場ラベルを使うための準備ができました。

public StockQuotePage()
{
    add(new StockQuoteLabel("stockIBM", "IBM"));

    // create a form for entering a symbol
    final IModel model = new PropertyModel(quote, "symbol");
    final Form form = new Form("form");
    add(form);
    form.add(new TextField("symbol", model));
    
    // display the entered symbol and retrieved quote
    add(new Label("symbol", model));
    add(new StockQuoteLabel("quote", model));
}

The corresponding markup:
対応するマークアップです。

<p>
    IBM stockquote: <span wicket:id="stockIBM">1.23</span>
</p>
<form wicket:id="form">
    Type symbol: <input wicket:id="symbol" type="text" />
    <input type="submit" />
</form>
<p>
    Stock quote of <span wicket:id="symbol">symbol</span> is <span wicket:id="quote">quote</span>.
</p>



Discussion
When looking at the current component code, there is little that speaks for it, when compared to the POJO solution. And for these kind of components, it is probably best to use vanilla POJOs instead of creating a full blown component.


議論
現在のコンポーネントコードをみると、POJOソリューションと比べたところを話そうと思っても、少ししかありません。
また、これらのコンポーネントの種類のために、おそらく全てのブラウンなコンポーネントを作る代わりに、バニラのPOJOを使うことがベストです。

However, this wasn't a matter of just looking what the best scenario is for the stock quote, but how you can create components yourself.
The last option we provided is the most flexible one, but also needs more code.


しかしながら、これは株式相場のためのベストシナリオが確認できるだけのものではありません。どうやってコンポーネントを作れるかということもまた、確認できます。
ご紹介する最後の選択肢は、もっとも自由度の高いものです。しかし、よりたくさんのコードも必要です。