Search Results : mac

요즘은 블로그 쓰는 시간을 내는 건 사치를 부리는 것 같아서 짧게 짧게..

 

호주 북부에 몰아쳤던 싸이클론 올가인가 하는 놈이 다 죽어가면서 브리즈번에 도착했는데, 그래도 싸이클론이었던 지라 그 영향력이 대단하다. 일주일째 천둥 번개와 비를 수시로 뿌려대고 체감 기온은 한 10도는 떨어진듯하다. 덕분에 평화가 감기가 들려버렸다. 어제 저녁부터 밤새 열이 오르내리더니 기침도 하기 시작했다. 오늘은 어린이 집도 못보내고 병원에나 다녀온 뒤 집에서 돌봐줘야 할 것 같다. 비상모드.

 

제이보스 씸(Seam)을 공부하면서 신기했던 것 한 가지는 씸 애플리케이션이 브라우저의 창과 탭을 구분한다는 것이었다. 예를 들어 쇼핑몰을 돌아다니다가 여러 개의 탭을 열어서 각각 다른 상품을 선택하고 동시에 결재로 들어가면 두 가지 카드의 결재가 병렬적으로, 서로 영향을 주지 않고 진행하는 것이 가능하다는 것이다. 같은 브라우저 인스턴스에서는 멀티 창과 탭에서 모두 웹 세션이 공유되기 때문에 서로 영향을 준다는 것이 상식인데, 이게 어찌 가능한지 신기할 따름이었다. 씸 책에서는 이게 씸을 차세대 프레임워크로 차별화 시켜주는 것이다라며 한것 치켜올리기도 한다. 처음 이런 기능을 보면서 혹시 브라우저가 탭이나 창을 구분할 수 있는 ID 같은 것을 헤더에 보내주는 것이 아닐까라고 생각했다. 궁금해서 테스트를 해보니 탭이 달라져도 HTTP 헤더에 아무런 변화가 없다. 그러면 씸은 도대체 어떻게 각 탭에서의 작업을 완벽히 분리해서 처리할 수 있는 것일까?

답은 알고보니 매우 간단했다. 씸이나 JSF의 컨버세이션이 어떻게 유지되는지를 이해하면 사실 자명한 현상이다. 씸은 일반적으로 HTTP GET요청이 갈 때마다 새로운 컨버세이션을 만든다. 따라서 쇼핑 카트와 주문 프로세스가 하나의 컨버세이션이라면 링크를 클릭하거나 URL을 옮겨 적어 같은 브라우저에서 새 창을 열거나 새 탭을 열게 되면 HTTP GET이 날라가고, 그 안에서 새로운 컨버세이션이 시작되는 것이다. 이렇게 시작된 컨버세이션은 히든 필드에 ID를 숨겨서 POST를 타고 계속 넘어간다. 따라서 탭이 달라지고 창이 달라지면 분리된 컨버세이션이 만들어지고, 그 안에 새로운 컨텍스트를 가진 카트와 결재 컴포넌트들이 만들어져서 POST로 계속 이어지는 컨버세이션ID에 결합되어서 돌아가는 것 뿐이다. 알고보니 간단.

물론 씸은 원한다면 GET으로 링크를 타고 넘어갈 때도 컨버세이션을 유지시켜 줄 수도 있다. URL에 ID를 넣게 해주는 것을 지원한다. 그렇다면 이런 경우에 URL을 카피해서 다른 탭에서 작업을 계속 한다면? 그때는 탭마다 분리된 컨버세이션이 생기지는 못할 것이다.  시간이 없어서 직접 검증은 못해봐서 100% 장담은 못하겠지만 지금까지 공부한 씸에 대한 이해로는 이정도.

씸과 비슷한 stateful 방식의 애플리케이션을 지원하는 스프링 웹 플로는 URL의 파라미터로 각각의 컨버세이션을 구분하는 것이 디폴트이다. POST를 사랑하는 JSF가 기본이 아니기 때문이다. 물론 원한다면 SWF에서도 탭마다 병렬적으로 다른 컨텍스트를 유지시키는 것이 가능하겠지.

