Apache Pivot を使用して iTunes 検索クライアントを作成する

WTKX と Java 技術を用いてリッチ・インターネット・アプリケーションを構築する

Apache Pivot は、Java 環境でリッチ・インターネット・アプリケーション (RIA) を構築するためのオープンソースのプラットフォームです。このプラットフォームには、最近の RIA ツールキットが持つ高い生産性およびユーザビリティーと、業界標準 Java プラットフォームの堅牢性を兼ね備えています。Apache Pivot アプリケーションは XML をベースとしたユーザー・インターフェース設計用の言語である WTKX を利用するため、アプリケーションの出力を簡単に視覚化することができます。このチュートリアルでは、ユーザーが iTunes Storeのコンテンツを検索できるようにする、単純ながらも実用的な Pivot アプリケーションを実装する方法を手順に沿って説明します。

Greg Brown, Senior Software Engineer, VMWare

Greg Brown は、VMware の技術スタッフのシニア・メンバーです。10 年以上、リッチ・クライアントを実現する Java、Flash、Flex、Ajax などの技術に取り組み、その真価を説いてきた彼は、Java ベースのリッチ・クライアント・プラットフォーム、Pivot を設計し、主任開発者を務めています。彼はマサチューセッツ大学アマースト校でコンピューター・システム・エンジニアリングの学士号を取得しました。



2012年 1月 13日

始める前に

このチュートリアルでは、読者が一般的な Web 開発の概念と、Java 技術、XML、JSON、JavaScript、HTTP などの Web 開発技術についてある程度、理解していることを前提とします。チュートリアルを読み終える頃には、これらの Web 開発のスキルを適用して簡単に Pivot アプリケーションを構築できるようになるはずです。

このチュートリアルについて

よく使われる頭文字語

  • Ajax: Asynchronous JavaScript + XML
  • API: Application Programming Interface
  • CSV: Comma-Separated Values
  • GUI: Graphical User Interface
  • HTML: HyperText Markup Language
  • HTTP: HyperText Transfer Protocol
  • JSON: JavaScript Object Notation
  • JVM: Java Virtual Machine
  • REST: Representational State Transfer
  • UI: User Interface
  • URL: Uniform Resource Locator
  • W3C: World Wide Web Consortium
  • XHTML: Extensible HyperText Markup Language
  • XML: Extensible Markup Language

他の RIA 開発プラットフォームと同じように、Apache Pivot にも今風の GUI アプリケーションの構築を大幅に簡易化する、宣言型ユーザー・インターフェース、データ・バインディング、ビジュアル・エフェクトおよびトランジション、そして Web サービス統合などの数々の機能が組み込まれています。Pivot アプリケーションを構築するには、Java 技術と XML ベースのマークアップ言語である WTKX を組み合わせて使用します。また、Java 仮想マシン・スクリプト言語もサポートされているため、Pivot アプリケーションは Java プラグインを使用して Web ブラウザーで実行することも、スタンドアロン (オプションでオフライン) のデスクトップ・アプリケーションとして実行することもできます。

このチュートリアルでは、iTunes Storeのコンテンツをユーザーが検索できるようにする、単純ながらも実用的な Pivot アプリケーションを実装します。チュートリアルではまず始めに Pivot プラットフォームの紹介から入り、iTunes Store Web Service API の概要、そしてデモ・アプリケーションへと話を進めます。その過程で以下の方法を説明します。

  • Pivot の XML ベースの UI マークアップ言語である WTKX でユーザー・インターフェース宣言を作成する方法
  • Pivot に組み込まれた JSON シリアライズのサポートを使用して JSON データを処理する方法
  • JavaScript でユーザー・インターフェースのイベントに対処する方法

前提条件

このチュートリアルで使用するサンプル・コードは、Pivot 1.3 リリースをベースとしています。このリリースには、 Java 6 (またはそれ以上の) SDK が必要です。Pivot 1.3 は、バイナリーまたはソースとしてダウンロードすることができます。ソース・ディストリビューションには、プロジェクトのビルド方法を説明する BUILD ファイルが付属しています。

デモ・アプリケーションのソース・コードは、Pivot プラットフォームと一緒に配布されます。すべてのサンプル・コードは、Apache Software License バージョン 2.0 の下でリリースされています。

サンプル・コード、Pivot 1.3、Java 6 SDK、およびデモ・アプリケーションのダウンロード・リンクについては、「参考文献」を参照してください。


はじめに

このセクションでは、Apache Pivot の概要と Pivot プラットフォームでのアプリケーション開発について説明した後、チュートリアルで作成するサンプル・アプリケーションを紹介します。

Apache Pivot の概要

Web は現在、アプリケーションを配信する手段のデファクト・スタンダードとなっていますが、Web アプリケーションの機能要件はブラウザーの能力を超えるまでになりつつあります。スクリプトのサポートや動的な要素の操作、そして非同期サーバー通信で補完したとしても、HTML でデスクトップ・アプリケーションに匹敵するほどのユーザー・エクスペリエンスを実現するのは困難です。

