2009年4月8日水曜日

GAE/JavaでWicketを使ってみる

本日 Google App Engine for Java が提供開始されていて、中身を見ているとどうやらシンプルなWebAppなカンジ。Wicketも動作しそうだなーと思って試してみたメモを書いておく。去年GAEがリリースされた時もその日に色々エントリを書いたのが懐かしい。

ただし、GAEforJavaのアカウント(?)だか承認のメールが来ていないので、デプロイできておらずローカルでの動作確認しかできていない。デプロイしても動作するかどうかが不明だ…。

開発環境の準備

Eclipseを使用している事と、EclipseにGAE用のプラグインをインストールしてある事。

プロジェクトを作る

wicket-quicksartするか、EclipseのGAEプラグインで作るか、で迷うけどGAEプラグインで作る事にする。というのも、GAEプラグインが「${basedir}/war」の直下を固定で見ている気がするので、quickstartしてからフォルダ構成を変えるよりはGAEで作ったプロジェクトにWicket関連のモジュールをコピーする方がラクそうだから。

Eclipse上でプロジェクトを作る
新規作成Wizardで[Goolge/Web Application Project]を選択する。
Wicket関連のモジュールをコピーする
プロジェクト内の war/WEB-INF/lib直下に以下をコピーする。
  • wicket-1.4-rc2.jar
  • slf4j-api-1.4.2.jar
  • log4j-1.2.4.jar
  • slf4j-log4j12-1.4.2.jar
wicket-quickstartを流した事があれば、全部mavenのローカルリポジトリに存在するはずなので、そこからコピーするとかする。コピーした後は、Eclipse上でwar/WEB-INF/lib配下の対象jarを選択して[Build Path][Add to Build path]しておく。
web.xmlを修正する
普段wicket-quickstartで作られるものをそのまま流用。対象ファイルはwar/WEB-INF/web.xml。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
  <filter>
    <filter-name>wicket.shin1ogawa</filter-name>
     <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
    <init-param>
      <param-name>applicationClassName</param-name>
      <param-value>com.shin1ogawa.WicketApplication</param-value>
     </init-param>
   </filter>
  <filter-mapping>
    <filter-name>wicket.shin1ogawa</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
com.shin1ogawa.WicketApplicationっていうのが自分のWicketApplicationクラス。ここは適宜変えてくだしあ。
log4.propertiesを修正する
src/log4j.propertiesに以下のWicket用のロガーの設定を追加する。
log4j.logger.org.apache.wicket=INFO, A1
log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=INFO, A1
log4j.logger.org.apache.wicket.version=INFO, A1
log4j.logger.org.apache.wicket.RequestCycle=INFO, A1
JPAを使う予定の場合は、ついでに以下も追記しておくと良い。
log4j.category.DataNucleus.Connection=DEBUG, A1
log4j.category.DataNucleus.Query=DEBUG, A1
もちろん、自分のアプリケーション用の設定も必要であれば追記する。
Wicketの実行モードをDEPLOYMENTにする
残念ながら、DEVELOPMENTモードでは動作しない。というのも、DEVELOPMENTモードではリソースのチェックか何かにModificationWatcherというクラスが動作して、その先で new Thread() している箇所があり、そこでAccessControlException(java.lang.RuntimePermission modifyThreadGroup)が発生してしまうため。例えば自分ならWicketApplicationを以下のようにした。
package com.shin1ogawa;

import org.apache.wicket.Application;
import org.apache.wicket.protocol.http.WebApplication;

public class WicketApplication extends WebApplication {
  public WicketApplication() {
    System.out.println("WicketApplication constructor()");
  }

  @Override
  public String getConfigurationType() {
    return Application.DEPLOYMENT;
  }

  @Override
  protected void init() {
    super.init();
    mountBookmarkablePage("/home", HomePage.class);
  }

  public Class<HomePage> getHomePage() {
    return HomePage.class;
  }
}
ローカル環境のjava.policyを設定すれば良いと思うが、Macの場合にコイツをどこに配置すればいいのかわからんし、とりあえずWicketが動いてりゃそれでいいし、あんまり困らんので放置しておく。
セッションを有効にする
GAEの設定ファイルである、war/WEB-INF/appengine-web.xml内のappengine-web-app要素の直下に以下を追加する。
<sessions-enabled>true</sessions-enabled>
アプリケーションを実行する
GAEプラグインでプロジェクトを作った場合は、プロジェクトと同時にWeb Applicationの実行の構成も作られているのでそれを実行し、http://localhost:8080/を開けばおk!自分の場合は以下のようにQuickstartで作ったHomePage.javaを少し変えた程度。
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
if (user != null) {
 add(new Label("message", "Hello, " + user.getNickname()));
} else {
 getRequestCycle().setRequestTarget(
   new RedirectRequestTarget(userService.createLoginURL("/home")));
}
未ログイン時にGoogleのログインページへリダイレクトするため(ログインして返ってくるため)に、WicketApplication中で mountBookmarkablePage("/home", HomePage.class); しています。

困っている

データベースも使いたい&JDOよりもJPAでしょ!と思うのでJPAを使っているが、JPQL中でのEntityクラス名をFQCNにしないと org.datanucleus.exceptions.ClassNotResolvedException とか出てしまう。persistence.xml中でclass要素の指定をしてもダメ、DataNucleusのサイトにあった orm.xml を追加しないとダメか?と試したがそれだともっとダメなカンジ。FQCNで指定すればorm.xmlが無くても動作するし、なんだろなー。

コメントを投稿