====== Exception Handling 서비스 ====== ===== 개요 ====== 전자정부 표준프레임워크 기반의 시스템 개발시 Exception 처리, 정확히는 Exception 별 특정 로직(후처리 로직이라고 부르기도 함)을 흐를 수 있도록 하여 Exception 에 따른 적절한 대응이 가능도록 하고자 하는데 목적이 있다.\\ AOP 의 도움을 받아 비즈니스 POJO와 분리되어 After throwing advice 로 정의하였다.\\ AOP 관련한 내용은 [[egovframework:rte:fdl:aop|AOP 모듈]]을 참조하길 바란다.\\ Exception 에 대해 이야기 하겠다.\\ Exception 이 발생시 Exception 발생 클래스 정보와 Exception 종류가 중요하다. \\ Exception 발생 클래스 정보와 Exception 종류는 모두 후처리 로직의 대상일지 아닐지를 결정하는데 사용된다.\\ public CategoryVO selectCategory(CategoryVO vo) throws Exception { CategoryVO resultVO = categoryDAO.selectCategory(vo); try { .... // 넘어온 resultVO 가 null 인경우 EgovBizException 발생 (result.nodata.msg 는 메세지 키에 해당됨) if (resultVO == null) throw processException("result.nodata.msg"); // 또는 throw processException("result.nodata.msg", 발생한 Excpetion ); return resultVO; } ===== 설명 ===== 우리는 앞에서 언급했던 Exception 후처리 방식과 Exception 이 아니지만 후처리 로직(leavaTrace)을 실행할 하는 방식에 대해 설명하도록 하겠다. \\ 간략하게 보면 \\ Exception 후처리 방식은 ** AOP(pointCut => after-throw) => ExceptionTransfer.transfer() => ExceptionHandlerService => Handler ** 순으로 실행된다. \\ LeavaTrace 는 AOP를 이용하는 구조는 아니고 Exception 을 발생하지도 않는다. 단지 후처리 로직을 실행하도록 하고자 함에 목적이 있다.\\ 실행 순서는 ** LeavaTrace => TraceHandlerService => Handler ** 순으로 실행한다. \\ 먼저 Exception Handling 에 대해 알아보도록 하자. ==== Aop Config, ExceptionTransfer 설정 및 설명 ==== ---- === Bean 설정 === Exception 후처리와 leaveaTrace 설정을 위해서 샘플에서는 두개의 xml 파일을 이용한다. (context-aspect.xml, context-common.xml) 먼저 Exception 후처리를 위한 부분을 보겠다.\\ Exception Handling 을 위한 AOP 설정은 아래와 같다. \\ 비즈니스 개발시 패키지 구조는 바뀌기 때문에 Pointcut은 egov.sample.service.*Impl.*(..)) 을 수정하여 적용할 수 있다.\\ ExceptionTransfer 의 property 로 존재하는 exceptionHandlerService 는 다수의 HandleManager 를 등록 가능하도록 되어 있다.\\ 여기서는 defaultExceptionHandleManager을 등록한 것을 볼 수 있다. \\ **context-aspect.xml** ... **service.*Impl ... defaultExceptionHandleManager는 setPatters() , setHandlers() 메소드를 가지고 있어 상단과 같이 \\ 등록된 pattern 정보를 이용하여 Exception 발생 클래스와의 비교하여 ture 인 경우 handlers 에 등록된 handler를 실행한다.\\ 패턴 검사시 사용되는 pathMatcher 는 AntPathMatcher 를 이용하고 있다. \\ 특정 pattern 그룹군을 만든후 patterns 에 등록하고 그에 해당하는 후처리 로직을 정의하여 등록할 수 있는 구조이다. \\ === Handler 구현체 === 먼저 클래스에 대한 이해가 필요하다. 앞단에서 간단하게 설명을 했지만 다시 정리 하자면\\ Exception 발생시 AOP pointcut "After-throwing" 걸려 ExceptionTransfer 클래스의 transfer 가 실행된다.\\ transfer 메소드는 ExceptionHandlerManager 의 run 메소드를 실행한다. 아래는 구현예로 DefaultExceptionHandleManager 코드이다.\\ **(구현시 필수사항) 상위클래스는 AbsExceptionHandleManager 이고 인터페이스는 ExceptionHandlerService 이다.** \\ 구현되는 메소드는 run(Exception exception) 인 것을 확인할 수 있다. \\ ** DefaultExceptionHandleManager.java** public class DefaultExceptionHandleManager extends AbsExceptionHandleManager implements ExceptionHandlerService { @Override public boolean run(Exception exception) throws Exception { log.debug(" DefaultExceptionHandleManager.run() "); // 매칭조건이 false 인 경우 if (!enableMatcher()) return false; for (String pattern : patterns) { log.debug("pattern = " + pattern + ", thisPackageName = " + thisPackageName); log.debug("pm.match(pattern, thisPackageName) =" + pm.match(pattern, thisPackageName)); if (pm.match(pattern, thisPackageName)) { for (ExceptionHandler eh : handlers) { eh.occur(exception, getPackageName()); } break; } } return true; } } === Customizable Handler 등록 === 시나리오 : CustomizableHandler 클래스를 만들어 보고 sample 패키지에 있는 Helloworld 클래스 Exception 시에 CustomizableHandler 를 실행한다.\\ 먼저 CustomHandler 클래스를 아래와 같이 만든다.\\ ExceptionHandleManager 에서는 occur 메소드를 실행한다. \\ **Handler 구현체는 반드시 (필수사항) ExceptionHandler Interface를 갖는다. ** **CustomizableHandler.java** public class CustomizableHandler implements ExceptionHandler { protected Log log = LogFactory.getLog(this.getClass()); public void occur(Exception ex, String packageName) { log.debug(" CustomHandler run..............."); try { log.debug(" CustomHandler 실행 ... "); } catch (Exception e) { e.printStackTrace(); } } } CustomizableHandler 의 등록을 해보도록 하겠다.\\ 역시서 주의해야 하는 부분은 patterns 에 sample 패키지에 있는 Helloworld 클래스 를 지정해주어야 한다. \\ **sample.Helloworld 이런식으로 여러개의 Handler를 등록해줄 수 있다. ==== leaveaTrace 설정 및 설명===== ---- Exception 이거나 Exception 이 아닌 경우에 Trace 후처리 로직을 실행 시키고자 할 때 사용한다.\\ 설정하는 기본적인 구조는 Exception 후처리 하는 방식과 같다. 설정파일이 context-common.xml 이다.\\ DefaultTraceHandleManager 에 TraceHandler를 등록하는 형태로 설정된다.\\ === Bean 설정 === ... * ... === TraceHandler 확장 개발 Sample === ** Interface TraceHandler를 아래와 같이 implements 한다. ** package egovframework.rte.fdl.cmmn.trace.handler; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class DefaultTraceHandler implements TraceHandler { public void todo(Class clazz, String message) { //수행하고자 하는 처리로직을 넣는 부분... System.out.println(" log ==> DefaultTraceHandler run..............."); } } === leaveaTrace 코드상 발생 Sample === 사용방법을 다시 상기 해보면 아래와 같다. \\ 메세지키(message.trace.msg) 를 이용하여 메세지 정보를 넘겨 Handler 를 실행한다. \\ public CategoryVO selectCategory(CategoryVO vo) throws Exception { CategoryVO resultVO = categoryDAO.selectCategory(vo); try { //강제로 발생한 ArithmeticException int i = 1 / 0; } catch (ArithmeticException athex) { //Exception 을 발생하지 않고 후처리 로직 실행. leaveaTrace("message.trace.msg"); } return resultVO; } ===== 참고자료 ===== * [[http://www.onjava.com/pub/a/onjava/2006/01/11/exception-handling-framework-for-j2ee.html?page=1|exception-handling-framework-for-j2ee]] * Effective Java (Joshua Bloch) : Chapter 8 예외처리