아무튼 stateful의 세계는 여러모로 흥미롭다. 조만간 바쁜 작업을 마무리 하고 나면 stateful 개발에 올인해볼 생각이다. 그나저나 친애하는 자바 챔피언 양회장님은 한국 씸 프레임워크 사용자 모임(KSFUG)을 언제 시작하시려나. 발기인으로 참여한지 4개월째인데, 아직도 모임 사이트 소식이 없다…

 

스프링소스의 직원이자 톰캣의 핵심 개발자인 Mark Thomas의 Tomcat 7 관련 인터뷰 기사가 http://java.dzone.com/articles/memory-leak-protection-tomcat 에 실렸다. 구체적으로 Tomcat 7(또는 6의 최신버전)에서 그동안 말썽이던 메모리 누수 문제를 대폭 해결했다는 것이다. 톰캣의 리로딩 기능은 유용하지만 개발과정에서 왠만한 규모의 애플리케이션이라면 4-5차례 리로링을 하고 나면 PermGen이 모자란다고 칭얼거리며 뻗는 톰캣을 경험해봤을 것이다. 문제의 원인과 책임규명은 사실 복잡하고 지저분하다. 근본적인 원인은 리로딩 시에 기존 웹 앱의 클래스 로더를 톰캣이 제거하지만 GC 대상이 되지 못하기 때문이다. 클래스로더가 GC되야 역시 그 안에서 로딩된 애플리케이션의 클래스들도 함께 제거될텐데, 클래스로더가 톰캣 외에 다른 오브젝트를 통해서 참조되고 있기 때문에 문제가 된다. PermGen처럼 사이즈가 작은 메모리가 그래서 가장 먼저 타겟이 된다. 이런 문제의 원인은 다양한데, 위 기사에 잘 설명되어있다. 2004-2005년 즈음에 이 문제로 하이버네이트, CGLib, Commons Logging이 피터지는 공방을 벌였던 기억이 난다. 개빈 킹은 하이버네이트가 집중 공격 당하는 과정에서 열받아서 아파치 그룹의 프로젝트 중 ANT와 Log4J 빼면 다 쓰레기다라는 유명한 발언을 하기도 했다. 지금은 어떻게 생각하는지 모르겠지만. 결국 톰캣 개발자들은 이런 메모리 누수 원인은 대부분 애플리케이션과 라이브러리 탓이라고 책임을 돌렸다. 사실이긴 하다. 심지어 GWT가 적극 사용한다는 JRE의 java 2d API 조차도 메모리 누수의 주범이라고 한다. 깔끔하게 청소해주지 않는 ThreadLocal도 문제다(그래서 스프링은 Thread scope보다는 같은 ThreadLocal을 사용하지만 요청이 끝날 때마다 깔끔히 정리해주는 Request scope 사용을 권장한다).

아무튼 톰캣 최신 버전은 이런 잘 알려진 애플리케이션 내의 메모리 누수의 원인을 톰캣 차원에서 직접 해결하는 기능을 추가했다고 한다. 과연~. 개선했다는 클래스로더의 clearReference()메소드를 구경하고 싶지만.. 어흑 시간이.

 

아이폰 관련 기사나 글, 트위터에 보면 너도 나도 어플리케이션(application) 또는 어플이라는 말을 쓴다. 원 발음 그대로 차음하면 영 어색한 2음절 강세 단어(퍼래미터(parameter)나 어패치(apache) 같은)도 아닌데, 애플리케이션이라고 하면 안되나. 아예 통일해서 "어플(apple)이 만든 먹북(macbook)에서 어플리케이션(application)"을 쓴다라고 하던가.

조쉬 블록 트위터를 보다가 이번 봄에 읽어볼만하다 싶은 흥미로운 책 발견.

Coders at Work

웹사이트를 통해서 추천받은 프로그래머 중 15명을 선정해서 그들을 인터뷰한 내용을 담은 책이라고 한다. 어떻게 프로그래머가 되고, 어떻게 자신의 기술을 발전시켰는지 등에 관한 내용이라고 하는데, 내가 딱 좋아하는 그런 책이다. 이런 식의 인터뷰는 너무 미화되거나 과장되지만 않으면 배울 것도 많다.