RIA 開発プラットフォームは、Web アプリケーションのエクスペリエンスと、デスクトップ・アプリケーションのエクスペリエンスとのギャップを埋める手段です。RIA 開発プラットフォームはブラウザー・プラグインを使用して、開発者がネイティブ・デスクトップ・アプリケーションのようなルック・アンド・フィールを持ちながらも、従来の HTML ベースの Web アプリケーションのように Web でデプロイできるアプリケーションを構築できるようにします。RIA にはまた、アニメーションやその他の動的な振る舞いなど、ユーザー・エクスペリエンス全体を強化するビジュアル・エフェクトが組み込まれていることもよくあります。

RIA を構築するために現在よく使われているプラットフォームには、Adobe Flex、Microsoft Silverlight、および Sun JavaFX があります。おおかたの見方で言うと、最もよく使われているプログラミング言語は今でも相変わらず Java ですが、これらのプラットームのうち、開発者が Java で RIA を作成するために使用できるものは 1 つもありません。Flex アプリケーションを作成するには ActionScript を使用し、Silverlight アプリケーションを作成するには .NET を、JavaFX アプリケーションを作成するには JavaFX Script を使用することになっています。その一方、Pivot では Java 開発者が使い慣れた技術と API を使用して、Java プラットフォームをターゲットとした RIA を構築することができます。

Pivot は RIA 開発者にとって、本当の意味でのオープンソースによる代替手段でもあります。程度の差はあれ、Flex、Silverlight、JavaFX もオープンソースであると言えますが、それでも独自仕様のプラットフォームであることには変わりありません。Pivot は 2007年に VMware で研究開発プロジェクトとして始まり、2008年 6月、Apache 2.0 ライセンスの下でオープンソース・プロジェクトとしてリリースされました。2009年 1月に Apache Incubator に加わった Pivot は、現在完全に Apache Software Foundation によって推進されています。

Pivot プラットフォームの概要

Pivot は包括的な基本クラス一式を提供しており、これらのクラスがまとめて 1 つのフレームワークを構成します。Pivot のクラスは以下の主要なカテゴリー別にグループ分けされてパッケージ化され、それぞれに対応するライブラリーという形で配布されます。

  • Core ― 共通の非 UI クラスのセット
  • WTK ― ユーザー・インターフェース開発用のクラス (ウィンドウ、ダイアログ、ボタン、リスト、テキスト入力、レイアウト、ドラッグ・アンド・ドロップ、XML マークアップなど)
  • Web ― リモート・データ・サービスと通信できるようにするクラス
  • Charts ― インタラクティブなチャート作成機能を Pivot アプリケーションに追加するためのクラス
  • Tools ― 開発ツールおよびユーティリティー・アプリケーション

このチュートリアルで取り上げるアプリケーションは、Core、WTK、および Web ライブラリーで提供される機能に焦点を当てます。

デモ・アプリケーション

このチュートリアルで説明するデモ・アプリケーションでは、ユーザーが指定したクエリー基準一式と一致するタイトルを iTunes Store で検索することができます。クエリーは検索語のセットとして指定され、一致する項目が表形式のビューに表示されます。この表に表示されている項目を選択すると、タイトルのサムネール・プレビューが表示されます。項目をダブルクリックするか、または「Preview (プレビュー)」ボタンを押すと、その項目のプレビューを 30 秒間再生することができます。このデモ・アプリケーションを選んだ理由は、WTKX と JavaScript を使用して簡単に UI を作成できること、そして Pivot の組み込みサポートによって JSON ベースの REST サービスと対話できることなど、このデモで Pivot が持つ数多くの長所が明らかになるためです。

図 1 は、サンプル・アプリケーションで Cheap Trick というバンドのタイトルについて検索を実行した後に撮ったスクリーン・キャプチャーです。

図 1. iTunes Store 検索デモ・アプリケーション
iTunes Store 検索デモ・アプリケーションで検索を実行した後のスクリーン・キャプチャー

参考文献」に、デモ・アプリケーションのライブ・サンプルへのリンクが記載されています (Java 6 SDK が必要です)。表の行をクリックすると検索結果のサムネール画像が表示され、「Preview (プレビュー)」ボタンをクリックすると、その項目のプレビューが 30 秒間再生されます。

アプリケーションのユーザー・インターフェースの基本構造を最初に設定するには、次のセクションで取り上げる WTKX を使用します。UI の背後にあるコア・ロジックと振る舞いは、Java を使用して定義します。その他の構成要素を結び付ける役目を果たすのは、軽量のスクリプト言語、JavaScript です。


Pivot における UI マークアップ言語: WTKX

