Macintosh Developer Online (MDOnline)


2001年8月11日発行号 - WebObjects三昧-1



来週はMacWIREのお休みですので、せっかく倉橋さんががんばって記事を書いてくれていますから、一気に全部掲載します。通常だったら、小出しするのですが、そういう事情です。よろしくお願いします。サイズが大きくなるとMajordomoがエラーを出すみたいなので、2通に分けて配信します。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥Information
WebObjectsの日本語マニュアルが公開されはじめています
 
WebObjects 5をとりあえず使ってみたい人は無償の「トライアルCD」をどうぞ!
 まで、送り先を記載してメールをください。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Macにラックマウントタイプがないじゃないかと昨日記載しましたけど、読者の小宮さんより御指摘をいただきました。以下のような製品が売られています。訂正させてください。特に、iMacを1Uラックに押し込めるという製品はなかなか魅力的ですね。しかし、Power Macとなると4Uになってしまうのですね。ちなみに、iRackというiMacのスタンド?もあるみたいですね。

◇MARATHON: Rack シリーズ
 http://www.focal.co.jp/1_PRODUCT/MARATHON/marathon_.html

日本の値段は以下のBrainmusicさんのサイトで参照できます。うーん、なんかIntel系だとラックマウントサーバくらいの値段で、マックとなるとラックのみですかぁ…。

◇Products // Marathon Computer
 http://www.brainmusic.com/products/marathon/marathon_top.html

ちなみに、開発元のMarathon Computerでは$399と送料となっています。あるページでは100ドルほどの送料で直接購入したという話もみました。

◇iRack
 http://www.marathoncomputer.com/pr_irack.html