아마존의 소프트웨어 개발 카테고리 판매 1위, 전체 서적 판매 100위이다. 이쯤 되면 아마 어느 출판사에선가 번역도 하고 있겠지?

아래는 이 책이 소개하는 코더들 목록이다.  각 코더들에 대한 좀 더 자세한 소개는 http://www.codersatwork.com/ 에 잘 나와있다.

  • Frances Allen: Pioneer in optimizing compilers, first woman to win the Turing Award (2006) and first female IBM fellow
  • Joe Armstrong: Inventor of Erlang
  • Joshua Bloch: Author of the Java collections framework, now at Google
  • Bernie Cosell: One of the main software guys behind the original ARPANET IMPs and a master debugger
  • Douglas Crockford: JSON founder, JavaScript architect at Yahoo!
  • L. Peter Deutsch: Author of Ghostscript, implementer of Smalltalk-80 at Xerox PARC and Lisp 1.5 on PDP-1
  • Brendan Eich: Inventor of JavaScript, CTO of the Mozilla Corporation
  • Brad Fitzpatrick: Writer of LiveJournal, OpenID, memcached, and Perlbal
  • Dan Ingalls: Smalltalk implementor and designer
  • Simon Peyton Jones: Coinventor of Haskell and lead designer of Glasgow Haskell Compiler
  • Donald Knuth: Author of The Art of Computer Programming and creator of TeX
  • Peter Norvig: Director of Research at Google and author of the standard text on AI
  • Guy Steele: Coinventor of Scheme and part of the Common Lisp Gang of Five, currently working on Fortress
  • Ken Thompson: Inventor of UNIX
  • Jamie Zawinski: Author of XEmacs and early Netscape/Mozilla hacker

가장 맘에 드는 건 책 제목이다. 코더라는 말을 저급 개발자를 지칭하는, 그래서 상대적인 우월감을 가지려 하는 용도로 쓰는 사람들에게는 충격적인 제목이겠지?

조만간 구해서 읽어봐야겠다.

alankang님이 쓰신 “OOP란 조건문(if)을 줄이는 것“이란 글을 읽다가 문득 든 생각이다. 그 글이랑 별 상관없는 생각이긴 하지만.

자바5+에서 애노테이션이 등장했을 때 대체로 환영하는 분위기였다. iBatis의 개발자처럼(누구더라..) 자바5+의 새로운 언어기능은 다 쓰레기다라고 분노한 사람도 있긴 하지만, 스프링의 설정은 죽어도 XML이면 충분하다고 꽤 오랜동안 고집을 부렸던 로드존슨 조차도 닷넷의 애노테이션을 보라면서 자바의 소스코드 애트리뷰트 도입의 필요성을 자주 이야기하곤 했을 정도로 애노테이션 자체에 대해서는 반기는 입장이었다. 1.x시절부터 SpringMVC를 이용해서 웹 프로그램을 만들때면 지금의 @RequestMapping과 같은 아파치 애트리뷰트를 이용한 소스코드 내의 URL매핑을 가장 먼저 적용한다고 한 것도 로드존슨이다.

XML과 외부설정에 지쳐서 하이버네이트(2.x)를 비롯해서 왠만한 설정은 XDoclet을 적용해왔던 나도 역시 대 환영이었다.

JPA의 애노테이션 설정이라든가 스프링의 @Transactional, @Required에 이은 2.5의 @Autowired류의 @DI등을 만났을 때, 또 @RequestMapping으로 한방에 URL매핑을 해버리는 @MVC를 사용했을 때의 만족감은 대단했다. JUnit 3.x의 TestCase 상속구조에 발이 묶여있던 스프링테스트가 @Test를 가진 JUnit4를 지원하는 TestContextFramework을 내놓으면서 심지어 도메인 클래스를 확장해서 테스트를 만들어도 된다는 놀라운 사실에 감탄했다.

하지만 애노테이션에 대한 환상은 금방 깨졌다.

애노테이션이 소스코드랑 결합되어있어 설정을 바꾸려고 해도 컴파일을 다시 해야 한다거나, XML처럼 구조적인 정보를 만들기도 어렵고 정보가 모여있지도 않고, 검증도 힘들다는 것 등등은 이미 예상했던 것들이니까 그려려니 했다.