Pivot アプリケーションを組み立てるには、XML ベースのマークアップ言語である WTKX を使用します。WTKX は、アプリケーションのユーザー・インターフェース構造を定義するために、ごく一般的に使用されています。XML 文書の階層構造は Pivot コンポーネント階層の構造にかなり厳密に対応するため、最終的な出力を簡単に視覚化することができます。しかし、あらゆるタイプの Java オブジェクト・ツリーを宣言型で構成するために実際に使用できるのは WTKX です。このセクションでは WTKX について簡単に紹介し、サンプル・アプリケーションで WTKX を適用する場合に重要となるいくつかの側面に焦点を当てて説明します。

WTKX の紹介

XML をベースとしたあらゆる UI マークアップ言語の例に漏れず、WTKX は要素属性という基本的な XML の概念を用いています。Pivot がこれらの構成体を Java のクラスとプロパティーのインスタンスにどのように対応付けるかを見てみましょう。

要素

WTKX では、XML 要素はクラス・インスタンスまたはクラス・インスタンスのプロパティーのいずれかを表します。タグ名が大文字で始まる要素はクラス・インスタンスを表し、小文字で始まる要素はクラス・インスタンスのプロパティーを表します。WTKX シリアライザー (WTKX ファイルをロードするクラス) は、タグ名が大文字で始まる要素を検出すると、このタグが Java クラスの名前であると見なし、そのクラスのインスタンスを作成します。要素の名前空間には、そのクラスが属するパッケージの名前が含まれているものと見なされます。小文字で始まるネストされた要素の中身は、そのクラスに適用されるプロパティー値であると見なされます。プロパティー要素の名前は、そのクラス・インスタンスで公開される JavaBean プロパティーの名前と見なされます。

属性

属性値も同じく JavaBean プロパティーと見なされます。属性値は、セッター・メソッドの引数として渡されます。プロパティーの型がストリングであれば、属性値はそのままの形で渡されますが、その型がプリミティブ型のいずれか (boolean、char、byte、short、int、long、float、または double) である場合、あるいはプリミティブ型のラッパーに相当するものである場合は、セッターが呼び出される前に、属性値が適切な型に変換されます。

一例として、リスト 1 に記載する単純な JavaBean クラスを見てください。

リスト 1. 単純な JavaBean クラス
view sourceprint?
package com.foo;
 
public class MyBean {
    private String foo = null;
    private int bar = 0;
     
    public String getFoo() {
        return foo;
    }
     
    public void setFoo(String foo) {
        this.foo = foo;
    }
     
    public int getBar() {
        return bar;
    }
     
    public void setBar(int bar) {
        this.bar = bar;
    }
}

このコードに対する WTKX コードは、Bean をインスタンス化して foo および bar のセッターを呼び出し、setFoo() には String 値を渡し、setBar() には int 値を渡します。つまり、<MyBean xmlns="com.foo" foo="hello" bar="123"/> のようになります。

リスト 2 も、リスト 1 に対する上記 WTKX コードと同様の結果を生成します。

リスト 2. 同様の結果を生成する WTKX コード
<MyBean xmlns="com.foo" bar="123">
    <foo>hello</foo>
</MyBean>

bar プロパティーが属性として指定されたままであることに注意してください。その理由は、上記で説明したプリミティブ型の変換プロセスは、属性には適用される一方、要素の値には適用されないためです。ただし、要素のプロパティーにはその中身としてストリングの他にも、複合型 (例えば、他の JavaBean インスタンス) を含めることができます。一方、属性に複合型を含めることはできません。

クラスのインスタンス化の他にも、WTKX にはインクルード、スクリプト、リソース注入など、ユーザー・インターフェースの作成に役立つ多数の機能が用意されています。これらの機能のいくつかについて、次のセクションで詳しく説明します。

サンプル・アプリケーション

リスト 3 に、サンプル・アプリケーションのユーザー・インターフェースを作成するための WTKX ソースを記載します。ルート要素は <Window> で、デフォルトの名前空間を使用することから、org.apache.pivot.wtk.Window のインスタンスに相当します。この要素は、Pivot が提供する最も基本的なウィンドウのタイプであり、タイトル・バーやサイズ変更ハンドルなどの飾りは一切ありません。単にディスプレイ (Pivot アプリケーションでの最上位レベルの UI 構成体) へのエントリー・ポイントとして機能するだけです。

リスト 3. アプリケーションのユーザー・インターフェースを作成するための WTKX ソース
<Window title="Search Demo" maximized="true"
    xmlns:wtkx="http://pivot.apache.org/wtkx"
    xmlns:content="org.apache.pivot.wtk.content"
    xmlns="org.apache.pivot.wtk">
    <content>
    ...
    </content>
</Window>

ウィンドウの maximized プロパティーが true に設定されていることに注意してください。この設定により、ウィンドウはアプリケーションのコンテキストでのクライアント領域全体を占めることになります。つまり、ブラウザーで実行する際には、アプリケーションが実行されるアプレットのクライアント領域、一方デスクトップでは、アプリケーションのフレーム内のクライアント領域ということになります。

