Web Performer のビルド時に不要なライブラリやファイルを削除する

こんにちは。エヌデーデーの関口です。
Web Performer で拡張開発を行っている時に、自動生成(ビルド)の際には必要となるライブラリが、Tomcatなどのアプリケーションサーバーの共有ライブラリとして登録されている場合、warファイルを肥大化させたくないので、取り除いておきたいといったニーズがあると思います。

すぐに思いつく方法としては、バッチコマンドを作成して、その中で ant 実行 → 不要ファイル削除 という処理を書くなどでしょうか。
今回は、もう少しスマートに Web Performer の自動生成ボタンを押した場合も同様の処理を行う方法をご紹介します。

想定される読者

  • Web Performerは導入済み
  • Web Performerで拡張機能開発を行っている
  • アプリケーションデプロイに課題を持っている

ケーススタディ

それでは、具体的にどのようなケースの時に、今回の対応を行うのか見てみましょう。

アプリケーションサーバーの構成

Web Performer で作成したアプリケーションが、Tomcat 上で稼働しており、データベースには Oralce を利用し、データソース接続を行うようになっているとします。以下にアプリケーション APP1, APP2 をデプロイしている Tomcat のフォルダ構成例を示します。

$CATALINA_HOME/
 ├ bin/
 ├ conf/
 ├ lib/
 │  ├ {ライブラリいろいろ}.jar
 │  └ ojdbc8-*.jar    --- データソース接続で利用する Oracle JDBC ドライバ
 ├ logs/
 ├ temp/
 ├ webapps/
 │  ├ APP1/           ---  アプリケーションAPP1のルートフォルダ
 │  │  ├ {フォルダいろいろ}/
 │  │  └ WEB-INF/
 │  │     ├ classes/  ---  実行クラスファイルのフォルダ
 │  │     ├ {フォルダいろいろ}/
 │  │     └ lib/      ---  実行時に使用するライブラリのフォルダ
 │  └ APP2/           ---  アプリケーションAPP2のルートフォルダ
 │     ├ {フォルダいろいろ}/
 │     └ WEB-INF/
 │        ├ classes/  ---  実行クラスファイルのフォルダ
 │        ├ {フォルダいろいろ}/
 │        └ lib/      ---  実行時に使用するライブラリのフォルダ
 └ work/

APP1, APP2 ともに Oracle への接続は、Tomcat に設定したデータソースを利用するため、Tomcat のライブラリフォルダ $CATALINA_HOME/lib に Oracle の JDBC ドライバが配置されており、アプリケーションでライブラリを共有する想定とします。

Web Performer の拡張機能の概要

さてこのような環境で、Web Performer で作成したアプリケーション APP1 の処理の一部で、Oracle のストアドプロシージャを呼び出し、その戻り値としてカーソル型を受け取りつつ、その結果を使ってさらに別の処理も実行するというケースを想定してください。

Web Performer の標準機能である、CALLPROCEDURE を使ってビジネスプロセスのみで実装することも出来ますが、今回は次に示すような Java プログラムで実装しなければならないケースを想定してください。

package sample;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import jp.co.canon_soft.wp.runtime.AppRuntimeException;
import jp.co.canon_soft.wp.runtime.bp.BpContext;
import jp.co.canon_soft.wp.runtime.bp.BusinessProcess;
import jp.co.canon_soft.wp.runtime.dm.DmBroker;
import jp.co.canon_soft.wp.runtime.dm.DmBrokerFactory;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;

public class SampleBp implements BusinessProcess {

    public List execute(BpContext context) {
        List result = new ArrayList();
        CallableStatement stmt = null;
        DmBroker broker = DmBrokerFactory.getBroker(context.getTransaction());
        try {
            Connection con = broker.getConnection();
            // ストアドプロシージャ PKG.PROC の呼び出し
            // 戻り値は REF CURSOR 型
            stmt = con.prepareCall("{call PKG.PROC(?, ?)}", 
                    ResultSet.TYPE_FORWARD_ONLY,
                    ResultSet.CONCUR_READ_ONLY);

            // 戻り値、引数の設定
            stmt.registerOutParameter("OUT_PARAM", OracleTypes.CURSOR); // REF CURSOR 型であることを定義
            stmt.setString("IN_PARAM", (String) context.getArg("@1"));
            stmt.executeUpdate();

            // 戻り値を取得
            ResultSet rs = ((OracleCallableStatement)stmt).getCursor(1);
            while (rs.next()) {
                // 何かいろいろと処理する
            }

            return result;
        } catch (SQLException e) {
            throw new AppRuntimeException("select error", e);
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e1) {
                    // do something
                }
            }
            broker.close();
        }
    }
}

