Exception Handling

Anyframe에서 제공하는 BaseException 유형의 Exception이 throw되었을 때, 이를 처리하는 ExceptionHandler에 대해 알아보기로 하자.
  • DefaultExceptionHandler
  • DefaultExceptionHandler는 Struts의 ExceptionHandler를 확장한 클래스로써, Anyframe에서 제공하는 BaseException이 catch 되었을때, BaseException 내에 정의된 메시지 key와 대체 문자열을 ActionMessage 객체에 저장하여 Forward하는 로직으로 구성되어 있다. 이 외, Exception이 catch 되었을 때는 Struts의 기본 ExceptionHandler에서와 같이 <exception>에 정의된 key 값을 이용하게 된다.

  • DefaultBaseExceptionHandler
  • Anyframe에서 제공하는 BaseException을 상속받아 구현한 비즈니스 Exception은 생성 시점에 전달된 메시지 Key를 이용하여, Message Resource Bundle 내에 정의된 유형별 메시지(기본,해결책,원인)가 해당 Exception 객체에 담기게 된다. (Anyframe Core 매뉴얼의 Tech. Service >> ExceptionHandling 참조)
    DefaultBaseExceptionHandler는 catch한 BaseException으로부터 유형별 메시지를 모두 처리할 수 있게 구성되어 있으므로 DefaultBaseExceptionHandler를 사용하는 것이 좋다. Tag Library를 통해 메시지 Key로써 에러 메시지를 출력하는 형태가 아닌 유형별 메시지 자체를 추출하고 있다. 또한, 비즈니스 Exception 외에 프리젠테이션 레이어에서 발생한 Exception에 대해서도 에러 메시지 처리가 가능토록 기본 Resource Bundle명인 "anyframe.web.struts.common.CommonResource"를 참조한다. 일반적으로, ExceptionHandler는 Anyframe에서 제공하는 DefaultBaseExceptionHandler를 상속받아 구현하면 된다.
다음에서는 선언적인 Exception Handling 기법과 DefaultBaseExceptionHandler 확장 방법에 대해 알아보기로 한다.

선언적인 Exception Handling

Anyframe Web에서는 Action 클래스에서 직접 try-catch 문으로 Exception을 처리하지 않고, 속성 정의를 통해 선언적으로 exception을 처리할 수 있다.

Samples

다음은 struts-config-exception.xml 의 일부로 선언적인 exception 처리의 예이다.
<action path="/exceptionHandling"
	type="anyframe.sample.struts.web.action.ExceptionHandlingAction"
	scope="request">
	<exception type="anyframe.common.exception.BaseException"
		key="common.msg.action.error"
		path="/extensions/error.jsp" 
		handler="anyframe.web.struts.util.DefaultBaseExceptionHandler"/>
</action>
위 설정을 통해 ExceptionHandlingAction 수행시 Exception이 발생한 경우, 발생한 Exception이 BaseException 유형이면 DefaultBaseExceptionHandler를 통해 해당 Exception이 처리된다.
아래와 같이 <global-exceptions> 내에 Exception에 대한 처리를 공통 정의할 수도 있다. 만일, <action>과 <global-exceptions> 내에 동일한 Exception이 정의되어 있는 경우 <action>에 정의된 Exception 처리가 우선 적용된다.
<global-exceptions>
	<exception path="/extensions/error.jsp"
 		key="common.msg.authentication.error"
 		type="anyframe.web.struts.util.AuthenticationException"
 		handler="anyframe.sample.struts.web.common.SampleExceptionHandler" />
 	<exception path="/extensions/error.jsp"
 		key="common.msg.authorization.error"
 		type="anyframe.web.struts.util.AuthorizationException"
 		handler="anyframe.sample.struts.web.common.SampleExceptionHandler" />
 	<exception path="/extensions/error.jsp" 
 		key="common.msg.base.error"
 		type="anyframe.common.exception.BaseException"
 		handler="anyframe.sample.struts.web.common.SampleExceptionHandler" />
 </global-exceptions>

DefaultBaseExceptionHandler 확장

다음은 DefaultBaseExceptionHandler를 확장하여 해당 프로젝트의 Exception 처리 방식을 재정의한 SampleExceptionHandler.java 이다.
public class SampleExceptionHandler extends DefaultBaseExceptionHandler {

	public SampleExceptionHandler() {
		this.defaultBundle 
			= "anyframe.sample.struts.web.common.SampleResources";
	}

	public ActionForward execute(Exception exception, ExceptionConfig config,
			ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws ServletException {

		
		ActionForward forward = mapping.getInputForward();
		
		if (exception instanceof AuthenticationException) {
			String loginPageURI = "/loginView.do";
			forward.setPath(loginPageURI);
			request.setAttribute("authenticateFail", "true");
		} else if (exception instanceof AuthorizationException) {
			String homePageURI = "/authrizationView.do";
			forward.setPath(homePageURI);
			request.setAttribute("authFail", "true");
		} else {
			String forwardPath = forward.getPath();
			if (forwardPath == null || forwardPath.equals("")) {
				forwardPath = "/loginView.do";
				request.setAttribute("authFail", "true");
			}
			String url = forwardPath + "?";
			
			Enumeration enumrequest = request.getParameterNames();
			while (enumrequest.hasMoreElements()) {
				String parameterName = (String) enumrequest.nextElement();
				String parameterValue = request.getParameter(parameterName);
				url += parameterName + "=" + parameterValue + "&";
			}
			forward.setPath(url);
			
		}
		request.getSession().setAttribute("afterErrorPage", forward);
		return super.execute(exception, config, mapping, form, request,
				response);
	}
}
에러 메시지 처리를 위한 기본 Message Resource Bundle을 anyframe.sample.struts.web.common.SampleResources로 재정의하였고 이전 요청 정보를 get 방식으로 url에 추가하여 afterErrorPage로 포워딩하는 로직이 추가되어 있다. 또한, Exception 유형에 따른 처리는 super.execute 메소드를 그대로 사용하고 있음을 알 수 있다.
다음은 해당 SampleExceptionHandler를 통해 전달된 에러 메시지를 처리하는 error.jsp 의 일부이다.
<%
    ... 중략 ...
	String[] messages 
		= (String[])request.getAttribute(Globals.MESSAGE_KEY);
  	
	String userMessage = messages[0];
  	String solution = "";
  	String reason = "";
  	
  	if(messages.length==2) {
  		solution = messages[1];
  	}
  	
  	if(messages.length==3) {
  		solution = messages[1];
  		reason = messages[2];
  	} 
%>
	... 중략 ...
	<%= userMessage %><p/>
	<% if(!solution.equals("")) { %>
		<strong>* SOLUTION</strong><br/>
		<%= solution %>
	<% } %>
	<% if(!reason.equals("")) { %>
		<strong>* REASON</strong><br/>
		<%= reason %>
	<% } %>
	... 중략 ...
<td background="<html:rewrite page='/sample/images/ct_btnbg02.gif'/>" 
    class="ct_btn01" style="padding-top:3px;">
    <a href="javascript:fncGoAfterErrorPage();">확인</a>
</td>
	... 중략 ...

Resources

  • 다운로드
  • 이클립스 프로젝트 형태의 샘플 웹 어플리케이션을 포함하고 있는 anyframe-struts-sample-extensions.zip 파일을 다운받은 후, 테스트 환경 설정 을 참조하여 위에서 제시한 예제 코드를 실행해 볼 수 있다.
    Name
    Download
    anyframe-struts-sample-extensions.zip
    Download


  • 참고자료