<Window> が持つ唯一の直接の子要素は、<content> 要素です。この要素の中身が、ウィンドウの content プロパティーとして設定されます。ウィンドウのコンテンツとは、ウィンドウ自体の使用可能なクライアント領域に収まるようにサイズ設定されたコンポーネントのことです。この例の場合、ウィンドウのコンテンツは TablePane に設定されます。大まかに言うと、TablePane は HTML の表に相当する Pivot のコンテナーであり、子コンポーネントを行と列からなるグリッドに配置します (オプションでセルに跨って配置することもできます)。表の構造は、XML で指定された <rows> および <columns> のコレクションによって定義されます (リスト 4 を参照)。

リスト 4. TablePane コンテナーの定義
<TablePane styles="{padding:6, verticalSpacing:6}">
    <columns>
        <TablePane.Column width="1*"/>
    </columns>
    <rows>
    ...
    </rows>
</TablePane>

TablePane 要素の styles 属性に注目してください。コンポーネントの外観をカスタマイズするために使用される styles 属性は、WTKX では JSON フォーマットの名前/値ペアのコレクションとして指定されます。すべての WTK コンポーネントは styles 属性をサポートしますが、各コンポーネントがその現行のスキンに応じてそれぞれに異なるスタイルのセットをサポートすることができます (スキンは、Pivot がプラガブルなルック・アンド・フィールをサポートする手段です)。上記の例では、表ペインにそれぞれ値 6 (ピクセル) の padding (パディング) および verticalSpacing (垂直スペーシング) が割り当てられます。パディングは、表ペインが周囲のコンポーネントとの間に設けるスペースの量を表し、垂直スペーシングは、表ペインの行間に設ける間隔の大きさを表します。

この WTKX ファイルの残りの部分は、アプリケーションのユーザー・インターフェースの構造を設定するとともに、「イベント処理: JavaScript」で詳しく説明する JavaScript のイベント・ハンドラーも定義します。なかでも、特に注目すべき点は、検索結果を表示するために使用される TableView コンポーネントの定義です (リスト 5 を参照)。

リスト 5. TableView コンポーネントの定義
<TableView wtkx:id="resultsTableView">
    <columns>
        <TableView.Column name="itemName" width="1*" headerData="Name"/>
        <TableView.Column name="itemParentName" width="1*" headerData="Album"/>
        <TableView.Column name="artistName" width="1*" headerData="Artist"/>
    </columns>
    ...
</TableView>

この表のビューが定義する一連の列の名前は、検索によって返される JSON データの項目プロパティーに直接対応します。Pivot の TableView コンポーネントは、JSON データをそのまま表示できるので、データ変換を追加する必要はありません (CSV データもサポートされます)。この点が、JSON や CSV という一般的なデータ・フォーマットを使用できる REST クライアントを構築するには Pivot が理想的なプラットフォームとなる理由です。次のセクションでは、Pivot がどのように機能するかを見て行きます。


クエリーの処理: Java + JSON 技術

Pivot アプリケーションのユーザー・インターフェースは多くの場合、WTKX を使用して定義されますが、アプリケーションの振る舞いに関しては、Java コードで定義されるのが通常です。アプリケーション・ロジックもスクリプトで記述できるため、開発者は Pivot アプリケーションの一部、あるいはアプリケーション全体を、Groovy や Scal などの定評のある JVM 言語を使って構築することができます。私は JavaScript を使用してサンプル・アプリケーションのイベント・ハンドラーを定義しました。

JSON (JavaScript Object Notation) は、特定のプラットフォームに依存しないデータ交換フォーマットです。JSON は構造化データを表現するために使用される点では XML と同様ですが、Java や JavaScript を始めとする、よく使われているプログラミング言語の多くで使用されるデータ構造には、JSON のほうが XML よりも相性が良い場合はよくあります。さらに、終了タグが必要ないことから、XML と比べると多少簡潔になります。JSON が最もよく使用されているのは Ajax 開発においてですが、JSON をサポートするあらゆる言語またはプラットフォームで使用することができます。Pivot はネイティブに JSON をサポートし、Pivot プラットフォーム全体でリソースの定義やスタイル宣言、そしてデータ交換のために JSON を広範に使用します。

ここからは、Java コードが Pivot アプリケーションのユーザー・インターフェースを WTKX からロードする方法、そして JSON データに対する Pivot の堅牢なサポートを利用すれば、元々は Ajax アプリケーションのために作成されたサービスでも簡単に利用できる仕組みを、iTunes Store Web Service API を例に説明します。アプリケーションの完全なソース・コードは、「参考文献」から入手することができます。

ユーザー・インターフェースのロード: Java コード

