劣化Twitter作ってみた

習作がてら作ってみました。飽きたので放流します。 ソースはこちら。
http://www.nagaseyasuhito.net/nicola.zip
eclipseWTP+m2eclipseで作りました。 pom.xmlもついてますが単体でビルドできるかどうかわかりません、ごめんなさい。 なのでwarもつけておきました。
一応こんな感じに動いています。
http://nicola.nagaseyasuhito.net/

使ったフレームワーク
wicket1.3.0-beta4
guice1.0
warp::persist
JPA(Hibernate3.2)

warp::persistはguiceHibernateJPAをイイ感じに使うためのやつです。 Dynamic FinderというKuina-DAOからCriteriaを抜いたようなのがありますが、wicket-guice環境だとちゃんと動きませんでした。
Kuina-DAOがSeasar非依存になるととても嬉しいなぁ。

Resource(主に画像)がSessionに入っちゃってるのでSessionがバカでかくなります。 SharedResourcesに入れたのはSessionに保存されないようにならないのかな、俺の書き方がいけないのかな。
LoadableDetachableModelの使い方が変です。 DataProviderのmodelメソッドでもっかいfindなりするのも面倒だしなぁ、setCacheableすれば気にならない、かな?

そんな感じで所々とても手抜きです。 DISり待ちでございます。

wicket-auth-rolesとonSubmitでpost dataを保持してくれない件

Wicket-1.3.0-beta3でますねー。 PasswordTextFieldのsetPersistenceがUnsupportedExceptionを吐くのでさっそくwicket-auth-rolesについてるSignInPageが使えなかったりしますが。 PaletteのRecorder問題も直ってよかった。

で、表題の件ですよ。
サインインが必要ないページ(PageA)でサインインが必要なページ(PageB)にForm#onSubmitすると、RestartResponseAtInterceptPageException吐いてサインイン画面に遷移しますよね。
で、ユーザー名パスワード入力してサインインするとFormで入力した値がnullになってPageBが呼ばれ(Form#onSubmitの場合)たり、PageAに戻ったり(FormにaddしたButton#onSubmitの場合)しちゃうんです。

週末この問題にハマってたんですが、一応解決策っぽいの。

formのmethodをgetにする。 イェイ、これだけ。

巨大なデータだったり、fileuploadがあったらどうなのかなぁとか思うんですが、getにしておけばこうすると問題なさげです。
というのもWicketさんはRestartResponseAtInterceptPageException吐いてサインインページに飛ばしたとき、戻り先(continueToOriginalDestination)はURLしか保持してないんですねー。 1年くらい前にMLにこの問題を言及した人が「んじゃyouがPOST DATA保持するの作っちゃいなyo!」みたいに書かれてたけど放置プレイでした。 そんなもんかー。
んじゃ、俺が作れって? うう、。

WebPageやhtmlを頻繁に書き換える場合

package net.nagaseyasuhito.sandbox;

import org.apache.wicket.application.ReloadingClassLoader;
import org.apache.wicket.protocol.http.ReloadingWicketServlet;

public class SandboxWicketServlet extends ReloadingWicketServlet {
	private static final long serialVersionUID = 1L;

	static {
		ReloadingClassLoader.includePattern("net.nagaseyasuhito.sandbox.page.*");
	}
}

こんな感じにしとけばOKだと思います。 Filterも似たようなのがあります。
WTPはauto publishingをoffにしとくこと。

Wicket1.3のWicketTester

Wicket1.3になってWicketTesterはApplicationを継承しなくなったので、SeasarにS2WicketのSeasarComponentInjectionListenerの登録を任せる場合は、

<component name="wicketTester" class="org.apache.wicket.util.tester.WicketTester">
  <initMethod>
    #self.getApplication().addComponentInstantiationListener(new org.seasar.wicket.injection.SeasarComponentInjectionListener(#self.getApplication()))
  </initMethod>
</component>

こんな感じ。

Wicket1.3-beta-2とS2Wicket

なんとなくWicket1.3に手を出してみました。
apacheに移動してパッケージ名が変わったのでS2Wicketの方もちょっと手直し。
org.seasar.wicket.injection.InjectionProcessor
org.seasar.wicket.injection.S2ContainerHolder
org.seasar.wicket.injection.S2ContainerLocator
org.seasar.wicket.injection.SeasarComponentInjectionListener
のimport文を"wicket.*"から"org.apache.wicket.*"に変更で終わり。

わーい楽チン。

Wicketをfilterで動かす場合はS2Servletが使えないので、WebApplication#init()内で、

SingletonS2ContainerFactory.init();

すればとりあえず動くはず。


1.3で遊んでみるー。

WTPを使いつつPOHPをちまちま書くには

WTPで動かすtomcatはデフォルトの設定のままだとリソースをちょこっといじっただけでrepublishしちゃうので、JPAとか使ってると時間がかかってイライラするのです。

なのでrepublishしないように設定するのはどうやるのかなー、調べました。たぶんこんな感じ。

赤で囲ったトコを選択すればリソースを書き変えても自動でrepublishされなくなります。 やったね!

WicketTesterのインジェクション

こんな感じ?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd">
<components namespace="s2junit4">
<component name="context" class="org.seasar.framework.unit.impl.SimpleInternalTestContext" />

    <component name="wicketTester" class="wicket.util.tester.WicketTester">
        <initMethod name="addComponentInstantiationListener">
            <arg>
                <component class="org.seasar.wicket.injection.SeasarComponentInjectionListener">
                    <arg>wicketTester</arg>
                </component>
            </arg>
         </initMethod>
    </component>
</components>