사실 애노테이션을 적용하면서 놀라게 된 것은 “애노테이션 덕분에 POJO가 됐어요”라는 캐치프레이즈 뒤에 숨은 애노테이션에 대한 뒤치닥 거리 코드들이었다. 애노테이션을 단지 코멘트처럼 개발중에 코드를 읽기 위해서 사용할 수도 있고, 빌드타임중에 설정파일 대용으로 사용할 수도 있다. 하지만 대부분의 경우 애토네이션은 런타임시에 프레임워크 또는 애플리케이션 스스로 사용한다.

애노테이션 정보를 얻으려면 자바의 리플렉션 API를 이용해야 한다. 애노테이션 자체가 단순 텍스트가 아니라  @Interface로 정의되어 컴파일되는 일종의 클래스 정보이므로 애노테이션 자체를 얻어오고 비교하고 엘레먼트 값을 읽고 하는 것은 텍스트 설정정보를 다루는 것보다는 분명 우아하다.

문제는 애노테이션이 단순히 XML과 같은 초기 설정정보를 대치하는 것에서 벗어나서 원래 자바의 객체지향적인 기법을 이용해서 만들었어야 하는 것들을 대체하기 시작했다는 점이다. 그것은 애노테이션 탓이라기 보다는 사실 애노테이션이 길을 닦아준 메타프로그래밍 스타일의 개발방법 때문이라고 생각된다. 거기다 RoR이 일으킨 CoC의 열풍은 적절한 애노테이션으로 마킹하고, 나머지는 CoC에 의해서 미리 정해진 전제조건을 가지고 일단 시도해본다는 참 낙관적인 스타일의 코드를 만들게 하고 있다.

JUnit4는 더 이상 템플릿메소드니 아답타니 코맨드니 플러거블셀렉터이니 콤포짓이니 하는 그럴싸한 디자인패턴이 필요없이, 그저 @Before, @Test, @After 따위가 붙으면 프레임워크가 애노테이션을 일일히 읽어가면서 순서를 정하고 타입을 판단하고 부가적인 기능을 부여해준다.

JUnit 3.x는 조금 복잡하긴 해도 상위 클래스인 TestCase를 따라가서 어떻게 이 코드가 실행될지를 파악하고 싶다면 어렵지 않게 그 동작방식을 이해할 수 있었다. 필요하다면 2.0까지의 스프링테스트처럼 템플릿메소드 패턴을 이용해서 작업흐름을 확장하고 적절한 훅 메소드를 제공해서 확장된 기능의 테스트를 만들도록 되어있다. 역시 상속한 코드를 따라가보면 별 어렵지 않게 그 흐름을 읽을 수 있다.

템플릿 패턴과 전략패턴의 왕자 SpringMVC도 그랬다. 프로퍼티를 보면 어떤 기능을 확장해서 쓸지가 한 눈에 보였다. 계층구조를 따라가며 확장되가는 플로우 구조를 파악하면 반나절 정도면 SpringMVC의 전체 흐름을 꿰는 것은 평균수준의 개발자라면 별 어려운 일도 아니다. 그리고 자기 입맛에 맞게 그것을 어떻게 확장해서 쓸지를 머리 속에 그려볼 수 있다. 작업 플로우를 확장하고 싶으면 적절한 단계의 훅 메소드를 상속해서 final로 막고 거기서 자신의 흐름을 만들 후 새로운 확장용 훅 메소드를 제공해주면 그만이다. 기능적인 확장이라면 DI를 이용해 맘것 쓰세요하고 제공해주는 각종 프로퍼티들에 관련 인터페이스를 구현한 기능을 얼마든지 만들어 넣으면 된다.

하지만 MAC(MultiActionController)가 나오면서부터 이상해졌다. CoC라고 하는데, 이게 영 확장도 변경도 하기 힘들다. 3년전에 리플렉션 API로 떡칠이 되어있는데다 final로 있는대로 다 막아버린 “확장금지” MAC를 굳이 확장해서 기능을 추가하려고 어쩔 수 없이 코드를 통채로 배껴서 고쳐서 써야 했을 때의 씁쓸한 마음이 생각난다.

