GAEjを今更ながら触ってみた

参考にしたのは以下のページ。「JSPの日本語表示」までやってみた。

Google App Engineで手軽に試すJavaクラウド

以下、大した事ないけど、自分的メモ。

Google App Engineのアカウント

ケータイのベンダー入力する画面の「User Name」は、携帯メールアドレスのドメインの前部分を入力する。

使用許諾メールは、昨日(2009/11/28)に申請出したら、1分もかからず送られてきました。

今の時期、空いてる?

EclipseでのGAEjアプリケーション

1. GAEjプラグイン内のJetty

EclipseプラグインをインストールしてGAEjアプリケーションを構築する。

ローカルでのアプリケーションの動作確認は、そのプラグインに組み込まれているJettyで実行する。

このJettyは、すでにJSPを利用可能な状態に設定されている。

「WEB-INF以下にworkフォルダ置いて、プリコンパイルされたJSPのコードを見る」事も、もちろん可。

2. ワークスペースの設定によって、JSPファイルが「問題」にされる。

別に設定しなくても動作はするけど、なんかキモチワルイ。

ワークスペースの「インストール済みJRE」をJDKに変える事で、JSPが正常に認識されるようになる。

JSPでJSTLを利用したい場合は、ビルドパスにGAEjプラグインのJSTLのjarにパスを通す。

僕の環境だと以下のディレクトリ内の「repackaged-appengine-jakarta-jstl-1.1.2.jar」と

「repackaged-appengine-jakarta-standard-1.1.2.jar」に通しました。

${Eclipseのpluginsディレクトリ}com.google.appengine.eclipse.sdkbundle_1.2.6.v200910130758\appengine-java-sdk-1.2.6\lib\tools\jsp

なお、ELを使う場合は、pageディレクティブに「isELIgnored=“false"」を追記する。

GAEjアプリケーションでのJSPの使用

ぶっちゃけ実際にGAEjでアプリを作る事になった場合、JSPの出番はあまり無いかもしれないけど、

サンプルのJSPがあまりにもスクリプトレットを多様して気持ち悪かったので少しリファクタリングしました。

といっても、簡単なカスタムタグを定義しただけですが。

1. Googleのユーザ系オブジェクトをスクリプトレット無しで扱う為のカスタムタグ
package guestbook.web.tags;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

/**
 ページコンテキストにオブジェクトをロードするカスタムタグの基底クラス。
*/
public abstract class ObjectLoadOnPageTag<T> extends TagSupport {
    /**
     ページコンテキストにオブジェクトを設定する際に指定するキー。<br/>
     JSPからは、このフィールドに設定した文字列でページコンテキストにロードした
     オブジェクトを参照できる。
    */
    private String name;

    @Override
    public int doStartTag() throws JspException {
        if (name == null || name.equals(""))
        throw new JspException("name属性を指定する必要があります。");
        pageContext.setAttribute(name, getLoadedObject());
        return SKIP_BODY;
    }

    protected abstract T getLoadedObject();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package guestbook.web.tags;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

/**
 ページコンテキストにcom.google.appengine.api.users.UserServiceをロードするカスタムタグ。
*/
public class GoogleUserServiceLoadTag extends ObjectLoadOnPageTag<UserService> {
    @Override
    protected UserService getLoadedObject() {
        return UserServiceFactory.getUserService();
    }
}
package guestbook.web.tags;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;

/**
 ページコンテキストにカレントのcom.google.appengine.api.users.Userをロードするカスタムタグ。
*/
public class GoogleCurrentUserLoadTag extends ObjectLoadOnPageTag<User> {
    @Override
    protected User getLoadedObject() {
        return UserServiceFactory.getUserService().getCurrentUser();
    }
}
2. Googleログイン・ログアウトのaタグを生成するタグ
package guestbook.web.tags;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

/**
 aタグをHTMLで生成するカスタムタグの基底クラス。
*/
public abstract class WriteURLLinkTag extends TagSupport {
    /**生成するaタグのBODYに生成される文字列 */
    private String value;

    @Override
    public int doStartTag() throws JspException {
        HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
        UserService userService = UserServiceFactory.getUserService();
        String url = getURL(request, userService);
        JspWriter out = pageContext.getOut();
        try {
            out.write("<a href=\"" + url + "\">" + value + "</a>");
        } catch (IOException e) {
            throw new JspException(e);
        }
        return SKIP_BODY;
    }