SearchDemo クラスが実装する org.apache.pivot.wtk.Application インターフェースは、あらゆる Pivot アプリケーションへのメイン・エントリー・ポイントの役割を果たします。このインターフェースは、従来のアプレット開発で使われているライフサイクル・メソッドに似た、以下の 4 つのメソッドを定義します。

  • startup(): アプリケーションの起動時に呼び出されます。
  • shutdown(): 実行中のアプリケーションがシャットダウンされる時点で呼び出されます。
  • suspend(): アプリケーションが一時的に非アクティブになると呼び出されます。
  • resume(): 一時停止されていたアプリケーションが再開されると呼び出されます。

以下に、サンプル・アプリケーションでの startup() および shutdown() の実装について説明します。suspend()resume() は、この例では使用しません。

startup() メソッド

リスト 6 に、このアプリケーションでの startup() メソッドの定義を記載します。

リスト 6. サンプル・アプリケーションの startup() メソッド
public void startup(Display display, Map<String, String> properties) 
throws Exception {
    WTKXSerializer wtkxSerializer = new WTKXSerializer();
    wtkxSerializer.put(APPLICATION_KEY, this);

    window = (Window)wtkxSerializer.readObject(this, "search_demo.wtkx");
    wtkxSerializer.bind(this, SearchDemo.class);

    ...    
    window.open(display);

    termTextInput.requestFocus();
}

このメソッドは、WTKX ファイルから UI をロードするために使用する org.apache.pivot.wtkx.WTKXSerializer のインスタンスを作成し、自身への参照をシリアライザー・スコープに追加します。これは、ファイルに定義されたスクリプト・コードがアプリケーションをコールバックして、executeQuery() メソッド (「executeQuery() メソッド」で説明) によってクエリーを実行できるようにするためです。次に、シリアライザーの readObject() メソッドを呼び出します。すると、このメソッドが WTKX ソースを構文解析し、ルート WTKX 要素に対応するクラス・インスタンスを返します。

続いて startup() は、シリアライザーの bind() メソッドを呼び出します。このメソッドは、WTKX ファイル内の名前付きオブジェクト参照をアプリケーションのメンバー変数にマッピングします。これらのオブジェクトは、ソース・ファイル内では wtkx:id 属性によって識別され、Java ソース内での対応するメンバー変数には、@WTKX アノテーションでタグが付けられています (リスト 7 を参照)。

リスト 7. @WKTX アノテーションによるメンバー変数のタグ付け
@WTKX private TextInput termTextInput;
@WTKX private PushButton searchButton;
@WTKX private Label statusLabel;
@WTKX private TableView resultsTableView;
...

@WTKX アノテーションは、開発者にとっての便宜上の手段に過ぎません。同じオブジェクト参照は、シリアライザーの get() メソッドでも取得することができます。したがって、例えば startup() メソッドに、次のようなステートメントをいくつか含めるという方法もあります。
termTextInput = (TextInput)wtkxSerializer.get("termTextInput");.

startup() は最後にウィンドウを開き、ユーザー入力のフォーカスが検索語のテキスト入力に設定されるように要求します。

shutdown()

リスト 8shutdown() メソッドを定義します。

リスト 8. サンプル・アプリケーションの shutdown() メソッド
public boolean shutdown(boolean optional) {
    if (window != null) {
        window.close();
    }

    return false;
}

このメソッドは、startup() で開かれたメイン・アプリケーション・ウィンドウを閉じて、シャットダウンを続行するように指示する false を返すだけです (つまり、シャットダウンをキャンセルしないように指示します。メソッドが true を返す場合には、シャットダウンがキャンセルされます)。

次に、これらのメソッドが既存のサービスでどのように機能するかを見ていきます。既存のサービスとは、JSON ベースの iTunes Store Web Service API です。

検索クエリーの実行: JSON と iTunes Store Web Service API

iTunes Store は、Apple が iTunes メディア管理ソフトウェアのユーザーに提供しているオンライン・メディア・カタログです。iTunes Store では、ユーザーが音楽や映画の他、デジタル・コンテンツをブラウズして購入することができます。

Apple は、iTunes Store に対して単純な検索クエリーを実行できるように、JSON ベースの HTTP API を提供しています。例えば、以下の URL のコンテンツを検索すると、バンド Cheap Trick の一連の検索結果が返されます。

http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/itmsSearch?
limit=100&term=cheap+trick&output=json&media=all&country=us

(注: 上記の URL はチュートリアルのフォーマットの都合上、2 行に分かれていますが、実際には一続きのストリングです。)

このクエリーの実行結果は、リスト 9 のようになります (簡潔にするために、結果の多くを省略しています)。