@MVC의 @RequestMapping이니 @ModelAttribute등을 처리하는 클래스를 열어봤을 때도 비슷한 마음이었다. 성능을 생각해서 리팩토링을 일부러 안한 부분까지는 이해는 하겠는데, 이게 무슨 3-5중 중첩 if 문은 기본이고, DI는 극히 제한적으로 허용되고, 클래스의 코드를 직접 고치지 않고는 그 기능을 확장하기 힘들게 만들어진 코드를 보고 얼마나 실망했는지 모른다.

생각해보면 이게 다 애노테이션과 메타프로그래밍을 써서 기존에 OO방식을 써서 해결하던 것을 대치하면서 모두 발생한 일이 아닌가 싶다. 물론 사용자는 편하다. 단, 잠깐만 편하다. 상속도 안하고, 인터페이스 구현도 없는 POJO라서 편해요라고 하는 것도 순간이다. 애노테이션과 CoC로 범벅이 되어있는 Spring2.5+의 @MVC 컨트롤러와 기존 Controller인터페이스 하나만 구현하면 되는 가장 기본적인 제한만 가지고 자유롭게 확장할 수 있던 구식 MVC와 비교해서 어느 것이 정말 사용하기 편한지 곰곰히 생각해보자. 당장에 후다닥 만들어서 쓰기엔 MAC니 @MVC가 나을지 모르겠다. 하지만 그걸 이용해서 범용적인 테스트를 만든다거나, 특정 request패턴을 따르는 컨트롤 로직을 부여한다거나, 모델이나 커맨드를 적절히 조작해주는 기능을 만들려고 해보면 아마도 @MVC는 스프링자체를 직접 손대지 않는한 거의 불가능하다.

JUnit은 안그런가? JUnit 4.x는 애노테이션을 적용하기 시작하면서 이미 그 프레임워크의 매력을 잃었다. 코드를 보면 실망스럽다. 핵심 테스트 러너인 BlockJUnit4ClassRunner을 보면 Conditional Factory 패턴의 적용한 코드가 나온다. 애노테이션을 읽어봐서 있으면 기능을 추가하고 없으면 말고 뭐 그런 식이다. 하나하나 사용할 애노테이션이 이미 다 코드에 박혀있다. 확장하려면? 코드를 직접 고치는 것 말고는 방법이 없다. @Inteceptor가 등장했으니 그걸로 유연하게 전체구조를 바꾸어 준다면 어찌될지 모르겠지만, JUnit5.0이 나오면서 명분을 가지고 설계를 통채로 개선하기 전에는 불가능할 것이다.

@RequestMapping의 매핑 알고리즘을 추가하거나 바꾸려면? @MVC의 1/3쯤은 뜯어고쳐야 할 것이다.

그 안에는 무수히 많은 애노테이션을 사용하는 메타프로그래밍과 그 메타 정보를 가지고 플로우를 직접 제어하는 코드들이 등장한다. OO가 제거해줬다는 if 문장이 그 덕분에 다시 출현해서 활동을 재개하고 있는 것이다. 애노테이션은 인터페이스인듯 생겼고, 상속도 되지만 딱 그 뿐이다. 그 안에 로직을 담을 수도, 그대로 가져다 사용할 수도 없다. 어느 곳에선가 애노테이션을 읽고 그걸로 조건을 판단해서 다른 코드를 실행하거나, 제어하거나, 성격을 부여해주거나 해야 한다. 기존의 OO적인 수단을 대치하는 것으로 사용되기 쉽상이다.

다형성도 필요없다. 애노테이션과 CoC로 적절히 생긴모양(메타정보)를 파악해서 스마트 덕 타이핑도 가능하다. 점점 클래스 타입도 별 의미가 없어질지도 모르겠다. 어쩌면 코드는 애노테이션에 담긴 메타정보를 가지고 머리를 굴리지 않으면 정말 어떤 일이 일어날 것인지 이해하기는 점점 힘들어질 것이다. 이젠 수퍼클래스나 사용할 인터페이스의 API문서가 아니라, 애노테이션을 해석하고 뒤치닥 거리를 해주는 관례가 담긴 정책문서를 보고 개발을 해야 할지도 모르겠다.