    protected abstract String getURL(HttpServletRequest request, UserService userService);

    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

package guestbook.web.tags;
import javax.servlet.http.HttpServletRequest;
import com.google.appengine.api.users.UserService;

/** Googleログインのaタグを生成するカスタムタグ。 */
public class WriteLoginURLLinkTag extends WriteURLLinkTag {
    @Override
    protected String getURL(HttpServletRequest request, UserService userService) {
        return userService.createLoginURL(request.getRequestURI());
    }
}
package guestbook.web.tags;
import javax.servlet.http.HttpServletRequest;
import com.google.appengine.api.users.UserService;

/** Googleログアウトのaタグを生成するカスタムタグ。 */
public class WriteLogoutURLLinkTag extends WriteURLLinkTag {
    @Override
    protected String getURL(HttpServletRequest request, UserService userService) {
        return userService.createLogoutURL(request.getRequestURI());
    }
}
3. 上記カスタムタグのTLD(common.tld)
<?xml version="1.0"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlnsxsi="http://www.w3.org/2001/XMLSchema-instance"
    xsischemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"
    version="2.0">
  <tlib-version>2.0</tlib-version>
  <tag>
    <name>user</name>
    <tagclass>guestbook.web.tags.GoogleCurrentUserLoadTag</tagclass>
    <info>Load currentUser on page context</info>
    <bodycontent>empty</bodycontent>
    <attribute>
      <name>name</name>
      <required>true</required>
    </attribute>
  </tag>
  <tag>
    <name>service</name>
    <tagclass>guestbook.web.tags.GoogleUserServiceLoadTag</tagclass>
    <info>Load userService on page context</info>
    <bodycontent>empty</bodycontent>
    <attribute>
      <name>name</name>
      <required>true</required>
    </attribute>
  </tag>
  <tag>
    <name>login</name>
    <tagclass>guestbook.web.tags.WriteLoginURLLinkTag</tagclass>
    <info>Write link of login</info>
    <bodycontent>empty</bodycontent>
    <attribute>
      <name>value</name>
      <required>true</required>
    </attribute>
  </tag>
  <tag>
    <name>logout</name>
    <tagclass>guestbook.web.tags.WriteLogoutURLLinkTag</tagclass>
    <info>Write link of logout</info>
    <bodycontent>empty</bodycontent>
    <attribute>
      <name>value</name>
      <required>true</required>
    </attribute>
  </tag>
</taglib>
web.xmlのタグライブラリ登録部分
<jsp-config>
  <taglib>
  <taglib-uri>/el/google/common</taglib-uri>
  <taglib-location>/WEB-INF/tld/common.tld</taglib-location>
  </taglib>
</jsp-config>
4. カスタムタグを利用したJSP
<%@ page contentType="text/html;charset=UTF-8"language="java"  isELIgnored="false"%>
<%@ page import="com.google.appengine.api.users.UserServiceFactory" %>
<%@ page import="com.google.appengine.api.users.UserService" %>
<%@ page import="com.google.appengine.api.users.User" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="/el/google/common" prefix="common" %>

<html>
<head>
<title>zetta1985 sample</title>
</head>
<body>
  <common:service name="service"/>
  <c:if test="${service.currentUser != null}" var="signIn"/>
  <c:if test="${signIn}">
  <p>Hello! ${service.currentUser.nickname} (<common:logout value="SignOut"/>)</p>
  </c:if>
  <c:if test="${!signIn}">
  <p>Hello! Please <common:login value="SignIn"/></p>
  </c:if>

とりあえず、JSPは需要があるかないかは別として、思った通りに使えそうです。

個人で手軽にWebサーバを持てるってのは、凄く便利ですし、色々な利用方法があると思いますが

僕はGoogleAppEngineは教育に使えそう、という印象を持ちました。

これからは、とりあえずGWTいじって、Wicket-extいじって~といった感じで勉強したいと思います。

あ、Scalaが動くかも試してみたいですねー。

mixiアプリとか作って公開する、ってのもやってみたいし、夢が広がりんぐ。

このエントリーをはてなブックマークに追加
comments powered by Disqus