リスト 9. クエリーの実行結果
{ "resultCount": 100,
  "results": [
    { "wrapperType": "track", 
      "mediaType": "song", 
      "artistName": "Cheap Trick", 
      "itemParentName": "Heaven Tonight (Remastered)", 
      "itemParentCensoredName": "Heaven Tonight (Remastered)", 
      "itemCensoredName": "Surrender", 
      "itemName": "Surrender", 
      "artistLinkUrl": "http://itunes.apple.com/WebObjects/MZStore.woa
/wa/viewArtist?id=461577&uo=4", 
      "artworkUrl60": "http://a1.phobos.apple.com/us/r1000/015/Music/47/5b
/a4/mzi.epawifmt.60x60-50.jpg", 
      "artworkUrl100": "http://a1.phobos.apple.com/us/r1000/015/Music/47/5b
/a4/mzi.epawifmt.100x100-75.jpg", 
      "country": "USA", 
      "currency": "USD", 
      "discCount": 1, 
      "discNumber": 1, 
      "itemExplicitness": "notExplicit", 
      "itemLinkUrl": "http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewAlbum?i
=203267147&id=203267125&s=143441&uo=4", 
      "itemPrice": "0.99000", 
      "itemParentExplicitness": "notExplicit", 
      "itemParentLinkUrl": "http://itunes.apple.com/WebObjects/MZStore.woa/wa
/viewAlbum?i=203267147&id=203267125&s=143441&uo=4", 
      "itemParentPrice": "9.99000", 
      "previewUrl": "http://a1060.phobos.apple.com/us/r1000/000/Music/4c/4c
/ab/mzi.zquuboiu.aac.p.m4p", 
      "primaryGenreName": "Rock", 
      "trackCount": 13, 
      "trackNumber": 1, 
      "trackTime": 253733},  
    ...
  ]
}

すべての iTunes クエリーの URL は、以下の基本 URL で始まります。

http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/itmsSearch

クエリーをカスタマイズするには、以下のようにクエリー・ストリングの引数を使用します。

  • limit=10: 結果を 10 件に制限します。
  • term=cheap+trick: 文字列「cheap trick」との一致を検索します。
  • output=json: JSON フォーマットの出力を要求します (デフォルトのレスポンスは、HTML ページです。HTML ページは主に、iTunes Store のコンテンツへのリンクを組み立てるために使用されます)。
  • media=all: すべてのメディア・タイプでの一致を要求します (「all」の他に指定できる値には、「music」、「movie」、「podcast」があります)。
  • country=us: iTunes Store 米国版のページからの結果を要求します。

サンプル・アプリケーションでは、この API を使用して iTunes Store のコンテンツに関する情報を取得し、ユーザーに結果を表示します (完全な API へのリンクについては、「参考文献」を参照してください)。

(多少冗長な) レスポンスのコンテンツをブラウズするのに便利な (Pivot で作成された) ユーティリティーについては、「参考文献」に記載されているリンクを参照してください。このユーティリティーには Java 6 SDK が必要です。

クエリーの実行結果として返された JSON データをこのアプレットに貼り付けると、データがツリー・ビューで表示されるため、遥かにナビゲートしやすくなります。

executeQuery() メソッド

メイン・アプリケーションでは、executeQuery() というメソッドを追加で定義しています。このメソッドは、WTKX 自体のなかに定義されたイベント・ハンドラーによって呼び出され、実際の検索を行います。具体的には、HTTP リクエストを実行し、取得した JSON 結果を処理します。このメソッドが取る引数は、検索ストリングが含まれる 1 つのストリング引数だけです。

作業の大部分は、org.apache.pivot.wtk.GetQuery のインスタンスによって処理されます。このクラスは、Pivot で「Web クエリー」と呼ばれるタイプを表します。Web クエリーは、リモート・データ・サービスと通信するための Pivot 固有の手段です。主に、JSON ベースの REST サービスとの対話を容易にするように設計されていますが、任意のデータ・フォーマットを使用したあらゆるタイプの HTTP ベースのサービスとの通信にも十分対応できる汎用性も備えています。Pivot には、POSTPUTDELETE などの他の HTTP 操作を対象としたクエリー・クラスもあります。

executeQuery() は、リスト 10 に記載するクエリー・リクエストをセットアップします。

リスト 10. executeQuery() メソッド
getQuery = new GetQuery(QUERY_HOSTNAME, BASE_QUERY_PATH);
getQuery.getParameters().put("term", term);
getQuery.getParameters().put("country", country);
getQuery.getParameters().put("media", MEDIA);
getQuery.getParameters().put("limit", Integer.toString(LIMIT));
getQuery.getParameters().put("output", "json");

このメソッドは次に、検索を実行中であることを示すように UI 状態を更新し、クエリーを実行します (リスト 11 を参照)。