처음은 편하겠지만. 딱 거기까지이다. 뭔가 다른 레벨에서 기능을 확장하고, 만들어진 POJO를 사용하고 싶다면 애노테이션을 사용해서 동작하는 복잡-지저분한 코드의 프레임워크가 하고있는 노가다를 흉내내야 할 수 밖에 없다. 수많은 if 문을 써야 하면서 말이다.

오랜만에 살펴보는 3.0 개발현황.

아직도 M2가 마무리되지 않고 있다. 여러번 추가 이슈가 등록이 되어 처리되고 있고, 이슈에 등록되지 않은 다양한 기능의 추가와 polishing, 문서작업 등이 계속 올라오고 있는 중이다. 최근에 "M2 release를 위한 준비"라는 코멘트를 가진 commit이 있었으니 조만간 출시되리라 기대해본다.

사실 M2에서 가장 바라는 것이 있다면 최신 기능에 대해서 업데이트된 레퍼런스 문서가 포함되는 것과 새로운 3.0의 기능들이 충실하게 사용된 샘플이다. 2.0시절에 등장했던 맛보기 샘플 같은 것이라도 만들어주면 안될까.

최근 유겐의 작업은 주로 코드의 Java5로 업그레이드 또는 Java5의 신기술을 활용한 API추가, 그런 과정에서 새롭게 발견된 버그 픽스, 코드 정리하기 등등이다. M3에서 새로운 기능을 많이 추가하기 위해서 M2에서 기존 코드를 안정적이고 탄탄하게 다져놓으려는 의도인 듯 하다.

그리고 스프링에서 공식적으로 사용하는 Hibernate의 버전이 3.3으로 바뀌었다.

지난 12월 M1 공개이후 두달 이상을 끌고 있는 M2 작업이 어서 마무리 되었으면 좋겠다.

아래는 현재까지 M2의 변경된 기능에 대해서 최신 change log에 나온 내용이다. 여기에 추가해서 최근에 RestTemplate 기능이 포함됐다. REST 방식의 호출을 하는 client코드를 만들 때 사용할 수 있는 스프링 template 스타일의 기능이다. 내부적으로 OXM 추상레이어를 사용해서 동작하도록 설계되어있다. 

Changes in version 3.0.0.M2 (2009-02-20)
—————————————-

