Japan Akihito Fujii's Weblog 日々是新 Akihito Fujii's Weblog

金曜日 8 12, 2005

English Translation: (Google) / (Yahoo!)

JavaのWeb Applicationとして、RSS/Atom Feedを作成するプログラムを作成してみましょう。J2EE web applicationの開発に精通した方には、今回の内容はあまり有益ではないかも知れませんが、「RSS/Atom FeedってどうWebから生成すればいいのだろう」と漠然と考えている方にはお勧めです。Javaのツールを使って簡単に実現することができます。今回 はJava.netのRome Projectが提供しているFeed Syndication APIとそのsample codeをそのまま利用します。
RomeのFeed Syndication APIを利用することで、様々なFeed Formatに非常に簡単に対応することが可能です。もちろん、JavaのAPIですから既存のJ2EE web applicationにも直ぐに適用することができます。JDK だけで開発するのも可能ですが、今回は今後のことも考えて、最新のJava統合開発環境のNetBeans 4.1 日本語版と、J2EE 1.4の実行環境であるApplication Server 8.1 PEを利用します。
こんな簡単なことをするのに、なぜ統合開発環境とApp serverをと思われるかもしれませんが、ビルドや配備作業、デバッグ、プロファイリング、HTTPモニタ機能など、現実の開発に必要なツールが多数含 まれているためです。(今後好評ならこれを発展させて行きたいので・・・)

準備
  • Rome プロジェクトの サ イトからバイナリをダウンロード、解凍し、rome-0.6.jarを取り出します。Romeは、JDOMを利用しているため、JDOMのサイトからJDOM 1.0のバイナリをダウンロード、解凍し、jdom.jarを取り出します。
  • 今回は無料で利用できるJava開発ツールと、J2EE Application Serverを利用するため、NetBeansとSun Java System Application Server 8.1 Platform Editionをインストールします。NetBeans, SJS Appliction Server 8.1 PEは、NetBeans.orgからダウンロードが可能です。NetBeans.orgのダウンロードページからNetBeans IDE 4.1 with J2EE Application Server 8.1 PE bundleを選んでください。バイナリをダウン ロード後、インストールしてください。インストールしたApplication Server 8.1 PEは、NetBeansを起動し、左側パネルの「実行時」タグをクリックし実行時ペインを開き、サーバを右クリックし、「サーバを追加」を選択してくだ さい。ウィザードが起動し、指示に従い情報を入力することで追加することが出来ます。
サーバの追加 App server 8.1の追加

 アプリケーションの開発
  •  NetBeansを起動し、新規プロジェクトを作成してください。ここではFeedApplication1としてWebアプリ ケーションのプロジェクトを作成します。
(各スナップショットは、画像のみを表示することで拡大できます。)
プロジェクトの作成 プロジェクトの作成

  • プロジェクトタグのFeedApplication1を右クリックし、新規からJavaパッケージを選択し、このアプリケーションの package名を指 定します。ここでは、jp.co.sun.feedとしています。
ライブラリの追加 

  • プロジェクトタグのライブラリを右クリックし、「JAR/フォルダを追加」を選び、rome-0.6.jarとjdom.jarをそれぞれ追 加してください。

ライブラリの追加

  • プロジェクトタグのFeedApplication1を右クリックし、新規からサーブレットを選択し、新しく SampleFeedServletを作成します。サーブレットのパッケージ名は、先ほど作成したjp.co.sun.feedが選択可能になっていま す。<コンテキスト>/<URLマッピング名>でSampleFeedServletが呼び出されるよう、URLマッピングを /feedとします。

SampleFeedServlet servlet mapping

  • 作成したSampleFeedServletのコードを追加します。このコードはRome プロジェクトのサンプルコードを修正して利用しています。(コードの詳細はまた別の機会にでも紹介することにします。)Feedが英語のままだとつまらな いので、記述は日本語に変更しています。
/*
 * SampleFeedServlet.java
 * Most of codes are copyed from rome-sample-06 FeedServlet.java
 * Please refer to rome-sample-06 which is available on http://wiki.java.net/bin/view/Javawsxml/Rome
 * Created on 2005/08/11, 16:51, Akihito Fujii
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package jp.co.sun.feed;

import java.io.*;
import java.net.*;

import javax.servlet.*;
import javax.servlet.http.*;
import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedOutput;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author akihito
 * @version
 */
public class SampleFeedServlet extends HttpServlet {

    private static final String DEFAULT_FEED_TYPE = "default.feed.type";
    private static final String FEED_TYPE = "type";
    private static final String MIME_TYPE = "application/xml; charset=UTF-8";
    private static final String COULD_NOT_GENERATE_FEED_ERROR = "Could not generate feed";

    private static final String DATE_FORMAT = "yyyy-MM-dd";

    private String _defaultFeedType;
   
    public void init() {
        _defaultFeedType = getServletConfig().getInitParameter(DEFAULT_FEED_TYPE);
        _defaultFeedType = (_defaultFeedType!=null) ? _defaultFeedType : "atom_0.3";
    }
   
