GWT は、機能豊富な Ajax ブラウザーのクライアント・インターフェースのビルドを、従来の Java GUI インターフェースのビルドでさえ及ばないほど簡単にします。そんな優れた GWT ですが、単独では Web アプリケーション全体を作成することはできません。サーバー上のデータ・ストアと、そのデータを Java オブジェクトに変換して GWT がサーバーからクライアントに渡せるようにするためのフレームワークが必要です。この連載記事では Apache Derby を使用します。この 100% 純粋な Java データベースは、残りのサーバー・サイドのコードと同じ JVM (Java Virtual Machine) に組み込めます。
連載第 1 回目では GWT に焦点を当て、GWT をセットアップして、ユーザー操作に応答する単純なクライアント・インターフェースを作成する方法を説明します。今後の記事では、Derby データベースのセットアップ方法、GWT フロントエンドを Derby ベースのバックエンドに接続する方法を紹介していきます。そして最後に、開発環境以外でシステムをデプロイする方法を学んでください。
GWT では、Java プログラミング言語で Ajax アプリケーションを開発できます。Ajax アプリケーションの特徴は機能豊富な対話環境で、この環境は多くの場合、従来の UI アプリケーションに関連付けられています。図 1 に、デスクトップ E メール・アプリケーションを真似たサンプル GWT インターフェースを示します。このデモは、GWT Web サイトで見ることができます。
図 1. GWT E メールのデモ
GWT で最も独特な特徴は、Ajax アプリケーションを作成しながらも、コードは Java 言語で作成できるという点です。つまり、お好みの Java 統合開発環境 (IDE) を使用することが可能で、しかもクライアントをその Java IDE でデバッグすることもできます。クライアントとサーバー間の通信には Java オブジェクトを使用できるため、クライアントの重要性は Java アプレットの場合より遥かに軽くなります。
要するに GWT はコンパイラーとして、作成された Java コードを JavaScript コードに変換します。このコードが HTML ページに挿入されて、アプリケーションのクライアント・サイドを実行するために使用されます。この機能によって、さまざまなブラウザーで JavaScript コードをサポートするための詳細を気にすることなく、プログラムのインターフェースおよび対話に専念することできます。
GWT が提供するのがコンパイラーとしての機能だけであったとしたら、たいして騒ぎ立てるほどのことではありませんが、GWT の実力はもちろんそれだけではありません。GWT では、コンパイラーはクライアント/サーバー・アプリケーション・アーキテクチャー全体を実現するための単なるメカニズムでしかありません。GWT には以下の特徴もあります。
- 見映えのいい標準 UI ウィジェットのセット。これらの柔軟なウィジェットは、すでに主要なブラウザーすべて (Safari および Opera を含む) で機能するように調整されています。
- クライアント・サイドで完全にイベントをキャッチして応答するためのイベント・メカニズム。
- Web アプリケーションとサーバー間の非同期呼び出しを管理するためのフレームワーク。
- ステートフル・ブラウザー履歴を作成して、Ajax アプリケーションが正常な戻るボタン動作に干渉しないようにするためのメカニズム。
- JUnit でクライアント・アプリケーション用の単体テストを作成できるテスト・フレームワーク。
この連載では、上記のさまざまな特徴を取り上げる予定ですが、まずは GWT をダウンロードしてインストールしなければ始まりません。
この記事を書いている時点は、GWTの最新バージョンは 1.2 です (ダウンロード・サイトへのリンクは、記事の終わりにある「参考文献」に記載しています)。GWT は、Microsoft® Windows® XP、Windows 2000、GTK+ 2.2.1 以降を実行する Linux® システム、そして Mac OS X で完全にサポートされています。
ダウンロードしたファイルは圧縮ファイルです。解凍して、そのディレクトリーを任意の場所に配置してください。配布の詳細はバージョンによって多少異なりますが、基本的な要素は以下のとおりです。
- 3 つの .jar ファイル: gwt-user.jar には、プロジェクトのクラスパスに必要となるユーザー・クラスが含まれています。一方、大量のコンパイラー・コードが含まれているのは gwt-dev-windows.jar または gwt-dev-linux.jar という名前のファイルです。gwt-servlet.jar はデプロイメントで使用します。
- 3 つのコマンド・ライン・ユーティリティー: applicationCreator、junitCreator、および projectCreator です (Windows では、.cmd という接尾部が付きます)。詳細については、この後に説明します。
- サンプル・コードのディレクトリー。
GWT を使用すると、上記の他にもいくつかのファイルが一時ファイルを管理する GWT ホーム・ディレクトリーに配置されます。
すべてがダウンロードされたら、作業の第一段階として、まずプ初めにロジェクトを作成します。これからビルドするのは、オンラインでピザを販売する Slicr という名前の最新 Web 2.0 ビジネスです。GWTプロジェクトのセットアップ方法の詳細は、IDE を使用するかどうかによって変わってきます。ここでは、Eclipse を使用します。Eclipse は無料で、しかも GWT コマンド・ライン・ユーティリティーで直接サポートされるためです。
まず、GWT コマンド・ライン・ユーティリティーを使用して Eclipse プロジェクトを作成します。手順は以下のとおりです。
- ハード・ディスクの任意の場所に、slicr という名前のディレクトリーを新規に作成します。
- 新規 slicr ディレクトリー内でコマンド・プロンプトを開きます。
- 以下のコマンドを入力します (スラッシュなどは、ご使用のオペレーティング・システムに合わせて変更してください)。
<GWT_HOME>/projectCreator -eclipse slicr
上記のコマンドによって、GWT プロジェクトに必要最小限のものが作成されます。つまり、新しい src サブディレクトリーと .project および .classpath ファイルです。
このままの状態でプロジェクトを開始することもできますが、GWT には追加の構造も必要です。これは、以下のコマンドで設定できます。
<GWT_HOME>/applicationCreator -eclipse slicr com.ibm.examples.client.Slicr
引数 -eclipse slicr は Eclipse プロジェクトの名前なので、projectCreator で使用した名前と同じでなければなりません (名前が異なると、Eclipse 内部から GWT アプリケーションを起動できなくなります)。最後の引数は、アプリケーションのメイン・クラスとなるクラスの完全修飾名です。最下層のパッケージを指定クライアントにすることもできますが、独自のものでもかまいません。
上記のコマンドによって、いくつかのファイルが設定されます。そのうちの .java ファイルが、メイン・クラス (および作成する必要があるすべての親ディレクトリー) となります。client ディレクトリーと同じレベルに public ディレクトリーが作成され、このディレクトリーに Slicr.html という名前のファイルが含まれます。その上のディレクトリーには、Slicr.gwt.xml という重要なファイルが含まれます。GWT はいくつかのシェル・スクリプトの他、Eclipse が使用する Slicr.launch ファイルも作成します。
あと一息でプロジェクトは完成です。以下の手順に従って、プロジェクトを Eclipse に組み込んでください。
- Eclipse を開き、File > Import をクリックします。
- 表示されたウィンドウで、General ツリーを展開して Existing Projects into Workspace を選択します。
- Next をクリックし、次に Browse をクリックして Slicr ルート・ディレクトリーを選択します。
- プロジェクトを選択し、Copy projects into workspace オプションが設定されていないことを確認します。このオプションが設定されていると、プロジェクトが移動されません。
上記のプロセスによって、コードが Eclipse に配置されます。ここで、コードをよく調べてください。GWT によって 3 つの重要なファイルが作成されています。まず、com.ibm.examples パッケージ内に含まれる slicr.gwt.xml という名前のファイルです。これが、XML 構成ファイルとなります。今の時点では、ファイルはリスト 1 のようになっています。
リスト 1. slicr.gwt.xml
<module>
<inherits name='com.google.gwt.user.User'/>
<entry-point class='com.ibm.examples.client.Slicr'/>
</module>
|
この XML 文書に、GWT アプリケーションのモジュールを定義できます。モジュールは GWT コードの基本単位で、クライアントが使用する HTML ページによって参照されます。
2 つ目の重要なファイルは、public ディレクトリー内に作成されている Slicr.html ファイルです。これは、Web アプリケーションのフロント・ページとして実際にクライアントに送信される .html ファイルです。デフォルトでは、あまり必要のないコメントが多数含まれています。このファイルの主要な部分をリスト 2 に示します。
リスト 2. Slicr.html
<html>
<head>
<title>Wrapper HTML for Slicr</title>
<meta name='gwt:module'
content='com.ibm.examples.Slicr'>
</head>
<body>
<script language="javascript"
src="gwt.js"></script>
<iframe id="__gwt_historyFrame"
style="width:0;height:0;border:0"></iframe>
<h1>Slicr</h1>
<p>
This is an example of a host page for
the Slicr application.
</p>
<table align=center>
<tr>
<td id="slot1"></td>
<td id="slot2"></td>
</tr>
</table>
</body>
</html>
|
上記で注目すべき最も重要な点は、結局のところ、これは通常の .html ファイルだということです。つまり、あらゆる任意の HTML を組み込むことができます。この .html ファイルには、これが GWT によって使用されるファイルであることを特定する以下の 4 つの要素があります。
- meta タグ: name 属性は上記に示したとおりでなければなりません。content 属性は、モジュールの完全修飾論理名です (XML モジュール・ファイルが含まれるパッケージ名に、拡張子を除いた XML のファイル名が続きます)。このタグは、HTML ページを特定のモジュールに関連付けます。ページを呼び出すと、該当モジュールが開始されます (具体的には、該当モジュールのすべてのエントリー・ポイント・クラスが初期化されます)。
- script タグ: このタグは、gwt.js ファイルをロードします。これは、GWT Java コードを JavaScript コードに変換するときに作成されるファイルのうちの 1 つです。このファイルはすべてのクライアント・コードのロードを制御するため、このタグを組み込むことが、プログラムの実行にかなり重要な意味を持ちます。
- iframe タグ: このタグを正確に (書かれているとおりに) 組み込むと、Web アプリケーションが履歴と状態を記憶できるようになります。つまり、GWT アプリケーションによってユーザーの Back ボタンが使用不可にされることがなくなります。
- td タグ: この特定の .html ファイル内にあるこれらのタグは、JavaScript 識別子を保持します。それ自体は特に変わったことではありませんが、この後説明するように、GWT はこれらの識別子を要素の配置場所として使用します。
GWT は、リスト 3 に示す定型 Java 起動クラスも自動的に作成します。
リスト 3. 定型 Java 起動クラス
public class Slicr implements EntryPoint {
public void onModuleLoad() {
final Button button = new Button("Click me");
final Label label = new Label();
button.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
if (label.getText().equals(""))
label.setText("Hello World!");
else
label.setText("");
}
});
RootPanel.get("slot1").add(button);
RootPanel.get("slot2").add(label);
}
}
|
このクラスについて注意しておきたい点がいくつかあります。この Java クラスはクライアント・パッケージに含まれています。つまり、GWT によって JavaScript コードにコンパイルされることになります。そのため、ファイルに含められる内容は制限されますが、ほとんどは基本的な Java 1.4 コードです。作成されるクラスが、EntryPoint インターフェースを実装します。このインターフェースが定義するメソッドは唯一、onModuleLoad() だけです。このモジュールを参照する HTML ページがロードされると、GWT が自動的にこのメソッドを呼び出します。
上記の EntryPoint は単純なもので、最初の 2 行でボタンとラベルを定義しています。最後の 2 行で、RootPanel.get() メソッドを使ってウィジェットを HTML ページの特定の要素に関連付けています。このメソッドの引数は、HTML ページで定義されている要素の JavaScript ID です。
上下 2 行の間では、Swing でイベントをバインドするときと同じようなイディオムを使って、イベント・リスナーを定義します。上記では、ボタンをクリックすると ClickListener が呼び出されて、ラベル・ウィジェットのテキストが切り替わるだけです。
いよいよ、GWT が作成したサンプル・プログラムを実行してみる段階になりました。GWT プログラムは、Web モードとホスト・モードという 2 つの方法で実行できます。Web モードは完全なデプロイメント・モードなので、GWT プログラムを JavaScript コードにコンパイルした後に使用します。
ホスト・モードは、開発時に使用するエミュレーターで、クライアント・コードとサーバー・コードを一度にシミュレートできるため、開発段階でのデプロイメントが大幅に単純化されます (ホスト・モードは現在、Mac OS X では動作しません)。デバッガーを備えた IDE を使用している場合は、デバッガーでホスト・モードの GWT プログラムを実行できます。こうすることにより、JavaScript コードにコンパイルされるクライアント部分のコードにもブレークポイントと変数のウォッチを設定することが可能になります。もちろんこれは非常に賢く有益な方法なので、GWT で操作するときには、ホスト・モードに多くの時間を費やすことになるはずです。
ホスト・モードは何通りかの方法で呼び出せます。方法の 1 つとして、前の手順で実行した applicationCreator スクリプトによって Slicr-shell スクリプトが作成されていますが、このスクリプトをコマンド・ラインから呼び出すとホスト・モードが開始します。また、記事の前半で GWT プロジェクトを Eclipse にインポートする方法を説明しました。この Eclipse プロジェクトから、Run メニューまたはツールバーの Debug あるいは Run を選択します。これによって表示されるウィンドウで Java Application をクリックすると、Slicr オプションが表示されます。このオプションを有効にしているのは、GWT によって作成され、プロジェクトの残りと一緒に Eclipse にインポートした Slicr.launch ファイルです。この起動ファイルは、Eclipse の classpath と起動クラスを記述しています。このランチャーを一度実行すれば当然、ツールバー・ボタンをクリックする際のデフォルトになります。図 2 に、実際のウィンドウがどのようなものなのかを示します。
図 2. ホスト・モードの呼び出し
ホスト・モードでの実行時には、2 つのウィンドウが表示されます (ホスト・モードの設定が初期化されるまでには、数分かかります。とくに初めて実行する場合には時間がかかることに注意してください)。最初のウィンドウ (図 3) は Google Web Toolkit Development Shell / Port 8888 という名前で、GWT からのエラー・メッセージとログ・メッセージが表示されます。ツールバーを使ってホスト・ブラウザーを開いたり、オンスクリーン・ログの展開、クローズ、そしてクリアの操作ができます。
図 3. ホスト・モードのシェル・ウィンドウ
2 つ目のウィンドウ (図 4) は、シミュレートされたブラウザーです。図を見ると分かるように、このウィンドウには slicr.html ページからの静的 HTML、そして Slicr.java の EntryPoint クラスで作成されたボタン・ウィジェットが表示されます。このボタンをクリックすると、ラベルが切り替わります。セットアップの段階で間違ったことをしたとしても、このウィンドウではわかりませんが、シェルにエラー・メッセージが表示されます。このウィンドウで、すべての名前が正しいことを確認してください (特に、.launch ファイルを調べて正しいプロジェクト・ディレクトリーが指定されていることを確認してください)。
図 4. ホスト・モードでシミュレートされたブラウザー
この記事では、ウィジェットを画面に表示して、多少の対話性を持たせる方法に焦点を当てます。最終的に完成するのは、図 5 に示す画面です。この画面は、飾り気はないにしても十分に機能します。
図 5. Slicr
ページがロードされるときに、これらのウィジェットが作成されるようにするには、EntryPoint クラスの onModuleLoad() メソッドにコードを書き込みます。リスト 4 では、いくつかのインスタンス・データ・メンバーと、ヘルパーを呼び出して各パネルをビルドする最上位レベルのメソッドを定義しています。
リスト 4. モジュール・ロードのイベント・ハンドラー
private DockPanel panel;
private List clearables;
public void onModuleLoad() {
clearables = new ArrayList();
initDockPanel();
panel.add(buildActionPanel(), DockPanel.SOUTH);
panel.add(buildPizzaTypePanel(), DockPanel.WEST);
panel.add(buildToppingPanel(), DockPanel.EAST);
RootPanel.get("slicr").add(panel);
}
|
ウィジェットはすべて DockPanel 内に組み込みます。DockPanel は Swing パネルに相当する GWT で、BorderLayout を使用します。Swing には 1 つの Panel クラスと複数のレイアウト・マネージャーがある一方、GWT には複数の panel サブクラスがあり、そのそれぞれが独自のアルゴリズムで子ウィジェットをレイアウトします。その他のパネル・クラスには、SimplePanel、HTMLTable、FlowPanel、および StackPanel があります。ドック・パネルの作成は難しくありません。リスト 5 に示すように、セッターが必要なことを代わりに行ってくれます。
リスト 5. メイン・パネルの初期化
private void initDockPanel() {
panel = new DockPanel();
panel.setBorderWidth(1);
panel.setSpacing(5);
}
|
まず SOUTH (ボタン) パネルを定義します。コーナー・スペースを要求する段階になると、DockPanel が最初に処理されるためです。南側ウィジェットはこのように、パネル全体で実行されます。アクション・パネルは HorizontalPanel として組み立てます。リスト 6 に示すように、これは Swing ボックスにほぼ相当します。
リスト 6. SOUTH (ボタン) パネル
public HorizontalPanel buildActionPanel() {
HorizontalPanel actions = new HorizontalPanel();
actions.setSpacing(10);
Button clear = new Button("Clear");
clear.addClickListener(new ClearClickListener());
Button newPizza = new Button("Another Pizza");
Button submitOrder = new Button("Submit");
actions.add(clear);
actions.add(newPizza);
actions.add(submitOrder);
return actions;
}
|
上記では、GWT の Button ウィジェットを使って 3 つのボタンを作成し、パネルに追加しています。さらに、後で定義する Clear ボタン用の ClickListener も作成しています。GWT がイベント・リスナーを分割する方法は Swing とは異なります。つまり、ClickListener がリッスンするのはマウスのクリックだけです (このリスナーはインラインの匿名クラスとして定義されることがよくありますが、そのようなスタイルは読みにくく、テストもしにくいと思ったので、名前付き内部クラスを作成しました)。
ピザのタイプを表示するパネルは複雑なものではありません。リスト 7 に示すように、GWT の RadioButton ウィジェットを使用します。
リスト 7. WEST (ピザ・タイプ) パネル
public static final String[] PIZZA_TYPES = new String[] {
"Thin Crust Medium", "Thin Crust Large",
"Thin Crust X-Large", "Thick Crust Medium",
"Thick Crust Large"
};
private VerticalPanel buildPizzaTypePanel() {
VerticalPanel pizzaTypes = new VerticalPanel();
HTML label = new HTML("<h2>Pizza</h2>");
pizzaTypes.add(label);
for (int i = 0; i < PIZZA_TYPES.length; i++) {
RadioButton radio = new RadioButton("pizzaGroup",
PIZZA_TYPES[i]);
clearables.add(radio);
pizzaTypes.add(radio);
}
return pizzaTypes;
}
|
後でもっと賢い方法でデータを操作しますが、この時点では、HorizontalPanel の垂直版である VerticalPanel を使っています。HTML ウィジェットも使用していますが、これは HTML をレンダリングする単なるラベルです (基本的には HTML <span> タグのラッパーです)。RadioButton コントラクターには 2 つの引数があります。最初の引数はラジオ・ボタン・グループのストリング・ラベルで、2 つ目の引数はテキスト・ラベルです。それぞれのボタンをパネル、そして消去可能項目のインスタンス・リストの両方に追加し、リスナーのいずれかで使用します。
EAST (トッピング) パネルを作成する
トッピング・パネルは今までのパネルより多少複雑です。トッピングが左右で異なる 1 枚のピザをユーザーが作れるようにしたいためです。トッピングのボタンをクリックすると左右両方にチェック・マークが付きますが、左半分と右半分のそれぞれについてチェック・マークを付けたり消したりすることができます。すべての項目を一列に並べるため、リスト 8 のようにグリッドを使用します。
リスト 8. トッピングのグリッド
public static final String[] TOPPINGS = new String[] {
"Anchovy", "Gardineria", "Garlic",
"Green Pepper", "Mushrooms", "Olives",
"Onions", "Pepperoni", "Pineapple",
"Sausage", "Spinach"
};
private VerticalPanel buildToppingPanel() {
VerticalPanel toppings = new VerticalPanel();
toppings.add(new HTML("<h2>Toppings</h2>"));
Grid topGrid = new Grid(TOPPINGS.length + 1, 3);
topGrid.setText(0, 0, "Topping");
topGrid.setText(0, 1, "Left");
topGrid.setText(0, 2, "Right");
for (int i = 0; i < TOPPINGS.length; i++) {
Button button = new Button(TOPPINGS[i]);
CheckBox leftCheckBox = new CheckBox();
CheckBox rightCheckBox = new CheckBox();
clearables.add(leftCheckBox);
clearables.add(rightCheckBox);
button.addClickListener(new ToppingButtonListener(
leftCheckBox, rightCheckBox));
topGrid.setWidget(i + 1, 0, button);
topGrid.setWidget(i + 1, 1, leftCheckBox);
topGrid.setWidget(i + 1, 2, rightCheckBox);
}
toppings.add(topGrid);
return toppings;
}
|
ここでもまた、VerticalPanel と HTML ウィジェットを使用しています。GWT の Grid にすべてを含めるため、グリッドを作成するときにはそのサイズを設定する必要があります。グリッドの各セルには、プレーン・テキストまたは別の GWT ウィジェットのいずれかを含めることができます。行ごとにボタンと 2 つのチェック・ボックスを作成し、セルに割り当てます。ボタンのリスナーを追加して、チェック・ボックスを消去可能リストに入れます。
ウィジェットのセットアップが完了したので、ここで、定義した 2 つのリスナーを見てみましょう。この 2 つのうち、単純なほうは Clear ボタンのリスナーです。このボタンは消去可能リストをひととおりチェックしてすべてを消去します。リスト 9 を参照してください。
リスト 9. Clear ボタンに定義されたリスナー
private class ClearClickListener implements ClickListener {
public void onClick(Widget sender) {
for (Iterator iter = clearables.iterator(); iter.hasNext();) {
CheckBox cb = (CheckBox) iter.next();
cb.setChecked(false);
}
}
}
|
注: GWT では、RadioButton は実際には CheckBox のサブクラスなので、上記のコードによってクラスのキャスト例外が発生することはありません。
トッピング・ボタンのリスナーは、もう一方のリスナーに比べてほんの少し複雑なだけです。関連付けられたいずれのチェック・ボックスも選択されていない場合、このリスナーは両方のチェック・ボックスにチェック・マークを付けます。いずれかが選択されている場合は両方のチェック・マークを消去します。
リスト 10. ボタンに定義されたリスナー
private class ToppingButtonListener implements ClickListener {
private CheckBox cb1;
private CheckBox cb2;
public ToppingButtonListener(CheckBox cb1, CheckBox cb2) {
this.cb1 = cb1;
this.cb2 = cb2;
}
public void onClick(Widget sender) {
boolean unchecked = !cb1.isChecked() && !cb2.isChecked();
cb1.setChecked(unchecked);
cb2.setChecked(unchecked);
}
}
|
この記事では、簡易バージョンの Slicr クライアントを作成するために必要なコードをすべて使用しました。次回の記事では Derby データベースを使ってサーバー・サイドにデータ層をビルドし、データをデータベース形式から Java オブジェクトに変換して GWT クライアントに送信できるようにする方法を説明します。続いて、サーバーとクライアントを接続するリモート・プロシージャー・アーキテクチャーを紹介します。
サーバー・サイドを独立して実行する必要がある場合は、開発環境と実動環境の両方でのデプロイ方法を検討しなければなりません。また、インターフェースの見た目をもう少し美しくする方法についても説明する予定ですが、とりあえずは GWT ダウンロード・サイトに進んで GWT を自分で試してみてください。
学ぶために
- GWT の Google Groups フォーラムにアクセスしてください。
-
公式 GWT ブログを調べてみてください。
- Derby サイトで Apache Derby に関する資料を入手してください。
- developerWorks の Apache Derby プロジェクト・エリアを調べてみてください。今日からでも Derby を使い始めるための様々な記事やチュートリアル、その他の資料が用意されています。
- Apahce Derby コード・ベースを使って構築された IBM® Cloudscape™ データベースについて、より深く学んでください。
- developerWorks の Eclipse プロジェクト・エリアにアクセスしてください。Eclipse 開発に必要なものがすべて揃っています。
-
developerWorks
technical events and Webcasts で最新情報を入手してください。
-
Eclipse Foundation とそのさまざまなプロジェクトについて学んでください。
- オープン・ソース技術を使用して開発し、IBM の製品と併用するときに役立つ広範囲のハウツー情報、ツール、およびプロジェクト・アップデートについては、 developerWorks Open source ゾーンを参照してください。
- developerWorks の Open source ゾーンには、Apache に関するさまざまな記事や無料の Apache チュートリアルが豊富に用意されています。
-
Safari bookstore には、この記事に関連した話題や他の技術を取り上げた技術書が豊富に取り揃えられています。
- Get an RSS feed for this series. (Find out more about RSS.)
製品や技術を入手するために
-
Apache Derby をダウンロードしてください。
-
Google Web Toolkit をダウンロードしてください。
-
IBM ソフトウェアの試用版を使用して、次のオープン・ソース開発プロジェクトを革新してください。ダウンロード、あるいは DVD で入手できます。
議論するために
-
developerWorks blogs から developerWorks コミュニティーに加わってください。