* refined OSGi version constraints for "javax.annotation" and "junit.framework"
* revised expression parser API design
* added SimpleThreadScope implementation
* "systemProperties" bean is not considered a default match for type Properties anymore
* registered plain singletons will be fully matched according to their qualifiers
* @Qualifier value matching takes chained aliases of target beans into account as well
* SimpleAliasRegistry’s "getAliases" method returns transitive aliases now
* pre-converted property values are preserved more eagerly for re-created beans
* ASM-based AnnotationMetadata fully resolves class arguments and enums into Java types
* ProceedingJoinPoint resolves parameter names using ASM-based parameter name discovery
* MethodInvocations and ProceedingJoinPoints always expose original method (not bridge)
* bridge method resolution works with Hibernate-generated CGLIB proxies as well
* generic collection type resolution respects upper bound (e.g. ? extends Number) as well
* TypeUtils detects variations of ParameterizedType/GenericArrayType assignability as well
* ReflectionUtils findMethod detects methods on "java.lang.Object" as well
* UrlResource eagerly closes HTTP connections in case of "getInputStream()" failure
* PathMatchingResourcePatternResolver avoids NPE when initialized with null ClassLoader
* all "taskExecutor" bean properties now accept any "java.util.concurrent.Executor"
* added "Future submit(Runnable)" and "Future submit(Callable)" to AsyncTaskExecutor
* SimpleAsyncTaskExecutor supports a custom "java.util.concurrent.ThreadFactory"
* SchedulingTaskExecutor interface extends AsyncTaskExecutor now
* added ThreadPoolExecutorFactoryBean (exposing the native ExecutorService interface)
* added ExecutorServiceAdapter class as a standard wrapper for a Spring TaskExecutor
* reduced backport-concurrent support to TaskExecutor adapters
* added @Async annotation and AsyncAnnotationAdvisor (namespace support coming in M3)
* EJB 3.1′s @Asynchronous annotation gets detected and supported by default as well
* ApplicationListener beans get obtained on demand, supporting non-singletons as well
* ApplicationListeners will be called in the order according to the Ordered contract
* generified ApplicationListener interface, narrowing the event type to be received
* introduced SmartApplicationListener interface for supported event/source types
* generified Transaction/Hibernate/Jdo/JpaCallback with generic "doInXxx" return type
* HibernateOperations uses generic parameter/return types where possible
* JdoOperations uses generic parameter/return types where possible (following JDO 2.1)
* removed "flush" operation from JdoDialect (fully relying on JDO 2.0+ compliance now)
* added JDO 2.1 compliant StandardPersistenceManagerProxy/SpringPersistenceManagerProxy
* Spring-created EntityManagers support JPA 2.0 draft API ("unwrap", "getQueryBuilder")
* Spring initiates JPA 2.0 query timeout with remaining Spring transaction timeout
* added support for WebSphere’s ResourceAdapter-managed messaging transactions
* made SpringBeanAutowiringInterceptor callback signature compatible with WebSphere
* WebSphereUowTransactionManager preserves original exception in case of rollback
* added "flush()" method to TransactionStatus and TransactionSynchronization interfaces
* test context manager automatically flushes transactions before rolling back
* DefaultLobHandler uses explicit Blob/Clob access for reading when "wrapAsLob"=true
* fixed JmsException/JmsUtils to fully avoid NPEs in case of cause messages being null
* fixed MessageListenerAdapter’s "getSubscriptionName()" to work without delegate as well
* fixed HTTP invoker to support resolution of multi-level primitive array classes again
* introduced OXM support package (originating from Spring Web Services)
* introduced OXM-based MarshallingMessageConverter for JMS
* introduced OXM-based MarshallingView for Spring MVC
* refined @PathVariable handling in MVC handler methods
* updated Spring Portlet MVC infrastructure and mocks for Portlet API 2.0
* added resource and event methods to Portlet HandlerAdapter/HandlerInterceptor
* added resolveException method for resource requests to HandlerExceptionResolver
* introduced Resource/EventAwareController subinterfaces of Portlet Controller
* introduced @Action/@Render/@Resource/@EventMapping annotations for Portlet MVC
* added @RequestHeader support for Portlet MVC
* introduced @CookieValue annotation for Servlet and Portlet MVC handler methods
* @RequestMapping type-level param constraints taken into account consistently
* optional boolean parameters in MVC handler methods resolve to "false" if not present
* "url" macro in "spring.ftl" performs standard Servlet URL encoding automatically

이번 여행을 떠나기 전에 가장 고민했던 것은 무거운 DSLR 가방을 가져갈 것인가 말 것인가 였다. 가방 3개를 들고 이리저리 뛰고, 뭔가 남기고 전달해야 하기 때문에 수시로 카메라를 꺼내고 넣고 했던 이전 기억들이 그다지 좋지만은 않아서 과감하게 카메라를 놓고 오기로 했다. 게다가 다른 분들이 다 디카를 가져올 테니까 얻어 쓰면 될테니. 잘한 선택이었다.

케누 형이 올린 사진들 중에서 몇장…

스프링의 최신 모토인 Weapons for the War on Java Complexity. Cmplexitania와 전쟁을 벌이려는 스프링과 기타 스프링소스 제품이 흥미롭게 그려져있다.

 

첫날 파티 시간에 만난 캐나다와 미국에서 온 중국계 개발자들. 혼자 가서 만나고 있는데, 기선이와 영회,케누 형도 와서 즐거운 얘기를 나누었다. 젤 오른쪽은 시애틀에서 온 폴. 가운데 클라라라는 이름의 여자와 그 뒤의 남자 둘은 캐나다 토론토의 모 대학에서 함께 일하는 사람들이다. 컨퍼런스에 가보면 중국계 현지인 개발자들이 많다. 말투로 보아서는 현지에서 태어난 2세는 아니고 아마 유학을 왔다가 취업을 해서 살고 있는 사람들이 많은 듯. 어쨌든 같은 동양계라 만나면 좀 더 편하다. 클라라가 할 줄 아는 한국말은 "비빔밥"과 "감자탕"이라고.

 

