이것땜에 오늘 또 하루를 날렸다.. 바쁜때에는 꼭 예상 밖의 일들이 터져서 하루를 피곤하게 만든다.

며칠 전부터, 개발서버 AIX 환경에서 매 요청 마다 Exception 이 계속 발생했는데,
대충, Struts2 의 FileUploaderInterceptor 에서 부터 시작하고, 결국에는 NoSuchFieldException 을 throw 하게 되는 콜스택을 보이는 예외이다.

사실 동작하는데 크게 문제는 없지만, 여간 신경쓰이는게 아니어서 해결하려고, Struts2 와 내부에서 사용하는 xwork2 의 소스까지 빌드해가면서 찾아낸 결론은,

AIX 에서는 IBM JDK (JDK6) 와 xwork 와의 호환성에 문제가 있어,
struts.xml 이나 properties 에서, struts.i18n.reload 와 devmode 옵션을 false 로 주어야 한다


는 것이다.

좀더 깊숙히 원인을 분석해본 결과, struts2 가 사용하는 xwork2 라이브러리에서, ResourceBundle 을 사용하는데,
Struts 의 Dispatcher 에서 사용하는 xwork 의 클래스 중에서 (LocalizedText 였나.. 기억이..) java.util.ResourceBundle 을 사용한다.

이때, xwork 의 옵션으로, 리소스를 동적으로 갱신 시에 리로드 할 수 있는 옵션을 줄 수 있는데, struts2 에서는 Dispatcher 에서 struts.i18n.reload 옵션값을 읽어, xwork 에 설정하도록 한다.
이때 reload 옵션이 true 인 경우, 위와 같은 문제가 생기는데, 옵션이 true 이면, ResourceBundle 의 claerCache() 메소드를 호출하거나 하는게 아니라, Reflection 기능을 사용하여, ResourceBundle 의 내부 HashMap, 그것도 private 로 선언된 놈(멤버변수명: cacheList) 을 setAccessible(true)를 써가면서 까지 가져와 직접 clear() 를 호출하도록 하고 있다.

여기에서 문제가 생기는데, Sun 의 JDK 의 경우, 위 map 의 변수명이 cacheList 이지만, IBM 의 JDK 의 구현 소스는 내부적으로 많이 다르고, cacheList 라는 Field 변수 자체가 없다. 그래서 오류가 나는 것이다.

이 기능을 안쓰거나, xwork 소스를 수정하는 방법이 있겠는데, 나는 회피하는 방법을 쓰려고 struts.i18n.reload 를 false 로 struts.xml 의 constant 선언으로 값을 주었지만 먹지를 않았다. 그래서 결국 xwork 와 struts 를 소스로 받아 세팅값이 먹혔는지 보기 위해 maven 으로 빌드까지 해가면서 파악 해보니, struts.i18n.reload 값에 앞서, devmode 를 false 로 해줘야 하는것을 알 수 있었다.

결국은 저렇게 세팅하나 잘못 바꿔서 하루를 날려버리는 참 어처구니 없는 일을 저지르고 말았다..
그래도 Reflection 의 강력한 기능과 Struts2 의 내부를 조금이나마 더 들여다 볼 수 있는 기회이기도 했다는데에 만족하고 있다.

반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,