リスト 11. UI 状態の更新
getQuery.execute(new TaskAdapter(new TaskListener() {
    ...
});

クエリーを実行すると、コンストラクターの引数で指定されたサーバーに対して HTTP GET リクエストが行われ、その結果返された JSON データがデシリアライズされます。

Web クエリーはある種のタスクであり、Pivot では org.apache.pivot.util.concurrent.Task (GetQuery のスーパークラス) のインスタンスとして表現されます。タスクを使用する目的は、バックグラウンド処理の実行を単純化することです。バックグラウンド・スレッドでタスク・リクエストをキューに入れて処理するには、ディスパッチャーが使用されます。タスクは Ajax プログラミングで使用される XMLHTTPRequest オブジェクトと同じように動作しますが、その用途はサーバー・リクエストに限定されません。Pivot タスクは、あらゆるタイプのバックグラウンド処理を実装するために使用することができます。

execute() メソッドには、org.apache.pivot.util.concurrent.TaskListener のインスタンスが渡されます。このインターフェースが定義するメソッドは、タスクの実行が終わると呼び出されます (リスト 12 を参照)。

リスト 12. TaskListener インターフェースが定義する、タスクの実行が終わると呼び出されるメソッド
public interface TaskListener<V> {
    public void taskExecuted(Task<V> task);
    public void executeFailed(Task<V> task);
}

上記の最初のメソッドはタスクが正常に完了すると呼び出され、2 番目のメソッドはタスクが正常に完了しなかった場合に呼び出されます。

実際のリスナー実装は、org.apache.pivot.wtk.TaskAdapter のインスタンス内にラップされることに注意してください。Pivot のタスクは UI 駆動型アプリケーションだけで使われるわけではないため、タスク・リスナーのメソッドは、タスクが実行されたスレッドで呼び出されます。ただし、ほとんどのユーザー・インターフェース・ツールキットと同じように、Pivot でユーザー・インターフェースと対話できるのは単一のスレッドに限られます (このスレッドは、イベント・ディスパッチ・スレッド (Event Dispatch Thread: EDT) と呼ばれます)。TaskAdapter は、タスクのコールバックが実際のバックグラウンド・スレッドで行われず、EDT で行われることを確実にします。

クエリーの実行が正常に完了すると、クエリーから結果データが返されます。返される JSON データは、2 つの値が含まれるオブジェクトです。2 つの値のうち、resultsCount は返される結果の件数を示し、results は実際の検索結果が含まれる配列となります。Pivot では、JSON オブジェクトは org.apache.pivot.collections.HashMap のインスタンスに変換され、JSON 配列は org.apache.pivot.collections.ArrayList のインスタンスに変換されます。結果データが含まれるリストは、ルートの結果オブジェクトから抽出されます (リスト 13 を参照)。

リスト 13. 結果データが含まれるリスト
Map result = (Map)task.getResult();
List results = (List)result.get("results");

ここまで説明した内容を適用して保存した後、次のようにして結果を表のビューに設定します (resultsTableView.setTableData(results);)。

結果を表データとしてすぐに適用できるのは、Pivot の TableView コンポーネントは org.apache.pivot.collections.List のインスタンスをデータ・モデルとして使用しており、JSON 結果データが含まれる ArrayList が、このインターフェースの実装であるからです。ListView、TreeView、Spinner を始めとする、Pivot でのデータ駆動型コンポーネントはすべて、Pivot コレクションをデータ・モデルとして使用します。したがって、サーバーから返されたデータを UI に取り込む上で、データを変換したり、UI に適応させたりする必要がないため、JSON ベースの Web サービスによって提供されるデータを使用するには、Pivot は非常に効率的なクライアントとなります。


イベント処理: JavaScript

ここまでで、検索結果のデータがどのように構造化され、その構造化されたデータがデモ・アプリケーションによってどのように処理されるかを説明しましたが、クエリーが実際にどのように開始されるかについては、まだ明らかにしていません。このセクションでは、JavaScript を使用してクエリーを開始する方法を説明します。

クエリーを開始する方法

他のほとんどのユーザー・インターフェース・ツールキットと同じく、Pivot アプリケーション内でのアクションも、通常はイベントに応じて発生します。イベントとは、何かが起こったことを伝える通知です。大抵の場合、イベントを起動するのはマウスのクリックやキー・ストロークなどのユーザー入力ですが、他の非同期プロセス (例えば、「executeQuery() メソッド」で説明したクエリー・タスクの正常な完了など) によって起動することも可能です。

呼び出し側がイベントに関心があることを通知するには、イベント・リスナーを登録します。Pivot ではイベント・リスナーを、該当するイベントを定義するインターフェースの実装として定義します。例えば、以下のインターフェースはボタンの「押下」イベントを定義します (リスト 14 を参照)。

リスト 14. ボタンの押下イベント
public interface ButtonPressListener {
    public void buttonPressed(Button button);
}

Java コードでイベント・リスナーを登録するには、そのリスナーを関連する「リスナー・リスト」に追加します (リスト 15 を参照)。

リスト 15. イベント・リスナーの登録
myButton.getButtonPressListeners().add(new ButtonPressListener() {
    public void buttonPressed(Button button) {
        // Handle event
    }
});

これだけであれば単純ですが、多くのリスナー・インターフェースは複数のメソッドを定義するため、リスナーの登録は厄介になることがあります。Pivot には、ほとんどのリスナー・インターフェースにデフォルトの no-op 実装を提供するアダプター・クラスがありますが、重要なアプリケーションでは、おそらく多数のイベント・リスナーを定義しなければなりません。すべてのリスナーを匿名 (あるいは名前付きだとしても) 内部クラスとして作成すると、アプリケーションの Java ソースが複雑になり、クラスの実際の目的がわかりにくくなってしまいます。幸い Pivot には、それよりも単純な方法を使用してリスナーを定義することができます。それは、WTKX スクリプト・ブロックです。

一例として、リスト 16 に記載する「Preview (プレビュー)」ボタンの WTKX 宣言を見てください。

リスト 16. 「Preview (プレビュー)」ボタンの WTKX 宣言
<PushButton wtkx:id="previewButton" buttonData="Preview" enabled="false">
    <buttonPressListeners>
        <wtkx:script>
        <![CDATA[
        importPackage(org.apache.pivot.wtk);
        function buttonPressed(button) {
            var selectedResult = resultsTableView.getSelectedRow();
            ApplicationContext.open(selectedResult.get("previewUrl"));
        }
        ]]>
        </wtkx:script>
    </buttonPressListeners>
</PushButton>

このマークアップは org.apache.pivot.wtk.PushButton のインスタンスを作成し、<wtkx:script> 要素の中身をボタン押下リスナーとして登録します。script 要素の中に定義された関数は、このリスナー・インターフェースによって宣言されたメソッドに対応します。この単純な例では明らかではありませんが、追加ハンドラー・メソッドの定義はオプションです。呼び出し側が特定のイベントに関心を持たない場合、そのイベントのハンドラーは単純に省略することができます。したがって、スクリプト内のイベント・リスナーの実装を Java 環境での場合より遥かに簡潔にすることができます。


まとめ

このチュートリアルから、「それぞれのジョブに合わせて適切なツールを使用する」という Pivot の理念を明確に理解できたはずです。以下に、その理念を要約します。

  • 階層型マークアップ言語として、結果の出力を簡単に視覚化できる XML を使用して、ユーザー・インターフェースの構造を宣言する。
  • 堅牢でよく使われているプログラミング言語である Java のコードによって、アプリケーションの主な動作を定義する。
  • よく知られた定番のスクリプト言語である JavaScript によって、Java 環境ではコードを作成するのが面倒になりがちな迅速なイベント処理ロジックを定義する。

このチュートリアルでは Apache Pivot について紹介するとともに、Apache Pivot を使用して、iTunes Store の単純な検索クライアントを作成する方法を説明しました。また、WTKXマークアップ言語についても紹介し、Java とJSON プログラミングを Pivot で使用する方法についての概要と、イベント処理のスクリプト・コードを統合する例についても説明しました。

参考文献

学ぶために

  • Apache Pivot: Pivot および WTKX の詳細を調べるには、このサイトにアクセスしてください。
  • Apache Pivot FAQ: すべての質問の答えが見つかります。
  • Pivot iTunes Search Demo: デモ・アプリケーションを実際に確かめてください。
  • JSON: この軽量のデータ交換フォーマットの全容を学んでください。
  • TIOBE Programming Community Index: 各プログラミング言語の人気度を調べられます。
  • New to XML: IBM developerWorks で開発者向けに用意されているリソースを探すには、ここが絶好の出発点となります。
  • XML ゾーン: 広範な技術に関する記事とヒント、チュートリアル、そして標準については、developerWorks XML ゾーンを参照してください。
  • 無料の developerWorks オンデマンド・デモ: IBM およびオープンソースの技術と製品機能を見て学んでください。
  • 世界各地のオープンソース・イベント: 世界中で近日中に予定されている IBM オープンソース開発者を対象としたカンファレンス、見本市、ウェブキャストなどをチェックしてください。
  • オープンソース: オープンソース技術による開発、および IBM 製品での使用に関する詳細な方法、ツール、およびプロジェクト更新については、developerWorks Open source ゾーンにアクセスしてください。
  • developerWorks Java technology ゾーン: Java プログラミングのあらゆる側面を網羅した記事を探してください。
  • IBM XML 認定: XML や関連技術の IBM 認定技術者になる方法について調べてください。
  • XML 技術文書一覧: 広範な技術に関する記事とヒント、チュートリアル、標準、そして IBM Redbooks については、developerWorks XML ゾーンを参照してください。
  • developerWorks の Technical events and webcasts: 近日中に予定されているセッションで最新情報を入手してください。
  • developerWorks podcasts: ソフトウェア開発者向けの興味深いインタビューとディスカッションを聞いてください。

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, Open source, Web development
ArticleID=784173
ArticleTitle=Apache Pivot を使用して iTunes 検索クライアントを作成する
publish-date=01132012