이번에 함께 오게되 친해진 전 OKJSP (앞으론 OKSPRING) 교주 케누 광남이 형. 출생의 비밀이 있는 것인지 나이와는 다른 동안과 순수한 모습으로 사람들을 즐겁고 편안하게 해주는 것이 장점. 스프링의 매력에 풍덩 빠뜨리려고 무지 모력했는데… 두고 봐야겠다.

 

스프링 오픈소스의 창시자이자 스프링 개발의 90% 이상을 혼자 담당하고 있는 33살의 엄친아 유겐 할러와 한장. 거기서 이렇게 붙잡고 사진 찍는 사람은 우리들 뿐이었다.  유겐이 없었다면 지금의 스프링은 없다. 그의 코드를 보며 감탄한지 벌써 5년째… 아내인지 여친인지 미모의 여성과 키스를 나누는 것을 기선이가 포착.

 

내가 제일 좋아하는 스프링 서적인 Pro Spring(1판만, 2판말고)의 저자 Rop Harrop과도 한 컷. 그 옆엔 까칠해 보이지만 사실은 여리고 순진한 안녕해군. 지난 3년간 S1 가지고 꼬셨는데 결국 올해 착한 고객사를 만난 덕에 시간을 내어서 참석했다.

 

둘째날 저녁에 만난 벤 알렉스. 같은 호주에서 온 사람이고, 내가 무지 좋아하는 아씨지의 개발자인지라 꼭 한번 만나고 싶었으나, 보통 컨퍼런스에서 발표때 말고는 얼굴 보기 힘들어서 아직까지 인사를 못했는데, 영회가 KSUG 명함 주겠다고 펍의 한쪽 자리에서 스프링소스 직원들과 즐거운 시간을 보내고 있던 벤을 끌고 와버렸다. 볼이 발그스름한게 영회랑 비슷한데.. 오후에 해변에서 놀았던가? 벤이 호주에서 온 사람들도 몇 있다고 했는데, 누군지 알 길이 없어서 결국 못만났다. 아시아-태평양 지역 책임자라 홍콩, 싱가폴 같은데로 많이 여행을 하는데, 영회가 한국에 한번 초대하겠다고 벼르고 있다. 빵빵한 스폰서만 있으면 제주도에서 컨퍼런스를 열겠다는… 가운데 미모의 여성은 본인이 누구인지 어디서 온 사람인지 밝히지 말라고 신신당부를 하셔서, S사의 P님이라고 밖에 못 남기겠다. 세계적으로도 극히 드문 스프링을 잘 하는 여성개발자이다. 그리고 케누형.. 사람 얼굴 잘나오게 제발 플래쉬좀.

 

셋째날 풀 파티 때, 유일하게 수영장에 뛰어든 세마리 북극곰들. 표정은 즐거워보이지만 사실 세찬 바람에 매우 떨고 있다.

 

리조트 사진. 이건 숙소동이고, 저 옆에 컨벤션 센터가 연결되어있다. 가족과 함께 즐기기에는 최고의 리조트이다.

 

파티 때 바닷가에서 정말 우연히 만난 Spring in Action 1,2의 저자 Craig Walls와 두 딸. 온 가족이 함께 와서 시간을 보내는 듯 하다. 딸들이 정말 귀엽다. 1판이 번역된 것은 알고, 책도 가지고 있다고 한다(근데 왜 그리 무겁냐고…). 2판이 번역되었다는 사실은 아직 모르는 듯 해서 영회가 열심히 설명해줬다. 영회의 추천사가 들어간다. 귀여운 둘째는 사진찍는 케누형이 무섭다고 아빠한테 가자고 징징.

 

폐회식을 하는 가 해서 기다리고 있는 중. 기존에 NFJS가 직접 행사 진행을 했는데, 이번엔 스프링소스에서 직접 기획하고 진행한 듯 하다. 솔직히 NFJS가 할 때가 훨 낫다. 적어도 폐회식하면서 iMac 한대 추첨해서 주는 쎈스가 있었는데 말이다. 결국 마지막 세션으로 그냥 스르르 마무리.

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha