投稿機能を付ける
メッセージのリスト表示が出来たので、次に投稿機能を付けてみましょう。
例によって、コンポーネント化します。
投稿コンポーネントはSubmitComponentとして作り、それをTestPageに貼付けてみます。
SubmitComponentの構成ファイルは以下のようになりました。
SubmitComponent.html
<form jwcid="@Form"> <table border="0" cellspacing="2" cellpadding="2" align="center"> <tr> <td align="right">タイトル</td> <td><input jwcid="subject" size="60" maxlength="120"/></td> </tr> <tr> <td align="right">お名前</td> <td><input type="text" jwcid="userName" size="60" maxlength="60"/></td> </tr> <tr> <td align="right">Mail</td> <td><input type="text" jwcid="mail" size="60" maxlength="60"/></td> </tr> <tr> <td align="right">URL</td> <td><input type="text" jwcid="url" size="60" maxlength="60"/></td> </tr> <tr> <td colspan="2" align="right"><br/> <textarea jwcid="content" rows="4" cols="60"/></td> </tr> <tr> <td colspan="2" align="right">削除用パスワード : <input type="password" jwcid="userPass" size="4" maxlength="4"/> <input type="submit" jwcid="submitButton" value="送信"/> </td> </tr> </table> </form>
前に作ったMessageComponentと似ています。
静的な文字列を表示する代わりに、フォームを表示します。
SubmitComponent.jwc
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE component-specification PUBLIC "-//Apache Software Foundation//Tapestry Specification 3.0//EN" "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd"> <component-specification class="bbs.view.SubmitComponent" allow-body="no" allow-informal-parameters="no"> <property-specification name="submitMessage" type="bbs.data.Message" persistent="yes"/> <component id="subject" type="TextField"> <binding name="value" expression="submitMessage.subject"/> </component> <component id="userName" type="TextField"> <binding name="value" expression="submitMessage.userName"/> </component> <component id="userPass" type="TextField"> <binding name="value" expression="submitMessage.userPass"/> <binding name="hidden" expression="true"/> </component> <component id="mail" type="TextField"> <binding name="value" expression="submitMessage.mail"/> </component> <component id="url" type="TextField"> <binding name="value" expression="submitMessage.url"/> </component> <component id="content" type="TextArea"> <binding name="value" expression="submitMessage.content"/> </component> <component id="submitButton" type="Submit"> <binding name="listener" expression="listeners.submitAction"/> </component> </component-specification>
これもMessageComponentに似ています。
注意する所としては、
このMessageオブジェクトは、最終的にサブミットされてDBに保存されるので、"yes"にする必要があります。
SubmitComponent.java
package bbs.view; import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.Level; import org.apache.tapestry.BaseComponent; import org.apache.tapestry.IRequestCycle; import org.apache.tapestry.event.PageEvent; import org.apache.tapestry.event.PageRenderListener; import org.objectstyle.cayenne.access.DataContext; import org.objectstyle.cayenne.conf.Configuration; import bbs.data.Message; /** * 投稿コンポーネント * * @author toolkit * @version $Revision$ */ public abstract class SubmitComponent extends BaseComponent implements PageRenderListener { private static final Log log = LogFactory.getLog(SubmitComponent.class); public abstract Message getSubmitMessage(); public abstract void setSubmitMessage(Message submitMessage); public void submitAction(IRequestCycle rc) { Message mes = getSubmitMessage(); Date now = new Date(); mes.setSubmitDate(now); mes.setModificationDate(now); DataContext context = Configuration.getSharedConfiguration().getDomain().createDataContext(); context.registerNewObject(mes); context.commitChanges(Level.WARN); TestPage nextPage = (TestPage) rc.getPage("TestPage"); rc.activate(nextPage); } public void pageBeginRender(PageEvent arg0) { Message mes = new Message(); setSubmitMessage(mes); } }
MessageComponentと大きく異なる点は、PageRenderListenerをインプリメントしている事です。
なぜそのような事をするのかというと、このコンポーネントが描画される前にSubmitMessage変数がセットされている必要があるからです。
ここがセットされていないと、ページを描画する段階で
getSubmitMessage().getSubject()
などのメソッドが呼ばれてしまいます。
当然getSubmitMessage()はnullを返しますので、例外が飛んできます。
描画する前に何かするためには、PageRenderListenerをインプリメントし、pageBeginRenderメソッドを実装します。*1
submitActionメソッド内では、データベースにコミットしています。
本当はコミットする前に入力値を検証する必要がありますが、ここでは省略します〜。
このsubmitActionメソッドのコードは、これまたWebObjectsと似ています。
データベースにコミットするコードの類似性は前の記事で紹介しましたが、ページの遷移もコードが似ていますねぇ。
TestPage nextPage = (TestPage) rc.getPage("TestPage"); rc.activate(nextPage);
TestPage nextPage = (TestPage) pageWithName("TestPage"); return nextPage;
WebObjectsではページ遷移をする場合、そのページオブジェクトを返す必要があるのでreturnしていますが、Cayenne同様、TapestryもかなりWebObjectsが意識されている事が分かると思います。
ここまで出来てしまったら、SubmitComponentをTestPageに貼付けるだけです!
TestPage.htmlは以下のようにします。
TestPage.html
<html> <head><title>TestPage</title></head> <body> <span jwcid="submitComponent"/> <hr/> <div align="center"> <span jwcid="messageLoop"> <span jwcid="messageComponent"/> </span> </div> </body> </html>
さっきと違うのは、submitComponentが追加になった所です。(まさにコンポーネントを貼付けました。)
あとは見栄えの問題で、submitComonentの下に罫線を引いて、messageLoopをセンターあわせにしただけです。
当然、.pageにもコンポーネント定義を追加しなければなりません。
とはいっても
一行を追加するだけです・・・
コンパイルし直して、ページにアクセスしてみた様子が以下です。(クリックで拡大)
こんなかんじで、ぽんぽんページが出来ます。いい感じですね!
*1:この辺はWebObjectsには無い考え方で、結構悩みました・・・はたしてこの方法が良いのか悪いのかもよく分からないんですが・・・