Hatena::ブログ(Diary)

あさとの @drillbits このページをアンテナに追加 RSSフィード

2009/12/11

Google AppEngine/Java + slim3 でフィード生成したときのメモ

以前は「Struts の Action を書くだけの簡単なお仕事」しかしてなかったので色々と鬼門が多い…
最近は AppEngine + Slim3 で細々と Web アプリを組んでるんだけど、HttpServlet を継承したクラスなんて書いたことないお…といった感じでハマってます。

というわけで色々試したり調べたりアドバイスをいただいて書いたことをメモ。
今日は AppEngine で BigTable にストアしたデータからフィードを生成して出力しました。

まず、通常のサーブレットであればこんな感じ(jdom使ってます

import java.io.IOException;
import java.io.Writer;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

public class FeedServlet extends HttpServlet throws IOException {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("application/xml; charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");

        // てきとーなRSS
        Document doc = new Document();
        Element root = new Element("rss");
        doc.setRootElement(root);
        root.setAttribute("version", "2.0");
        Element channel = new Element("channel");
        root.addContent(channel);
        channel.addContent(new Element("title").setText("たいとる"));
        channel.addContent(new Element("link").setText("りんく"));
        channel.addContent(new Element("description").setText("ですくりぷしょん"));
        // BigTable から取得したのをくっつけたいときは…
        FooService service = new FooService();
        List<Foo> list = service.getAll();
        for (Foo foo : list) {
            channel.addContent(new Element("foo").setText(foo.getName()));
        }
        // とか

        Writer writer = resp.getWriter();
        Format format = Format.getPrettyFormat();
        format.setEncoding("UTF-8");
        XMLOutputter outputter = new XMLOutputter(format);
        outputter.output(doc, writer);
    }
}

で、Slim3 の場合はこんな感じ。

import java.io.IOException;
import java.io.Writer;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.util.ThrowableUtil;

public class FeedController extends Controller {

    @Override
    public Navigation run() {
        response.setContentType("application/xml; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");

        // てきとーなRSS
        Document doc = new Document();
        Element root = new Element("rss");
        doc.setRootElement(root);
        root.setAttribute("version", "2.0");
        Element channel = new Element("channel");
        root.addContent(channel);
        channel.addContent(new Element("title").setText("たいとる"));
        channel.addContent(new Element("link").setText("りんく"));
        channel.addContent(new Element("description").setText("ですくりぷしょん"));
        // BigTable から取得したのをくっつけたいときは…
        FooService service = new FooService();
        List<Foo> list = service.getAll();
        for (Foo foo : list) {
            channel.addContent(new Element("foo").setText(foo.getName()));
        }
        // とか

        try {
            Writer writer = response.getWriter();
            Format format = Format.getPrettyFormat();
            format.setEncoding("UTF-8");
            XMLOutputter outputter = new XMLOutputter(format);
            outputter.output(doc, writer);

        } catch (IOException e) {
            ThrowableUtil.wrapAndThrow(e);
        }

        return null;
    }
}

通常のサーブレットとほとんど同じだけど、最後に return null する。
いつもの調子で redirect(path) とか forword(path) とかすると java.lang.IllegalStateException って警告がでる(フィード自体は吐かれるけど)
Slim3 は cron で実行するやつも return null しないと、それが TaskQueue とかだとすごい Retry 数になるよ!

御礼

Twitter@2tommy さん@shin1ogawa さんにアドバイス頂きました。ありがとうございます。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証