'Should Not@'에 해당되는 글 3

  1. 2009.12.18 잘못된 예외 처리로 인해 엉뚱한 에러 발생
  2. 2009.10.22 예외 추적
  3. 2009.04.23 해서는 안되는 예외 처리 - 아무것도 안하는 경우

잘못된 예외 처리로 인해 엉뚱한 에러 발생

데이터 형식 nvarchar을(를) numeric(으)로 변환하는 중 오류가 발생했습니다.

갑자기 에러가 발생했다.
이런 에러가 예전부터 많이 나오긴 했었다.
SELECT count(*) cnt
FROM INFO_TEMP
WHERE pk1 = ? --20091211
AND pk2 = ? --1

문제가 없는 쿼리인데 에러가 발생한다.

로그를 보니 이상한 로그가 있다.
DEXTUploadException --> 데이터를 읽어오는 데 실패했습니다. 사용자와의 연결이 끊어졌거나 업로드를 중지했습니다.
        }catch (Exception ex) {
            System.out.println("DEXTUploadException --> "+ex.getMessage());
        }finally {
            try {
                fileUpload.dispose();
            ...

예외를 잡아서 로그만 남기고 아무런 처리를 하지 않는다.
업로드컴포넌트에서 처리가 되지 않아서 DAO에서 쿼리문을 처리할때 pk2가 빈 문자열이 넘어온거 같다.
(웹요청에 대한 값을 Map에 넣었다가 getString(NAME) 같은 메서드로 처리하는데 NAME으로 된 값이 없으면 빈 문자열로 처리하게 되어 있음)

결국에는 아래와 같은 쿼리가 실행되었다.
SELECT count(*) cnt
FROM INFO_TEMP
WHERE pk1 = ''
AND pk2 = '' --pk2는 숫자형임

업로드컴포넌트에서 에러가 난 이유는 디스크가 다 차서 더이상 용량이 남아 있지 않았다고 한다.

- 2010-02-08
다른 프로그램에서 동일한 에러 발생
전송을 했는데 화면이 정지하고 반응이 없었다고 함.
서버/네트워크 사용량이 많아서인지, 업체 PC 사양이 떨어져서 그런지는 불분명함.

예외 추적

}catch(Exception e){
    System.out.println("+++++++++++++++++++++" + e);
    this.logger.info("+++++++++++++++++++++" + e.getMessage());

    out.println("FAIL");
    out.println(e.getMessage());
    out.flush();
}
10-15 15:13:43 ERROR com.xxx.client.connect.transmit.SendSOAPServiceImpl.proc(SendSOAPServiceImpl.java:343) - com.xxx.client.connect.transmit.SOAPException
10-15 15:13:43 ERROR com.xxx.client.connect.transmit.SendSOAPServiceImpl.proc(SendSOAPServiceImpl.java:344) -
10-15 15:13:43 INFO com.xxx.client.connect.transmit.SendServlet.doPost(SendServlet.java:89) - +++++++++++++++++++++null

예외가 어디서 발생했는지 로그에 쓸만한 정보가 없다.
로그를 기록하는 부분을 다음과 같이 변경한다.
logger.error("error", e);
10-22 09:19:59 ERROR com.xxx.client.connect.transmit.SendSOAPServiceImpl.proc(SendSOAPServiceImpl.java:343) - com.xxx.client.connect.transmit.SOAPException
10-22 09:19:59 ERROR com.xxx.client.connect.transmit.SendSOAPServiceImpl.proc(SendSOAPServiceImpl.java:344) -
10-22 09:20:00 ERROR com.xxx.client.connect.transmit.SendServlet.doPost(SendServlet.java:90) - error
com.xxx.client.connect.transmit.SOAPException
    at com.xxx.client.connect.transmit.ApplicationXMLHandler.validate(ApplicationXMLHandler.java:862)
    at com.xxx.client.connect.transmit.ApplicationXMLHandler$$FastClassByCGLIB$$3ea56c40.invoke(<generated>)
    ...
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:534)
Caused by: java.security.NoSuchAlgorithmException
    at signgate.crypto.util.MDUtil.<init>(MDUtil.java:127)
    at com.xxx.client.connect.transmit.ApplicationXMLHandler.validate(ApplicationXMLHandler.java:849)
    ... 55 more

해서는 안되는 예외 처리 - 아무것도 안하는 경우

예외를 잡아서 아무것도 처리하지 않는 경우 예외가 발생했는지도 모르기 때문에 유지보수가 힘들다.
필요한 경우가 아닌 경우 절대 해서는 안되는 방식이다.
try{
    //throw exception
}catch(Exception e){
    //do nothing
}

로그만 남기고 지나는 경우도 별반 다르지 않다.
사용자는 예외가 발생했는지 인지할수가 없다.
그냥 안된다고만 한다.
try{
    //throw exception
}catch(Exception e){
    logger.error(e);
}

예외처리를 하더라도 로그는 남겨야 한다.(로그는 중앙집중적으로 한곳에서 남겨야 한다.)
에러났다고 하는데 원인을 파악할 수 없다.
try{
    //throw exception
}catch(Exception e){
    isError = true; //예외를 추적할 수 있는 e를 그냥 무시하고 있다.
    또는
    throw new XxxException(e.getMessage()); //이런 경우에도 예외를 추적할 수 없다. 필요한 경우가 아니라면 이렇게 사용하지 말고 아래와 같이 생성자에 이전 예외를 넣어준다. 
    //throw new XxxException(e); //권장
}
...
if(isError){
    message("에러입니다.");
}

  [todo] 적절한 예외 처리 를 정리할 것.