開発日誌2000年11月

SJIS 環境で PostgreSQL の JDBC ドライバを使う (2000/11/01)

 前回、フロントエンドのエンコーディングとして SJIS が使えるということ、README.mb.jp に見るべし、ということを書きましたが、README.mb.jp が見つからないというメールも頂きましたので、少々補足しておきたいと思います。

 まず、README.mb.jp は、ソースアーカイブを Get すれば、必ず入っているはずです。バイナリパッケージを入れている場合、パッケージングによって入っていない場合もあるかもしれません。でも、それはそのパッケージングの問題です。ソースパッケージの SPEC を修正してリビルドしましょう。

 では、本題です。PostgreSQL を Linux 上で動かし、データベースのエンコーディング EUC_JP で作成されているとします。このデータベースに Windows 環境から JDBC で接続する場合にどうすればよいか?です。

        try
        {
            Class.forName("org.postgresql.Driver");
            Connection conn = DriverManager.getConnection(
                            "jdbc:postgresql://host_name/database_name","user","password");
            Statement st = conn.createStatement();
            st.execute("set client_encoding to 'sjis'");
            ResultSet rs = st.executeQuery("select * from test");
            while (rs.next())
            {
                System.out.println(rs.getString("data"));
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

とやってやれば、SJIS でエンコーディングされます。データベースが、UNICODE だとダメです。「エンコーディングできない」とエラーが表示されます。蛇足ですが、クライアント側の PGCLIENTENCODING 環境変数は JDBC ドライバには関係しません。この環境変数は、libpq を使うアプリケーションに関係があるものです。例えば、psql は libpq を使います。

 どうしても Oracle と比較してしまうのですが、Oracle の JDBC ドライバは、特別意識しなくともエンコーディングしてくれるんですよね。NLS_LANG という環境変数によって意識的に制御することもできます。スマートですよね。

 以上、補足でした。と偉そうに書いてますが、当初、私もこのエンコーディングの仕組みを知らずに、自前で変換しておりました。(爆) PostgreSQL 6.5 あたりの JDBC ドライバは、こういう仕組みがなかった?のか、日本語対応させたドライバがあったようです。そういう情報を見てましたんで、てっきり 7.0 でも状況は同じなのかと思い込んでいたのです。皆さん、ドキュメントはちゃんと読みましょう。

Web Application の開発環境 (2000/11/03)

 Forte for Java Internet Edition Beta を使ってみましたが、内部の HTTP サーバーが日本語をうまく処理してくれないので断念しました。Forte for Java Community Edition ならば問題ありません。残念です。正式リリースに期待するしかありませんが、Internet Edition は有料になるかもしれないですね。

 結局、選択肢としては Forte for Java Community Edition か、Visual Age for Java 3.5 のどちらかです。ただ、Visual Age for Java は Linux で動くバージョンが 3.0 までしかないようです。3.0 だと Java2 対応じゃないんで、Forte for Java しかありませんね。JBuilder 3.5 を忘れてるじゃないかと言われそうですが、現バージョンの JSP のサポートが古いんで使い物になりません。

 Visual Age for Java は、IDE 内で Tomcat 環境が動くというのが魅力です。「実行環境=開発環境」となりますからわかりやすいし、問題も発生しにくいでしょう。ただ、Windows でしか開発できないのことが問題です。一方、Forte for Java は、Windows でも Linux でも動きます。また、JSP の開発環境が整ってます。

 どうやれば、うまく開発できるんでしょう???

補足(2000/11/06):Forte for Java Internet Edition で日本語をうまく処理してくれない問題は、どうやら JSP のコンパイル時の問題のようです。HTTP サーバーは問題なく日本語を処理できてました。

JBuilder Professional の次期バージョンは、まともな JSP/Servlet 開発環境があるようです。JBuilder は、Windows,Linux,Solaris に対応していますから有力な選択肢になりますね。

補足(2000/11/07):Forte for Java Internet Edition で日本語をうまく処理してくれない問題ですが、JSP のコンパイルじゃないです。出力されたソースは UTF8 で出力されてました。ところが、ブラウザに送られてくるデータは正しくエンコーディングされていないようです。例えば、JSP で contentType=”text/html; charset=EUC-JP” を指定した場合、JSP/Servlet 内部では UTF8 で扱われ、ブラウザに送る際に EUC-JP で送り出すはずなのですけど、どうやらこれがうまくいっていないようです。ちなみに、Tomcat でやってやると、うまくいくようです。

Web Application 開発環境の構築方法 (2000/11/08)

 私の構築した開発環境を紹介します。プラットフォームは、TurboLinux 6.0 です。

Sun Java2 Platform Standard Edition Version 1.3

 Sun の JDK 1.3 は、rpm パッケージは、ここにあります。/usr/java/jdk1.3 にインストールされます。

Tomcat 3.1

 Tomcat 3.1 の rpm パッケージは、ここにあります。Tomcat とともに Ant もインストールしました。/opt/tomcat, /opt/ant にインストールされます。

JOnAS 2.1

 JOnAS の tarball は、ここにあります。Tomcat にあわせて、/opt/jonas に展開しました。

PostgreSQL 7.02

 PostgreSQL の tarball は、RingServer にあります。PostgreSQL には rpm パッケージが用意されてます。PostgreSQL-JP には、日本 PostgreSQL ユーザー会の成果が登録されており、Patch が提供されています。私は、オリジナルの rpm パッケージに手を加えてインストールしました。

開発用環境変数の設定

 JDK,Tomcat,JOnAS 用の環境変数を設定します。.bash_profile に記述しておけばよいでしょう。

#JDK 1.3 Environment
JAVA_HOME=/usr/java/jdk1.3
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH

#Tomcat,Ant Environment
TOMCAT_HOME=/opt/tomcat
ANT_HOME=/opt/ant
CLASSPATH=$CLASSPATH:$TOMCAT_HOME/lib/servlet.jar
PATH=$PATH:$TOMCAT_HOME/bin:$ANT_HOME/bin
export TOMCAT_HOME ANT_HOME PATH CLASSPATH

#JOnAS Enrivonment
JONAS_ROOT=/opt/jonas
PATH=$JONAS_ROOT/bin/unix:$PATH
CLASSPATH=$CLASSPATH:~/classes
if [ -f $JONAS_ROOT/bin/unix/config_env ]; then
    .$JONAS_ROOT/bin/unix/config_env
fi
export JONAS_ROOT PATH CLASSPATH

開発用ディレクトリ作成

 ホームディレクトリ以下に、開発用ディレクトリを作成します。また、ホームディレクトリに、$JONAS_ROOT/examples/config.mk と $JONAS_ROOT/examples/stdrules.mk をコピーします。

~/
 |- bin/       : 各種開発用スクリプト用
 |- classes/   : EJB クラス格納用
 |- lib/       : 各種ライブラリ(JAR)用
 |- schema/    : データベース DDL スクリプト等
 |- src/       :
 |     |- ejb/ : EJB 作成用
 |     +- web/ : Web コンポーネント作成用
 |- tmp/       : テンポラリ
 |- config.mk
 +- stdrulse.mk

開発方法

 まずは、EJB の開発方法です。わかりやすくするために sb パッケージの test という Session Bean を作成することにします。

 ディレクトリ ~/src/ejb/sb を作成します。作成したディレクトリに移り、newbean とするとテンプレート作成用のスクリプトが起動します。

Choose the bean name, starting with a capital letter.
Avoid the reserved names : Home, EJB, Session, Entity.
bean name : \c
sb
Type of bean ?
ec = Entity CMP
eb = Entity BMP
sl = Session Stateless
sf = Session StateFul
Your choice: \c
sf
Enter the dot separated package name, usually matching
the current directory, where the beans will be compiled.
Package Name: (dot separated name: x.y.z) \c
sb
Creating bean test (type sf) in package sb
Your bean files have been created. You can now customize them.

 以上で、Session Bean の Java ソースとともに、必要な設定ファイル類と test.mk という Makefile が生成されているはずです。test.mk を修正します。config.mk,stdrules.mk と classes の在り処を指す相対パスを修正する必要があるからです。

ROOT = ../../..

としてやり、make -f test.mk とやれば、何もしない Session Bean が ~/classes に作成されます。とりあえず、JOnAS を起動して作成した EJB をロードしてみましょう。

# registry 12340
Jeremie Registry started

と、RMI Registry Server を起動した上で、~/src/ejb/sb をカレントにして EJBServer を起動します。

# EJBServer
JOnAS Server, version 2.1.1, running on Jeremie.
Mapping datasource jdbc:postgresql://localhost/jonas on jdbc_1
EJBHome:sb.test.JOnASaccountHome for test available
EJBServer is ready

とロードされればOKです。

 次は、Web コンポーネント側の開発方法です。Tomcat の Servlet のテストとともに、先ほど作った EJB を呼び出すテストも兼ねることにします。ここでは、テスト用に callsb パッケージの testServlet を作成します。

 まず、Web コンポーネントを配置するためのディレクトリを作成します。~/ServletTest をベースに以下のように作成してください。

~/
 +- ServletTest/
     +- WEB-INF/
         +- classes 

 次に、ディレクトリ ~/src/web/sb を作成します。作成したディレクトリに移り、サーブレットを作成します。doGet メソッドに 先に作成した Session Bean の method1() を呼び出すように実装します。method1() は、テンプレートとして含まれている空のメソッドですので、先程の作業のみで、何もしなくても存在してます。呼び出されたことがよくわかるように、method1() に System.out.println(“called method1”); 等を記述しておいてもよいでしょう。なお、サーブレットの作り方までは言及しません。呼び出しシーケンスのみ説明します。

package callsb;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.transaction.UserTransaction;
import javax.rmi.PortableRemoteObject;
import sb.*;

public class testServlet extends HttpServlet {

・・・略・・・

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
                         throws ServletException, java.io.IOException
    {
         response.setContentType("text/html; charset=ISO-2022-JP");
        java.io.PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");  
        out.println("<title>Servlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("サーブレットです");
        out.println("</body>");
        out.println("</html>");
        out.close();

        System.out.println("Start");

        Context initialContext = null;

        try
        {
                initialContext = new InitialContext();
        }
        catch (Exception e)
        {
                System.out.println("InitialContext Error.");
                e.printStackTrace();
        }

        accountHome home = null;

        try
        {
                home = (accountHome)PortableRemoteObject.narrow(
                           initialContext.lookup("accountHome"),accountHome.class);
        }
        catch (Exception e)
        {
                System.out.println("PortableRemotObject.narrow Error.");
                e.printStackTrace();
        }

        account t = null;

        try
        {
                t = home.create();
        }
        catch (Exception e)
        {
                System.out.println("homt.create Error.");
                e.printStackTrace();
        }

        try
        {
                t.method1();
        }
        catch (Exception e)
        {
                System.out.println("method1 Error.");
                e.printStackTrace();
        }

        try
        {
                t.remove();
        }
        catch (Exception e)
        {
                System.out.println("remove Error.");
                e.printStackTrace();
        }

        System.out.println("End");

   }

 作成したサーブレットをコンパイルします。~/ServletTest/WEB-INF/classes/callsb を作成し、そこへコンパイルしたクラスをコピーします。

 ~/src/web に web.xml を作成します。ここでは、最低限必要な設定のみ言及します。一応テンプレートとして、$TOMCAT_HOME/doc/appdev/web.xml.txt (あるいは、/usr/doc/tomcat.3.1/appdev/web.xml.txt)が参考になると思います。フルセットの記述方法は仕様書にあたるしかありませんが、先日紹介した、Forte for Java Internet Edition Beta では、IDE 上で web.xml を記述できるようです。ただ、バグがあるようでよく落ちるんですけど。。

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>
    <servlet>
      <servlet-name>test</servlet-name>
      <servlet-class>callsb.testServlet</servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>test</servlet-name>
      <url-pattern>/test</url-pattern>
    </servlet-mapping>
</web-app>

 作成した web.xml を ~/ServletTest/WEB-INF にコピーします。

 最後に、サーブレットを呼び出す index.html を ~/src/web に作成します。

<html>
<head><title>Test</title></head>
<body>

<FORM action="test">
<INPUT type="submit" value="Call">
</FORM>
</body>
</html>

 作成した index.xml を ~/ServletTest にコピーします。

 Servlet のクラスファイルや、web.xml, HTML を ~/src/web から、いちいち ~/ServletTest にコピーしなければならないのは面倒です。そこで登場するのが Ant です。Ant は、Java 版 Makefile のようなものです。私は、~/src/web/build.xml を作成して、面倒な手順を自動化してます。make でもかまわないですが、一応 Tomcat 流に挑戦してます。(笑) 実際、使ってみると、なかなか便利です。build.xml の書き方等は、$TOMCAT_HOME/example あたりにあるものを参考にすればいいです。

 では、最後に Tomcat 側の設定です。まず、簡単に実行させるために、$TOMCAT_HOME/webapps に ~/ServletTest のリンクを作成します。そして、$TOMCAT_HOME/conf/server.xml にリンクしたディレクトリを追加します。

<Context path="/ServletTest" docBase="webapps/ServletTest" debug="1" reloadable="true">
</Context>

 以上で実行準備はできました。tomcat start して、

Context log: path="/ServletTest" Adding context path="/ServletTest"  docBase="/opt/tomcat/webapps/ServletTest"

と表示され、コンテキストが追加されていればOKです。

 ブラウザから、http://localhost:8080/ServletTest/index.html にアクセスすると、ボタンが表示されるはずです。ボタンをクリックするとサーブレットが呼び出されます。

 以上、駆け足に開発環境の構築方法と、実際の開発手法について説明しました。巷には、インストールや動作確認についての情報は溢れているのですが、「実際にどうやって開発するんだ?」という具体的記述は、あまり見かけません。今回紹介した方法も私個人のやり方ですから、「こうやらなければいけない」というような代物ではありません。あくまでも参考にしかなりませんけど、ひとつの足がかりなればと思います。

J2EE Blueprints 日本語版 (2000/11/30)

 J2EE Blueprints の日本語版がリリースされてます。このドキュメントは、J2EE アプリケーション開発のバイブルです。これで、翻訳ソフを駆使して読む苦労はなくなりました。(笑) JDCのサイトから辿って手に入れることができます。

タイトルとURLをコピーしました