    /** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

        DateFormat dateParser = new SimpleDateFormat(DATE_FORMAT);

        SyndFeed feed = new SyndFeedImpl();

        feed.setTitle("Sample Feed (created with Rome)");
        feed.setLink("http://rome.dev.java.net");
        feed.setDescription("このフィードはRome(Java syndication utilities)を利用して生成されています。");

        List entries = new ArrayList();
        SyndEntry entry;
        SyndContent description;

        entry = new SyndEntryImpl();
        entry.setTitle("Rome v0.1");
        entry.setLink("http://wiki.java.net/bin/view/Javawsxml/Rome01");
        try {
            entry.setPublishedDate(dateParser.parse("2004-06-08"));
        }
        catch (ParseException ex) {
            // IT CANNOT HAPPEN WITH THIS SAMPLE
        }
        description = new SyndContentImpl();
        description.setType("text/plain");
        description.setValue("Romeの初期リリースです。");
        entry.setDescription(description);
        entries.add(entry);

        entry = new SyndEntryImpl();
        entry.setTitle("Rome v0.2");
        entry.setLink("http://wiki.java.net/bin/view/Javawsxml/Rome02");
        try {
            entry.setPublishedDate(dateParser.parse("2004-06-16"));
        }
        catch (ParseException ex) {
            // IT CANNOT HAPPEN WITH THIS SAMPLE
        }
        description = new SyndContentImpl();
        description.setType("text/plain");
        description.setValue("バグ修正、APIのマイナーチェンジ、数件の新機能の追加。"+
                             "<p>詳細は <a href=\"http://wiki.java.net/bin/view/Javawsxml/RomeChangesLog#RomeV02\">Changes Log for 0.2</a>を参照してください</p>");
        entry.setDescription(description);
        entries.add(entry);

        entry = new SyndEntryImpl();
        entry.setTitle("Rome v0.3");
        entry.setLink("http://wiki.java.net/bin/view/Javawsxml/Rome03");
        try {
            entry.setPublishedDate(dateParser.parse("2004-07-27"));
        }
        catch (ParseException ex) {
            // IT CANNOT HAPPEN WITH THIS SAMPLE
        }
        description = new SyndContentImpl();
        description.setType("text/html");
        description.setValue("<p>バグ修正、APIの変更、数件の新機能追加、ユニットテストの実施</p> "+
                             "<p>詳細は<a href=\"http://wiki.java.net/bin/view/Javawsxml/RomeChangesLog#RomeV03\">Changes Log for 0.3</a>を参照してください。</p>");
        entry.setDescription(description);
        entries.add(entry);

        entry = new SyndEntryImpl();
        entry.setTitle("Rome v0.4");
        entry.setLink("http://wiki.java.net/bin/view/Javawsxml/Rome04");
        try {
            entry.setPublishedDate(dateParser.parse("2004-09-24"));
        }
        catch (ParseException ex) {
            // IT CANNOT HAPPEN WITH THIS SAMPLE
        }
        description = new SyndContentImpl();
        description.setType("text/html");
        description.setValue("<p>バグ修正、APIの変更、数件の新機能追加、ユニットテストの実施終了< /p>"+
                             "<p>詳細は<a href=\"http://wiki.java.net/bin/view/Javawsxml/RomeChangesLog#RomeV04\">Changes Log for 0.4</a>を参照してください。</p>");
        entry.setDescription(description);
        entries.add(entry);

        feed.setEntries(entries);

       
        try {
           
            String feedType = request.getParameter(FEED_TYPE);
            System.out.println("FeedType:"+ feedType);
            feedType = (feedType!=null) ? feedType : _defaultFeedType;
            feed.setFeedType(feedType);

            response.setContentType(MIME_TYPE);
            SyndFeedOutput output = new SyndFeedOutput();
            output.output(feed,response.getWriter());
        }
        catch (FeedException ex) {
            String msg = COULD_NOT_GENERATE_FEED_ERROR;
            log(msg,ex);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,msg);
        }
       
    }
   
    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
   
    /** Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }
   
    /** Returns a short description of the servlet.
     */
    public String getServletInfo() {
        return "Short description";
    }
    // </editor-fold>
}


  • 作成されているindex.jspを編集します。
    (省略)
  <body>

    <h1>Feed JSP Page</h1>
    <BR><A HREF="./feed">FeedServlet パラメータなし</A><BR>
    <BR><A HREF="./feed?type=atom_0.3">FeedServlet Atom</A><BR>
    <BR><A HREF="./feed?type=rss_1.0">FeedServlet RSS 1.0</A><BR>
    <BR><A HREF="./feed?type=rss_2.0">FeedServlet RSS 2.0</A><BR>
   
    <%--(以下省略)

  • Webアプリケーションの配備記述子に、デフォルトのFeedタイプをを指定するための初期パラメータを追加します。
初期パラメータ

アプリケーションの実行
  • 実行ボタンを押し、アプリケーションをコンパイル、パッケージング、配備し、実行します。ブラウザが起動され、index.jspが表示され ます。それぞれのリンクをクリックすることにより、1つのサーブレットから異なるフォーマットのFeedが生成されます。以下はAtom, RSS 1.0, RSS 2.0の実行例です。
実行画面 Atom Feed RSS 1.0 RSS 2.0

最後に

このサンプルアプリケーションでは、初回ということで、Feedの情報をServletのコード内で作成していますが、情報をDBから取得したり、動的に生成したり、または、ユーザによってJ2EEの機能を活用した認証や、Feedのパーソナライズしたりすることにより、様々なことが可能になります。(LDAPと連携してここのIdentity情報をベースにしたPersonalized Feedなども実現できますね。)またJ2EE Application Server上で構築することは、このアプリの可用性向上や、負荷分散機能の実現が容易なことをも意味します。
この記事が好評なようであれば・・・、次の機会にこれらに挑戦してみたいと思います。(NetBeansのMobility Packを利用して、MIDPのRSS Readerと連携するってもも個人的には興味がありますが・・・)

Rome Projectのメンバーに感謝。
投稿されたコメント:

cool

Posted by wow gold on 11月月 03日, 2008年 at 10:42 午前 JST #

コメント
コメントは無効になっています。