高くても…などと言いながら、ちょっと値段が張りますね〜。というわけで、ラックマウント情報でした。いろいろ調べているとメーリングリストなんかにも掲載されたので、もうとっくに御存じの方も多いかと思います。
とまあ、ばらしてラックに入れるものもありますが、やっぱりAppleから純正品としてあると、また違うんじゃないかと思ったりもしますが、どんなもんでしょうね〜。
(新居雅行 msyk@mdonline.jp


実際のオンラインコマースサイトを題材にしたWebObjectsの自習教材を発売

テクニカル・ピットは、WebObjects自習用教材「SimpleOrder Ver.1.1」をリリースした。同社は、MDOnlineでWebObjects関連の連載を執筆している倉橋浩一氏が代表となっており、WebObjects関連の開発やトレーニングを行っている。同社のオンラインショッピングサイトで使っているアプリケーションを題材にした自習用教材がSimpleOrderである。WebObjects 4.5に対応しており、Java言語で記述されている。Mac OS X Server 1.2ないしはWindows NT/2000対応版が用意されている。OpenBase SQL 6.5.7向けのサンプルデータも付属する。実行ファイル一式とインストールマニュアルが含む「バイナリ版」は同社のサイトから無償でダウンロードできる。ソースプログラムと70ページ強のテキストを含む「フルセット版」は5万円で販売される。実際に自習を行うには、フルセット版が必要となる。アップルが開催している講習会のWebObjects-Iあるいは同社のHomework終了レベルの知識背景が必要であるとしている。より実際のアプリケーション構築に密着した内容を、SimpleOrderで習得できるとしている。

関連リンク:WebObjectsのページ
カテゴリ:WebObjects, サービス


倉橋浩一、じつはWebObjectsで飯食ってます》WebObjectsで作る掲示板〜続編(1)/再開です

どうも大変お待たせしました、WebObjectsで作る掲示板、の、続編です。

えー、続編と言っても、なにせ7ヶ月も経ってしまいましたので、元の記事がどんなのだったか覚えていらっしゃる方の方が少ないかも....というわけで、まず最初に、こちらをご参照くださいませ。

<MacWIRE掲載時には記事へのリンクをお願いします。>
<MDOnline購読者は、Webサイトで参照して下さい。カテゴリーは「倉橋浩一、じつはWebObjectsで飯食ってます」にある「WebObjectsで掲示板を作る」の一連のテキストです>

7ヶ月も経ってしまえば、前回掲載時に初心者だった方も、今は「そんなの鼻歌まじりで書けるよ」てなことになっているかもしれませんねぇ。それに当時の最新バージョンはWebObjects 4.5でしたが、今はWebObjects 4.5の出荷も停止され、WebObjects 5が急速に普及しつつあります。そんな中、どっちで書こうかと迷ったのですが、とりあえずWebObjects 4.5で掲示板をfixしてしまってから、次のステップとしてWebObjects 5への移植を試みる、という展開にしたいと思います。私も含めて、まだWebObjects 4.5を捨てられない人も多いと思いますし、かと言ってWebObjects 5を無視するわけにもいかないですし。

さて、では、追加する機能を考えてみます。「つい忘れていた機能」と「最初からつけようと思っていた機能」があります。

 1.「書き込みをやめる」ボタン
 2.メッセージ一覧ページにページめくりの機能を追加
 3.メッセージ削除の機能
 4.複数掲示板のサポート
 5.コメント機能

このうち、今回は1〜3までを片づけることにします。複数掲示板とコメント機能、作るのは簡単なんですが、説明がちょっと大変....ここ今度はそんなにお待たせしませんから....。

では、まず最初に、前回作ったプロジェクトSimpleBoardをProjectBuilderで開いておいてください。
(続く)
[倉橋浩一/テクニカル・ピット]

関連リンク:WebObjectsのページ
カテゴリ:WebObjects, 倉橋浩一、じつはWebObjectsで飯食っています


倉橋浩一、じつはWebObjectsで飯食ってます》WebObjectsで作る掲示板〜続編(2)/「書き込みをやめる」ボタン

ボタンとは言っていますが、実際にはHyperLinkにします。ボタンにしないのは、その必要がないからです。ボタン、つまりWOSubmitButtonを使うのは、WOFormの中で入力したテキストやチェックボックスの状態をサーバに送るのが目的です。ところが、「書き込みをやめる」機能の場合には、サーバにテキストなどを送信する必要がありません。単に、Actionメソッドを呼び出せれば、機能を実装することができます。それに、Formの内容をsubmitするのは、それなりにオーバーヘッドがかかりますし。また、ユーザ教育という点からも、ボタンとリンクはきっちり使い分けしておくことが必要だと思います。

さて、作業の手順は、以下の通りです。

(1).ProjectBuilderからMessagePage.woを開く:WebComponentsグループをクリックしてから、MessagePage.woをダブルクリックします。
 

(2).WOBuilderでActionメソッドを追加する(actionAbort):WOBuilderウインドウ左下の「Edit Source▼」から「Add Action...」を選び、Name:actionAbort、Pagereturned:MessageListPageを入力し、Addボタンをクリックします。
 

これでactionAbortが追加されました。
 

(3).WOHyperLinkを貼り付ける:WOBuilderの上で、送信、リセットボタンのカーソルを置き、一つスペースを空けてからWOHyperLinkを配置します。
 

"Hyperlink"の文字を、"書き込みをやめる"に変更します。そのままタイプすればOKです。
 

(4).WOHyperLinkのactionと追加したactionAbortをバインド:バインドしたら、一度Saveしておきましょう。
 

(5).ProjectBuilderに戻って、actionAbortをインプリメント:WOBuilderからProjectBuilderに手っ取り早く戻るには、「Edit Source▼」から「View Source File」を選びます。

MessagePage.javaの末尾付近に、先ほど追加した「actionAbort」がありますので、以下のコードを書きます。MessagePageは、MessageListPageで「書き込み」をクリックした時に呼び出されるactionNewMessage()で生成されます。actionNewMessage()では、新しいレコードを一件追加しています。この時、追加されたレコードは、まだディスクには書き込まれていません。actionAbortに追加したコードは、これを書き込むことなく破棄するものです。


//MessagePage.javaファイルのactionAbortメソッド
public MessageListPage actionAbort() {
session().defaultEditingContext().revert(); // 未保存の変更を破棄する

MessageListPage nextPage = (MessageListPage)pageWithName("MessageListPage");
return nextPage;
}


(6).テスト:では、さっそく試してみましょう。ProjectBuilderのToolsメニューからProject Build→Build & Runを選びます。1〜5までの手順に間違いがなければ、build完了後、ブラウザに「掲示板へ」のメッセージが表示されるはずです。
 

「掲示板へ」をクリックし、さらに「書き込み」をクリックすると、メッセージ書き込み画面にたどり着きます。うーん、久しぶりに見ても、やっぱりひどいデザインですね(笑)。
 

....気を取り直して、「書き込みをやめる」をクリックします。再びメッセージ一覧画面に戻りますが、書き込みをやめたので、何の変化もありません。当たり前ですが。

さて、これで一つ片づきました。どんどん行きましょう。
(続く)
[倉橋浩一/テクニカル・ピット]

関連リンク:WebObjectsのページ
カテゴリ:WebObjects, 倉橋浩一、じつはWebObjectsで飯食っています


倉橋浩一、じつはWebObjectsで飯食ってます》WebObjectsで作る掲示板〜続編(3)/ページめくりの機能を追加

メッセージ一覧画面MessageListPageは、データベースに登録されているメッセージを一覧表示するための画面なのですが、WODisplayGroupのdgMessageに1ページあたりのレコード数が設定されているにもかかわらずページを送るためのボタンが用意されていません。つまり、10件以上登録すると、そのメッセージが表示されなくなってしまう、という間抜けな状態です。

なお、dgMessageがどう設定されているかは、WOBuilder上でdgMessageをダブルクリックすれば見ることができます。
 

ここには、対象となるEntity(テーブル)がMessageであり、1ページに表示する行数は10、起動時にデータを読み込み(fetch on load)、更新日付順(updated)順にソートされる、と設定されています。ちなみに、ソート順は、dgMessageに対してupdateDisplayedObjects()を実行した時に反映されます。

なお、ページをめくるための機能を追加するには、二つの方法があります。それは、WOHyperLinkを使って自作する方法と、WebObjectsに予め用意されているページ管理コンポーネントWOBatchNav.Barを使う方法です。WOHyperLinkを使う方法については、新居さんの連載でも取り上げられていましたので(一言でいえば、WOHyperLinkを二つ用意し、WODisplayGroupのdisplayNextBatchと、displayPreviousBatchをそれぞれのactionとバインドすればOKです)、ここではページ管理コンポーネントを使ってみます。あまりデザインが良くないし変更の自由度もイマイチなのですが、必要な機能が用意されていて、とにかく簡単に使えますので。

(1).WOBuilderでMessageListPageを開く
 

(2).位置を決める:WOBatchNav.barを配置する位置を来ます。「戻る」と「書き込み」のリンクが配置されたテーブルと、WORepetitionの間にカーソルを置きます。この場合、WORepetitionの外側であれば、どこでも構いません。お好きな場所にどうぞ。WORepetitionの内側に置くとどうなるかは、後でご自分で試してみてください。少なくとも、壊れることはありませんから。

(3).WOBuilder上で、パレットを開く:パレットは、パレットアイコン(ShowPalette)をクリックするか、WindowメニューからPaletteを選択して、開くことができます。パレットの一番左にあるWOExtensionsアイコンをクリックします。
 

(4).WOBatchNav.Barを配置する:パレット上のWOBatchNav.Barを、さきほど決めた位置付近までドラッグします。なにやら立派なバーが配置されたはずです。
 

(5).WOBatchNav.BarとWODisplayGroupをバインド:dgMessageとWOBatchNav.BarのdisplayGroupをバインドします。

これだけでもページめくりとして使えるのですが、もうちょっと設定をします。インスペクタで、widthを400、objeectNameに"Message"と入力します。
 

ここで、WOBuilderをSaveします。

(6).テスト:これはコンポーネント上だけの変更ですから、コンパイルは不要です。ブラウザで、最初の画面(「掲示板へ」とだけ書かれた画面)に戻り、「掲示板へ」をクリックします。すると、「戻る」「書き込み」の下に、メッセージの数と、さきほど入力した「Message(s)」が表示されているはずです。
 

ここでは3件しかデータが入っていませんので、ページめくりの効果はわかりません。ので、適当にデータを入力してみます。すると、表示が変わります。
 

左右に向いた矢印をクリックするとページが前後し、ページ数を入力するとそのページを直接呼び出し、Display itemsを変更すると1ページに表示する件数を変更することができる....ページめくりの機能が実装できました。

なお、Message(s)の左にある数字は、WODisplayGroupのallObjects()に記録されているレコードの件数です。つまり、allObjects()は、fetch on loadなどでデータを読み込むと、すべてのデータを読み込んできてしまいます。せいぜい100件ぐらいまでならこの方式でも我慢できますが、これより多くなるとWODisplayGroup+WOBatchNav.Barでは満足なパフォーマンスを得ることができません。実は、この辺への対応が、WebObjectsのプロとアマを分ける一つの境界線だったりするのですが....。
(続く)
[倉橋浩一/テクニカル・ピット]

関連リンク:WebObjectsのページ
カテゴリ:WebObjects, 倉橋浩一、じつはWebObjectsで飯食っています


倉橋浩一、じつはWebObjectsで飯食ってます》WebObjectsで作る掲示板〜続編(4)/メッセージ削除の機能

どんどん行きます。

書いたメッセージを削除できるようにしましょう。でも、どんなメッセージでも削除していいというわけにはいきません。削除できるのは、キーワードが登録されているメッセージとします。また、それでは公序良俗に反するようなメッセージが書き込まれた時に、システム管理者として何も手を出せないということになってしまいますから、管理者用キーワードを入力すれば、すべてのメッセージを削除できるようにします。

動作としては、

1.メッセージ一覧表示に「削除」というWOHyperLinkを設ける。
2.「削除」をクリックすると既存のメッセージ入力画面へ
3.メッセージ入力画面には、クリックしたメッセージが表示される。新たに追加する入力フィールドにキーワードを入力し、「削除」ボタンをクリックすると、キーワードを確認した後、削除を行う。
4.メッセージ一覧表示に戻る

となります。

では、作っていきましょう。

(1).メッセージ一覧画面の改造:WOBuilderでMessageListPageを開きます。WORepetitionの内側ならどこでもいいですが、とりあえず「タイトル」の後に「削除」と入力し、入力した文字を選択してから、WOHyperLinkを配置します。
 

「Edit Source▼」から「Add Action...」を選択し、Name:actionDelete、Page returned:MessagePageを入力し、Addボタンをクリックします。
 

actionDeleteと、「削除」WOHyperLinkのactionをバインドします。actionDelete()では、MessagePageを生成してから、削除リンクによって選択したmessageを次のページに渡すコードをProjectBuilderに戻って書きます。


//MessageListPage.javaファイルのactionDeleteメソッド
public MessagePage actionDelete() {
MessagePage nextPage = (MessagePage)pageWithName("MessagePage");

session().defaultEditingContext().revert(); // 念のため、未保存の変更を破棄する
nextPage.setMessageForDelete(aMessage); // クリックしたメッセージを次のページに渡します

return nextPage;
}


(2).メッセージ入力画面MessagePage.woの改造:再びWOBuilder上の作業となります。MessagePage.woを開きます。

最初に、新たなフラグを追加します。MessagePageが新しいメッセージを追加するために呼び出されたのか、それとも削除するために呼び出されたのかを区別するためのフラグです。「Edit Source▼」から「Add Key...」を選択し、Name:isDelete, Type:booleanを入力し、Addボタンをクリックします。
 

削除の処理を行うためのactionを追加します。「Edit Source▼」から「Add Action...」を選択し、Name:actionDelete, Page returned:MessageListPageを入力し、Addボタンをクリックします。

「送信」ボタンの右隣に「削除」ボタンを追加します(WOSubmitButtonを追加し、valueに"削除"と設定)。actionDeleteと、「削除」ボタンのactionとをバインドします。

あとは、書き込みをするのか、削除をするのかに応じて、表示されるボタンを切り替える様にします。

「送信」「リセット」ボタンを選択してからWOConditionalを配置し(表示が崩れますが、気にしない)、WOConditionalのconditionとisDeleteをバインドし、negateをYESにします。こうすることで、通常のWOConditionalと異なり、条件が成り立たない時だけ、WOConditionalの中身をページ上に表示することができます。さらに「削除」ボタンを選択してからWOConditionalを配置し、もう一度isDeleteとWOConditinalのconditionをバインドします。今度はnegateはそのままです。
 

以上によって、isDeleteがtrueの時、つまりメッセージ一覧表示画面から「削除」をクリックして呼びされた時には「削除」ボタンが表示され、今まで通り「書き込み」をクリックして呼び出した時には「送信」と「リセット」が表示されます。もちろん、「書き込みをやめる」は、いずれの場合も表示されます....書き込みだけでなく削除もやめるわけですから、ここは「一覧に戻る」にしておきましょうか。

あ。すみません、大事な作業を忘れていました。削除キーワードを入力するWOTextFieldと、そこで使うためのStringを用意しなければなりません。削除ボタンのすぐ右か左にWOTextFieldを配置してから、「Add Key...」でName:strKey, type:Stringを追加し、strKeyとWOTextFieldのvalueをバインドします。
 

それと、削除時にパスワードを変更できてしまうのはまずいので、パスワード入力欄だけは非表示にします。パスワードという文字のどこかをクリックしてから、エレメント階層表示部で<TR>を選択します。
 

ここで例によってWOConditionalを配置して<TR>全体を覆います。さらに、isDeleteをconditionとバインドして、negateをYESにします。これで、この行全体が、削除時には表示されなくなります。最終的に、こんな感じになりました。
 

では、ProjectBuilderに戻り、コードを書きましょう。

次に、MessageListPageからmessageを受け取るためのメソッドを追加します。このメソッドでは、messageの設定をするとともに、isDeleteをtrueにしています。

//MessagePage.javaファイルのsetMessageForDeleteメソッド
public void setMessageForDelete(EOEnterpriseObject value) {
session().defaultEditingContext().revert(); // 未保存の変更を破棄する

isDelete = true; // 削除作業をするぞ、というフラグ

newMessage = value; // 対象となるメッセージを保存
}

続いて、actionDeleteです。ここは、「削除」ボタンをクリックした時に呼び出され、messageを削除してから元のMessageListPageを返します。キーワードが管理者パスワード(定数で埋め込んでいます)かメッセージ書き込み時に入力したパスワードと一致すれば、そのメッセージを削除します。

//MessagePage.javaファイルのactionDeleteメソッド
public MessageListPage actionDelete() {
MessageListPage page = null;
try {
if (strKey.equals((String)newMessage.valueForKey("password")) || strKey.equals("kesiteyaru")) {

session().defaultEditingContext().revert(); // 未保存の変更を破棄する

session().defaultEditingContext().deleteObject(newMessage); // 削除するメッセージを指定

session().defaultEditingContext().saveChanges(); // 未保存の変更を書き込む

page = (MessageListPage)pageWithName("MessageListPage");
}
else {
strKey = "cannot delete";
}
}
catch (Exception ex) {
debugString(ex.toString());
page = null;
}

return page;
}

エラー処理を簡略化していますし、パスワードが一致しなかった場合にはキーワード欄に直接エラーが表示されるという超手抜きですが。

そうそう、いちいち書いていませんけど、WOBuilderはわりに複雑なアプリケーションですので、たまにクラッシュします。ので、作業中、こまめに保存するようにしてください。幸い、undoがよく効きますので、うっかり保存してしまっても、戻すことができますから。
(続く)
[倉橋浩一/テクニカル・ピット]

関連リンク:WebObjectsのページ
カテゴリ:WebObjects, 倉橋浩一、じつはWebObjectsで飯食っています


倉橋浩一、じつはWebObjectsで飯食ってます》WebObjectsで作る掲示板〜続編(5)/テスト実行

WOBuilder上のコンポーネントがすべて保存されているのを確認してから、ProjectBuilderでBuild & Runを選びます。

これまでの操作に間違いがなければ(あるいは私の原稿にミスが無ければ)、コンパイルが無事終了し、例によってブラウザ上に「掲示板へ」という表示が現れるはずです。これをクリックし、適当なテスト用メッセージを入力します(パスワードも入力してください)。ごらんのように、メッセージを書き込む時には、削除に関するボタンは現れていません。
 

では、「送信」ボタンをクリックします。データベースに書き込んだ後、一覧表に戻ります。
 

で、メッセージ一覧で「削除」をクリックすると、画面はちゃんと削除仕様になっています。
 

ここでキーワードを入力してから削除ボタンをクリックすると、一覧表からメッセージが消えてくれました。
 

例によって駆け足でしたが、如何でしょう。続きは、今月中の出稿を予定しております。

それにしても、デザインがひどいですねぇ....次回は、その辺もちょっとなんとかしましょうか。読者の方で、「もうちっとマシなデザインをしてやろう」という方の無料支援、お待ちしております(笑)。

◇今回の掲示板のプロジェクトファイル
 http://mdonline.jp/figs/01/0018/SimpleBoard2.tar



あちこち、Code RedとかSirCamだかで大騒ぎですね。私のところにもサーバのログにCode Redの長い文字列が現れたり、どこかの誰かから同一の文面で重要そうなファイルが送られてきたりします(毎日、企画書ファイルを送ってくるlii.co.jpという会社の方、すぐ対策してください)。まったく迷惑な世の中になったものです。

世の中といえば....世の中には夏休みというものがあるそうですね(泣)。うーむ、しかし、私は東京生まれなのでどこにも行けません。9月になったらまた3回ほど沖縄に遊びに行く予定なので、公設市場「きらく」のナーベラ味噌炒めとテビチ定食、それに「御殿山」と「首里そば」を夢見つつ、蒸し暑い東京で大人しく仕事してまふ。ちなみに、"インテリなキュウリ状の食べ物"は、沖縄名物でゴーヤーと言いますです。豚肉、固く水切りした豆腐と一緒にガッと炒めるとゴーヤーチャンプルーという料理になります。火を通し過ぎないのがコツ。

ではでは。
[倉橋浩一/テクニカル・ピット]

関連リンク:WebObjectsのページ
カテゴリ:WebObjects, 倉橋浩一、じつはWebObjectsで飯食っています