[JC]Struts2での例外処理について


ExceptionSequenceActionなどでExceptionが発生した際に、自動的にエラーページに遷移できるようにしておくと余計なエラー処理を内部で各必要がなくなるので便利かと思い作成しました。

今回の要件として、上記に加え、エラーの内容をメッセージコードで管理しているのでそれを利用し、さらに意図しないエラーの場合はデフォルトのメッセージコードを割り当てるというものです。

作成したのは、「com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor」を継承した自作例外インターセプタークラスだけです。実際、処理もほとんど変わっていません。

いつもの用に作成したソースは、下記に掲載しているので良ければ見てください。

作成したクラス以外の注意点として、インターセプタースタックにデフォルトの「defaultStack」を利用している場合、exceptionという通常の例外処理用インターセプターが存在するため、それを除外する必要があります。定義済みのスタックから除外する方法が見つからなかったので、defaultStackからexceptionを除いてstruts.xmlにて再定義しています。

広告

■JcExceptionInterceptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package org.fukata.jc_common.interceptor;
 
import java.util.List;
 
import org.apache.commons.lang.StringUtils;
import org.fukata.jc_common.exception.JcSystemException;
 
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
import com.opensymphony.xwork2.interceptor.ExceptionHolder;
import com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor;
 
public class JcExceptionInterceptor extends ExceptionMappingInterceptor {
 
	private static final long serialVersionUID = 1L;
 
	protected String defaultMessageCode;
 
	public String getDefaultMessageCode() {
		return defaultMessageCode;
	}
 
	public void setDefaultMessageCode(String defaultMessageCode) {
		this.defaultMessageCode = defaultMessageCode;
	}
 
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
        String result;
 
        try {
            result = invocation.invoke();
        } catch (Exception e) {
            if (isLogEnabled()) {
                handleLogging(e);
            }
            List<exceptionmappingconfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
            String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
            if (mappedResult != null) {
 
            	// メッセージコードの格納
            	Exception ex = e; 
            	if (isDefaultMessageCode(e)) {
            		ex = new JcSystemException(getDefaultMessageCode());
            	}
 
                result = mappedResult;
                publishException(invocation, new ExceptionHolder(ex));
            } else {
                throw e;
            }
        }
 
		return result;
	}
 
	/**
	 * デフォルトのメッセージコードを適用するかどうか
	 * @param e
	 * @return
	 */
    private boolean isDefaultMessageCode(Exception e) {
    	if (e instanceof JcSystemException) {
			if (StringUtils.isBlank(e.getMessage())) {
				return true;
			}
		} else {
			return true;
		}
    	return false;
	}
 
	private String findResultFromExceptions(List</exceptionmappingconfig><exceptionmappingconfig> exceptionMappings, Throwable t) {
        String result = null;
 
        // Check for specific exception mappings.
        if (exceptionMappings != null) {
            int deepest = Integer.MAX_VALUE;
            for (Object exceptionMapping : exceptionMappings) {
                ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) exceptionMapping;
                int depth = getDepth(exceptionMappingConfig.getExceptionClassName(), t);
                if (depth >= 0 && depth < deepest) {
                    deepest = depth;
                    result = exceptionMappingConfig.getResult();
                }
            }
        }
 
        return result;
    }
}

■applicationContext.xml

1
2
3
4
	<bean id="jcExceptionInterceptor" class="org.fukata.jc_common.interceptor.JcExceptionInterceptor"
		scope="prototype">
		<property name="defaultMessageCode" value="exception.M00100"></property>
	</bean>

■struts.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
		<!-- インターセプター -->
		<interceptors>
			<interceptor name="jcException" class="jcExceptionInterceptor"></interceptor>
			<interceptor name="login" class="loginInterceptor"></interceptor>
 
			<interceptor -stack name="myDefaultStack">
				<interceptor -ref name="jcException"></interceptor>
				<interceptor -ref name="login"></interceptor>
				<interceptor -ref name="alias"></interceptor>
				<interceptor -ref name="servletConfig"></interceptor>
				<interceptor -ref name="i18n"></interceptor>
				<interceptor -ref name="prepare"></interceptor>
				<interceptor -ref name="chain"></interceptor>
				<interceptor -ref name="debugging"></interceptor>
				<interceptor -ref name="profiling"></interceptor>
				<interceptor -ref name="scopedModelDriven"></interceptor>
				<interceptor -ref name="modelDriven"></interceptor>
				<interceptor -ref name="fileUpload"></interceptor>
				<interceptor -ref name="checkbox"></interceptor>
				<interceptor -ref name="staticParams"></interceptor>
				<interceptor -ref name="actionMappingParams"></interceptor>
				</interceptor><interceptor -ref name="params">
					<param name="excludeParams"/>dojo\..*,^struts\..*
				</interceptor>
				<interceptor -ref name="conversionError"></interceptor>
				<interceptor -ref name="validation">
					<param name="excludeMethods"/>input,back,cancel,browse
				</interceptor>
				<interceptor -ref name="workflow">
					<param name="excludeMethods"/>input,back,cancel,browse
				</interceptor>
 
		</interceptors>
 
		<default -interceptor-ref name="myDefaultStack"></default>
 
		<global -results>
			<result name="exception">/jsp/Error.jsp</result>
		</global>
 
		<global -exception-mappings>
			<exception -mapping result="exception" exception="java.lang.Exception"></exception>
		</global>

関連記事