このプログラムで肝心な部分は、33行目や38行目で利用しているクラスが、Oracle JDBC 独特のクラスであるということです。

そのため、Web Performer の自動生成時には、Oracle JDBC ライブラリをアプリケーションに含めておく必要があります。仮に含めなかった場合、以下に示すようにエラーとなって自動生成が中止されてしまいます。(当然と言えば当然ですが)

対応としては次に示す図のように、拡張ディレクトリの WEB-INF/lib 以下に拡張Javaプログラムのコンパイルに必要なライブラリ(今回であれば ojdbc8-*.jar )を配置しておけば自動生成が出来るようになります。

そして、自動生成後のアプリケーションのフォルダ構成(概略)は次のようになります。

APP1/
 ├ {フォルダいろいろ}/
 └ WEB-INF/
    ├ classes/
    ├ {フォルダいろいろ}/
    └ lib/
       ├ {ライブラリいろいろ}.jar
       └ ojdbc8-*.jar  ---  拡張ディレクトリに配置したライブラリのコピー

問題点

実際のところ自動生成されたアプリケーションは、Tomcat 上にデプロイされた後、問題なく動作するので、実行については問題ありません。

問題があるならば、Tomcat のライブラリフォルダに既に拡張ディレクトリに配置したライブラリが登録されているため、同じライブラリを二重管理しなければならないという点でしょう。

まあ、動いているのだから問題ないじゃないかという方もいらっしゃるかと思いますが、この後、アプリケーションを war ファイルとしてまとめる作業などを考えると無駄なライブラリは取り除いておきたいですよね。

解決策

これまで述べたケーススタディで、問題点まで把握できたかと思います。

それでは、ここから今回のケーススタディで問題となっている 自動生成の後に無駄なライブラリを削除する という解決策をご紹介します。

注意点

これから示す方法は、Web Performer V2系統(~2.4)の全てで利用可能ですが、Web Performer のバージョンを上げてアプリケーションを自動生成し直す場合は、以下に示す手順をはじめからやり直してください。

まずは今まで通り自動生成

まずは、拡張ディレクトリの WEB-INF/lib に Java のコンパイルに必要となるライブラリを含めた状態で、一度コンパイルを行ってください。
そうすると、自動生成先の {アプリケーションルート}/WEB-INF 以下に build_base.xml というファイルが出来ているので、それを拡張ディレクトリの WEB-INF の下にコピーしてください。
APP1 というアプリケーションであれば、src/JavaWebApp/APP1/WEB-INF です。

ビルドファイルを編集する

コピーした build_base.xml を開いて編集します。次に示すように、post_build というAntターゲットが定義されているので、この内容を編集します。

<?xml version="1.0" encoding="Shift_JIS"?>

<project>
    ・・・・・
    <!-- ================================================================== -->
    <!-- ビルド後処理(ダミー)                                               -->
    <!-- ================================================================== -->
    <target name="post_build"/>
    ・・・・・
</project>

編集後は次のようになります。

<?xml version="1.0" encoding="Shift_JIS"?>

<project>
    ・・・・・
    <!-- ================================================================== -->
    <!-- ビルド後処理(ダミー)                                               -->
    <!-- ================================================================== -->
    <target name="post_build">
        <delete>
            <fileset dir="${lib.dir}" includes="ojdbc8*.jar"/>
        </delete>
    </target>
    ・・・・・
</project>

9行目から Ant の Delete タスク(ファイルやフォルダの削除命令)を追加して、不要なファイルを削除するようにしています。
不要なファイルが複数ある場合は、<fileset> を繰り返してください。
ちなみに、${lib.dir} はアプリケーションフォルダの WEB-INF/lib を示すようになっています。

再び自動生成する

これだけです。
この状態で、Web Performer のエディタから自動生成してみてください。自動生成後のアプリケーションフォルダから、不要なライブラリが削除されているのが確認出来ると思います。

まとめ

これまで、warファイル作成の度にアプリケーションサーバーに既にあるjarファイルをアプリケーションフォルダから削除しなければならず、そのためだけにバッチファイルをつくるという人もいたのではないでしょうか。

このように、以外と簡単に、かつ Web Performer が標準で使用しているファイルの編集のみで対応が出来るということが理解出来たかと思います。

また、今回紹介した post_build のターゲットは、ファイルの削除以外にも Ant で使用できる他のタスクを追加することできるので、アプリケーションを自動生成した後処理を自由に行うことが出来ます。

意外と簡単に、かつ Web Performer が標準で生成するファイルだけで対応が完結するので、オススメです。