Struts1 [例外処理]

struts ではエラーはとにかく例外となります。例外をキャッチするメカニズムも デフォルトの処理も既に実装済みなので、ユーザーはせいぜいオリジナルの処理を 追加設定するだけです。前回のサンプル(bbs02.war) をベースに、実装してゆきます。bbs03 として使います。今回のサンプル(bbs03.war)
更新日 2016-02-13

とりあえずデフォルトの例外処理を確認する。

運良く今まで例外発生を見た事がないのなら、一度見ておくのも悪くないでしょう。もちろん 見てて気持ちのいい画面ではありませんけど。

テスト用の例外発生ルーチンを準備

てっとりばやく例外を発生させる為に、bbsAction.java に細工します。0除算です。
// Compile command. You must be current file's directry.
// javac -classpath "../lib/struts.jar;../../../../common/lib/servlet-api.jar;"
 -d "." bbsAction.java

package mypackage;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.DynaActionForm;
import org.apache.struts.validator.DynaValidatorForm;

public class bbsAction extends Action
{
	public ActionForward execute
	(
		ActionMapping mapping,
		ActionForm form,
		HttpServletRequest req,
		HttpServletResponse res
	)
	throws Exception
	{
		DynaValidatorForm myForm = (DynaValidatorForm)form;

		int n = 5 / 0;	// 故意に例外を発生!

		return mapping.findForward( "success" );
	}
}
もちろんコンパイルしておきます。

動作テスト

bbs.jsp を開き、適当な文字列を入れて実行します。HTTPステータス 500 - が表示されるはずです。

例外に対してActionErrors インスタンスを生成する

例外発生に対して、単にActionErrors インスタンスを作り文字列を設定します。また遷移先も action エレメントのinput 属性となります。これでerror.jsp などからhtml:errors タグなどで エラーメッセージを取り出せます。

exception エレメントを記述する。

struts-config.xml のaction エレメント内にexception エレメントを作成します。
<action path="/bbs"
                type="mypackage.bbsAction"
                name="bbs_dvf"
                scope="request"
                validate="true"
				input="/error.jsp">
	<exception type="java.lang.ArithmeticException"
				  key="exception.Mathematics"/>		// 追加
	<forward name="success" path="/bbs.jsp"/>
	<forward name="error" path="/error.html"/>
</action>
type 属性には例外の種類。key 属性にはメッセージリソースを参照するさいのキーを設定します。

メッセージリソースの追加

メッセージリソース bbs_MR にexception.Mathematics という一文を用意しておきます。
exception.Mathematics=算術計算で例外発生です。
もちろんnative2ascii bbs_MR bbs_MR_ja.properties の実行も忘れずに。

動作テスト

bbs.jsp を開き、適当な文字列を入れて実行します。最初に記述したexception エレメントのtype に合致する例外が起きます。 メッセージリソースからexception エレメントのkey 属性の値に合う文字列が取り出され、ActionErrors インスタンスが作り、 その文字列を割り当てます。action エレメントのinput 属性に設定されたページに遷移し、そこでhtml:errors タグにより エラーの文字列が抽出される訳です。
動作の流れ的には、DynaValidateForm による検証の遷移と似ています。というか同じかも。

例外の後処理をクラスで実装する

exception エレメントのhandler 属性にクラスを設定しておけば、例外発生時に関数を呼び出す事ができます。

例外処理クラスを作成

bbsException.java というクラスファイルを新規作成します。ExceptionHandler クラスを継承したものを作ります。 で、コールバック用仮想関数であるexcute() メソッドをオーバーライドしたものです。
// Compile command. You must be current file's directry.
// javac -classpath "../lib/struts.jar;../../../../common/lib/servlet-api.jar;"
 -d "." bbsException.java

package mypackage;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ExceptionHandler;
import org.apache.struts.config.ExceptionConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

public class bbsException extends ExceptionHandler
{
	public ActionForward execute
	(
		Exception ex,
		ExceptionConfig conf,
		ActionMapping mapping,
		ActionForm form,
		HttpServletRequest req,
		HttpServletResponse res
	)
	throws ServletException
	{
		// Error.jsp で表示させる文字列をリクエストスコープに生成
		req.setAttribute( "report", "The bbsException class is called");

		return super.execute( ex, conf, mapping, form, req, res );
	}
}
コンパイルを忘れずに。

error.jsp を書き換え

bbsException が正常に呼ばれているならば、リクエストスコープに文字列(インスタンス名 report) が 生成されてるはずです。error.jsp 上でこれを出力させて確認します。
<%@page contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>

<html:html locale="true">
	<head>
		<title>error.jsp</title>
	</head>
	<body>
		<h3>Error!!</h3>
		<div><html:errors /></div>
		<div><bean:write name="report" /></div>	// 追加
	</body>
</html:html>

exception エレメントにhandler属性を追加記述する

struts-config.xml のaction エレメント内に記述したexception エレメントに、例外ハンドラクラスを指定する handler 属性を記述します。
<action 
	〜
	<exception type="java.lang.ArithmeticException"
				  key="exception.Mathematics"
				  handler="mypackage.bbsException" />	// 追加

動作テスト

正しく動けば正常です。

例外用の表示ページに遷移させる

struts-config.xml におけるaction エレメントのinput 属性がデフォルトのエラーページになってますが、 例外毎にページを指示する事もできます。

exception エレメントにpath属性を追加記述する

struts-config.xml のaction エレメント内に記述したexception エレメントに、遷移先のページへのパスを指定する path 属性を記述します。
<action
	 〜
	<exception type="java.lang.ArithmeticException"
				  key="exception.Mathematics"
				  handler="mypackage.bbsException" 
				  path="/exception.jsp" />		// 追加

exception.jsp の作成

例外時に遷移させるページを作成します。
<%@page contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS" %>
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>

<html:html locale="true">
	<head>
		<title>exception.jsp</title>
	</head>
	<body>
		<div><bean:write name="report" /></div>
	</body>
</html:html>

動作確認

exception.jsp に正しく遷移できれば成功です。