Whiteship's Note

'Spring DM'에 해당되는 글 117건

  1. 2009.07.11 스프링 슬라이스(Spring Slice)
  2. 2009.03.20 Our plans for building OSGi application 요약
  3. 2008.12.08 스프링 + OSGi(스프링 DM) 개발 필독 레퍼런스 3종 세트 (6)
  4. 2008.11.27 오호.. 스프링소스 manifest 헤더가 OSGi에 추가되는군요
  5. 2008.11.25 스프링 DM 1.2.0 m2 배포
  6. 2008.11.23 OSGi uses 충돌 감지하기
  7. 2008.11.23 OSGi "uses" 지시어 이해하기
  8. 2008.11.11 SpringSource DM Server 실습할 것 1
  9. 2008.11.09 SpringSource Application Platform(S2AP)은?
  10. 2008.10.21 OSGi 툴 세트 Pax
  11. 2008.10.16 스프링 DM 프로젝트 빌드하기
  12. 2008.10.04 Spring DM 1.1.2 릴리즈~
  13. 2008.09.25 Shared Mutable State (2)
  14. 2008.09.25 The Price of Freedom
  15. 2008.09.25 Concurrency and OSGi
  16. 2008.09.15 OSGi 개발에 PDE가 필요한가?
  17. 2008.09.05 스프링 DM 1.2.0 M1 배포
  18. 2008.08.25 OSGi에서 SessionFactory(Hibenate) 사용하기
  19. 2008.08.20 OSGi 패키지가 아니라 서비스야 말로 진정한 Dynamic
  20. 2008.08.19 흠... Hibernate Annotation 번들 왜이래 왜 ㅠ.ㅠ
  21. 2008.08.18 pom.xml에서 bnd 설정 파일 분리하기
  22. 2008.08.14 OSGi 기반 프레임워크과 애플리케이션 아키텍처 진화 과정 (2)
  23. 2008.08.14 OSGi에서 Hibernate의 SessionFactory 문제 (2)
  24. 2008.08.13 번들을 찾으려면.. http://www.springsource.com/repository/ (2)
  25. 2008.07.31 맥북에서도 Spring DM 웹 번들 설치 성공
  26. 2008.07.29 Spring DM 1.1.1 배포
  27. 2008.07.23 스프링 DM 모듈에서 단위 테스트하기(링크)
  28. 2008.07.20 Late Binding in Java (2)
  29. 2008.07.20 Whiteship's 스프링 DM 레퍼런스 1.0 m3 배포
  30. 2008.07.13 bnd에 번들 실행환경 설정하기

스프링 슬라이스(Spring Slice)

Spring DM/etc : 2009.07.11 11:36


참조
http://blog.springsource.com/2009/07/10/pluggable-styling-with-springsource-slices/
http://blog.springsource.com/2009/06/22/modular-web-applications-with-springsource-slices/

음.. 웹 애플리케이션을 OSGi 번들로 구성할 때, web 번들 하나랑 기타 서비스 번들 여러 개로 쪼개야 하는구나.. 라고 만 생각하고 있었는데, 그렇지 않았네요.

스프링 슬라이스를 이용해서 하나의 웹 애플리케이션에서 여러 개의 웹 번들을 구성할 수 있도록 해주는 프레임워크라고 보면 될 것 같습니다. 웹 번들이 여러 개라고 해서 ServletContext가 여러 개 생기는 건 아니고, parent/child 구조로 여러 슬라이스가 호스트의 ServletContext를 이용해서 쓰게 해주는가 봅니다. 설정은 호스트 쪽 web.xml 에 스프링 슬라이스 필터를 추가하면 되고, 슬라이스 쪽에서는 Manifest.mf에 Slice-Host와 Slice-ContextPath를 설정하면 되는 정도로 간단한 편인듯 하네요.

요즘은 이것 저것 볼 여력이 없기 때문에.. 이정도만 살펴보고 패스~
신고
top


Our plans for building OSGi application 요약

Spring DM/etc : 2009.03.20 20:51


참조 및 요약: Our plans for building OSGi application

OSGi 빌드 요구 사항

- 의존성 메타 데이터 중복 제거: 사용하는 빌드에 따라 pom.xml, ivy.xml에도 의존성을 정의하고 MANIFEST.MF 파일에도 의존성을 정의하는데 그러지 말고 한 곳에서 의존성을 정의하는 방법이 필요하다.

- 기존의 빌드 시스템 활용: 사용자들은 기존의 방식대로 메이븐 또는 Ant 빌드를 사용하고 싶어한다.

- 자동으로 MANIFEST.MF 파일 생성하기

- OSGi MANIFEST.MF 파일에서 의존성 가져오기: MANIFEST.MF 파일을 중심으로 의존성을 해결할 때 필요하다.

시나리오

1. 메이븐 + 이클립스 - pom.xml-주도: OSGi Manifest 파일은 메이븐 또는 이클립스 플러그인을 사용하여 자동생성한다. Manifest 생성에 필요한 대부분의 정보는 자바 코드에서 얻을 수 있지만 버전 정보는 그렇지 않다.  버전 정보는 pom.xml에서 그 정보를 가져올 수 있겠다. Manifest 템플릿을 통해서 그런 일을 할 수 있고 OSGi 속성이나 커스텀 헤더를 추가할 수 있겠다.

2. Ant + Ivy + 이클립스 - ivy.xml-주도: Ant 태스크로 manifest 파일을 생성한다. 위의 방법과 비슷하지만 단점으로 아직 이클립스에서 Ivy 2를 지원하는 플러그인이 없다. 개발자가 ivy.xml 파일을 작성하면 이클립스 플러긴을 사용해서 manifest를 만들고 이클립스 클래스패스를 자동으로 수정해주도록 한다.

3. 메이븐 + 이클립스 - MANIFEST.MF-주도: 개발자가 MANIFEST.MF 파일을 직접 또는 플러그인을 통해서 작성하면 그 파일을 기반으로 의존성을 처리한다. 이때 이클립스의 클래스패스 컨테이너를 이용한다. 테스트를 지원하기 위해 TEST.MF 파일에는 테스트에 필요한 의존성을 정의할 수 있게한다. 여기에 정의한 의존성은 테스트할 떄에만 가져온다. 남은 부분은 이것을 메이븐에 어떻게 적용하느냐 인데 현재 두 가지 옵션을 고려중이다. 하나는 pom.xml을 생성하는 것이고 다른 한 방법은 메이븐의 의존성 처리와 연동 또는 그것을 교체하는 것이다.

4. Ant + Ivy + 이클립스 - MANIFEST.MF-주도: 3번 방법과 비슷하고 2번의 단점인 Ivy 2 이클립스 플러긴 지원이 필요없어진다. Manifest-주도 이클립스 클래스패스 컨테이너를 사용할 것이기 때문이다.

OSGi 빌드 툴

- Bundlor: spring build 프로젝트에서 개발 중이며 몇 주후에 첫 번째 버전을 공개할 예정. 번들을 만들어 주며, manifest.mf 파일을 만들어 준다. http://www.springsource.com/repository/app/ 이곳에 있는 대부분의 번들을 이 툴로 만들었다. manifest 템플릿을 제공하여 커스터마이징 할 수 있게 해준다.

- BundlorEclipse: 이클립스 플러그인으로 Bundlor 기능을 이클립스에서 직접 사용할 수 있다. 소스 코드를 저장 버튼을 눌러 저장할 떄마다 manifest를 계속해서 수정해준다.

- 오프라인 의존성 리졸버

- Manifest 클래스패스 컨테이너

- 메이븐/Ivy 의존성 리졸버/pom.xml/ivy.xml  생성기

왜 bnd를 사용하지 않고 Bundlor를 만들었나?

처음에는 spring dm 프로젝트에서는 bnd를 사용했지만 다음의 부가 기능이 필요해서 만들었다.
- JDT-기반 코드 스캐닝
- 일부(Partial) 코드 처리하기
- 계속적인 manifest 생성

이클립스가 아닌 다른 IDE 활용하기

이클립스 말고 IntelliJ나 NetBeans 사용자를 위해 그쪽 팀에 Bundlor 핵심 라이브러리를 커밋했다. 그 결과 어떤 IDE 에서도 OSGi 개발 툴을 사용할 수 있게 됐다.

추가 요구사항

- 벌크 번들 생성

- 저장소-기반 코드 완성: dm 서버 저장소를 기반으로 소스 코드에서 자동 완성을 하면 자동으로 import 문을 추가해주고 Manifest에도 import 문을 추가해준다.
신고
top


스프링 + OSGi(스프링 DM) 개발 필독 레퍼런스 3종 세트

Spring DM/etc : 2008.12.08 14:13


스프링 DM 레퍼런스: http://static.springframework.org/osgi/docs/current/reference/html/
스프링 DM 서버 사용자 가이드: http://static.springsource.com/projects/dm-server/1.0.x/user-guide/html/index.html
스프링 DM 서버 개발자 가이드: http://static.springsource.com/projects/dm-server/1.0.x/programmer-guide/html/index.html

맨 위에껀 제가 번역/편역 해서 올린적이 있는데 지금은 또 많이 바껴서 다시 봐야겠고, 아래 두 문서도 분량이 얼마 되지 않으니 금방 읽어 보실 수 있습니다. 나머지 두 문서도 한글화를 할까 생각해봤는데 그럴 여유가 없더군요. 나중에 시간이 되면 블로그에 간단 요약 정도는 가능할지도 모르겠습니다.

읽는 순서는 일단 DM 레퍼런스를 보시는게 좋겠구요. 그 다음은 별로 순서가 필요없을 것 같습니다. 서버 사용법이 궁금하면 사용자 가이드를 보고, 개발할 때 dm 서버가 어떤 도움을 주는지 궁금하시다면 개발자 가이드를 보시면 됩니다. 개발자는 당연히 두 개 다 봐야겠죠? ㅋ

스프링을 사용하여 OSGi 개발이 상당히 편리해지고 있지만, 역시 핵심은 모듈화를 어떻게 할 것인가 인데.. 이건 삽질을 좀 해봐야겠습니다.

어찌됐든, dm 서버로 인해서 한층 OSGi 개발이 편리해진 것 같습니다. 손수 타겟 플랫폼 만들지 않아도 되고, 로깅 걱정 안 해도 되고, 에러 분석도 해주고, 배포 방법 다양하고, PAR 패키징 지원해서 여러 번들을 애플리케이션 별로 구분 할 수도 있고, 이클립스에서 편하게 사용할 수도 있으니 말이죠.

전 이제 자야겠습니다. 한국은 오후 2시 일텐데;;
신고
top


오호.. 스프링소스 manifest 헤더가 OSGi에 추가되는군요

Spring DM/etc : 2008.11.27 21:57


참조: http://blog.springsource.com/2008/11/27/springsource-manifest-headers-registered-with-osgi/

OSGi 진영에서 public registry에 밴더별 헤더를 등록해서 중복하는 헤더를 방지하고자 하는 것 같습니다.

추가된 스프링소스의 헤더 7개
- Import-Bundle
- Import-Library
- Module-Scope
- Modeul-Type
- Web-Contextpath
- Web-DispatcherServletUrlPatterns
- Web-FilterMappings

추가된 bnd 헤더 2개
- Include-Resource
- Private-Package

오호~~ 귿~~ 다시 한 번 스프링 DM 공부를 하고 가야겠습니다. S1A에 가서 스프링 DM과 DM 서버 관련 세션을 집중적으로 듣고 올 계획입니다. 이틀 남았네 빡쎄게 공부해야겠군..
신고
top


스프링 DM 1.2.0 m2 배포

Spring DM/etc : 2008.11.25 00:52


참조 : http://www.springsource.org/node/837

눈에 띄는 변경 사항은
- 일단 얼마전에 배포된 스프링 2.5.6을 사용하도록 변경 했다는 겁니다.
- compendium 네임스페이스를 추가했다는데..;; 뭔지 모르겠습니다. 알아봐야겠네요.
- shutdown 알고리즘을 개선했다는 군요.

나머진 잘 눈에 안 들어오고 모르겠네요~

ps: 이사 할 땐 손톱을 약간 길게 깍으세요. 평소처럼 깍았는데 이사하면서 손 끝이 부어서 그런가 굉장히 따갑습니다. ㅠ,ㅠ
신고
top


OSGi uses 충돌 감지하기

Spring DM/etc : 2008.11.23 18:39


참조 및 번역: Diagnosing OSGi uses conflicts

Glyn은 최근에 "OSGi "uses" 지시어 이해하기"를 제공했다. 나(Rob Harrop)는 uses 제약 위반 원인을 좀 더 자세히 살펴보고 여러분 애플리케이션에서 발생하는 uses 문제 해결에 유용한 몇 가지 팁을 제공하고자 한다.

나는 대부분의 예제에서 dm Server 보다는 이퀴녹스를 사용하려고 한다. 그 이유는 uses 제약사항이 dm Server에 한정적인 것이 아니고 모든 OSGi 사용자와 관련된 것이기 때문이다. 이 블로그 마지막에는, dm Server에 구축된 매우 똑똑한 제약 사항 실패 진단 몇 가지를 보여줄 것이다.

의존적인 제약 불일치(Dependent Constraint Mismatch)


가장 흔한 uses 위반은 한 개 이상의 의존적인 제약 사항끼리의 불일치 때문이다. 예제로 다음 세 개의 manifest를 살펴보자.

Manifest-Version: 1.0
Bundle-Name: Spring Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: spring
Bundle-Version: 2.5.5
Export-Package: spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
Import-Package: eclipselink;version="[1.0, 2.0)"

Manifest-Version: 1.0
Bundle-Name: EclipseLink 1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: eclipselink
Bundle-Version: 1
Export-Package: eclipselink;version="1.0.0"

Manifest-Version: 1.0
Bundle-Name: EclipseLink 2 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: eclipselink
Bundle-Version: 2
Export-Package: eclipselink;version="2.0.0"

스프링 번들 한 개와 두개의 eclipselink 번들이 있다. 물론 실제 번들은 아니다. spring 번들은 [1.0, 2.0) 버전 번위의 eclipselink 패키지를 사용한다. 분명히 오직 eclipselink_1 번들만이 이 제약 사항을 만족한다. 이제 다른 두 개의 애플리케이션 manifest를 살펴보자.

Manifest-Version: 1.0
Bundle-Name: App1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app1
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="[1.0, 1.0]"

Manifest-Version: 1.0
Bundle-Name: App2 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app2
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="[2.0, 2.0]"

app1은 exlicpselink [1.0, 1.0] 범위를 참조하고, app2는 eclispelink [2.0, 2.0] 범위를 참조한다. 만약 이 두 개의 번들을 이퀴녹스에 설치하고 app 번들들을 start 시도하면, 콘솔에서 다음과 같은 결과를 확인할 수 있다.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
2       RESOLVED    spring_2.5.5
3       RESOLVED    eclipselink_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       ACTIVE      app1_1.0.0
6       INSTALLED   app2_1.0.0

sprig과 eclipselink 번들들은 모두 잘 리졸브 된 걸 볼 수 있다. app1 번들은 시작(start)했지만, app2 번들은 시작하지 못했다. 이유를 알아보기 위해 diag 커맨드를 사용할 수 있다.

osgi> diag app2
file:/Users/robharrop/dev/resdiag/uses/app2/bin [6]
  Package uses conflict: Import-Package: spring.orm.hibernate; version="0.0.0"

여기서 우리는 spring.orm.hibernate 패키지를 임포트하는 부분에서 uses 충돌로 인해 해당 번들을 리졸브 할 수 없다는 것을 알 수 있다. 이것은 app2에서 spring.orm.hibernate를 임포트하는 것을 안 된다는 것이다. 그 이유는 다른 import로 인해 spring.orm.hibernate를 제공하는 번들의 uses 제약 사항이 깨질 수 있기 때문이다.

이를 진단하는 과정 처음으로 할 일은 spring.orm.hibernate 번들의 가용한 공급자를 찾아내는 것이다. 우리는 이미 해당 공급자가 spring 번들이라는 걸 알고 있지만, 만약 공급자를 모른다면 packages 커맨드를 사용할 수 있다.

osgi> packages spring.orm.hibernate
spring.orm.hibernate; version="2.5.5"<file:/Users/robharrop/dev/resdiag/uses/spring/bin [2]>
  file:/Users/robharrop/dev/resdiag/uses/app1/bin [5] imports

여기서 spring.orm.hibernate 패키지를 번들 2에서 공급(export)했다는 것을 알 수 있다. 이 정보를 가지고 번들 2의 spring.orm.hibernate에서 uses 지시어에 어떤 패키지가 등록되어 있는지 확인할 수 있다.

osgi> headers 2
Bundle headers:
 Bundle-ManifestVersion = 2
 Bundle-Name = Spring Bundle
 Bundle-SymbolicName = spring
 Bundle-Version = 2.5.5
 Export-Package = spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
 Import-Package = eclipselink;version="[1.0, 2.0)"
 Manifest-Version = 1.0

여기서 우리는 uses에 있는 유일한 패키지 eclipselink 패키지가 범인이라는 걸 알 수 있다. 사실, 스프링 번들은 eclipselink [1.0, 2.0) 범위를 참조하는 반면 app2는 eclipselink [2.0, 2.0] 범위를 참조하는 걸 확인할 수 있다. 이 두 범위는 상충한다. app2는 스프링 번들이 사용하는 eclipselink와 동일한 버전을 연결할 수 없다.

uses 목록이 긴 경우는, 어떤 패키지의 제공자가 둘 이상인지를 확인하여 위반을 한 패키지 범위를 좁혀볼 수 있다. uses 제약을 위반 패키지를 제공하는 공급자는 반드시 둘 이상이다.

버전 불일치는 의존 제약 불일치의 유일한 원인이 아니다. 속성도 버전처럼 제약 문제를 발생 시킬 수 있다.

설치 순서 문제


앞선 예제를 다시 살펴보자. spring 번들의 manifest를 변경하여 eclipselink 2.0 패키지를 참조하도록 변경하고 app1은 1.0 이상의 모든 버전을 허용하도록 수정하여 문제를 수정해보자.

Manifest-Version: 1.0
Bundle-Name: Spring Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: spring
Bundle-Version: 2.5.5
Export-Package: spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
Import-Package: eclipselink;version="[1.0, 2.0]"

Manifest-Version: 1.0
Bundle-Name: App1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app1
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="1.0"

번들들을 설치하고 app 번들을 시작하면 큰 변화가 생긴걸 볼 수 있다.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       RESOLVED    eclipselink_2.0.0
4       ACTIVE      app1_1.0.0
5       ACTIVE      app2_1.0.0

이제 두 개의 app 번들 모두 시작 할 수 있다. 불행히도 좀 더 교묘한 이슈가 우리를 기다리고 있다. 설치 순서에 따라, 이 번들 집합체는 같이 실행되지 않을 수도 있다. 이를 실험해보기 위해서, spring, eclipselink_1과 app1을 한 묶음으로 설치하고 app1을 실행한다.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0

자 이제 eclipselink_2와 app2를 설치한다.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       INSTALLED   app2_1.0.0

app2 번들은 시작되지 않는다. diag 통해 왜 그런지 살펴보자.

osgi> diag app2
file:/Users/robharrop/dev/resdiag/uses/app2/bin [5]
  Package uses conflict: Import-Package: spring.orm.hibernate; version="0.0.0"

uses 충돌이 다시 발생했다. 이번에는 앞선 진단 과정이 아무런 도움이 되지 않느다. 의존성 제약 불일치가 없기 때문이다. 첫 번째에 모두 잘 리졸브 됐기 때문에 이건 이미 알고 있다.

이슈는 리졸루션 순서에 있다. 번들들은 두 덩어리로 나눠서 설치하고 리졸브 했다. 첫 번째 덩어리는 spring, eclipselink_1, app1 이고 두 번째 덩어리는 eclipselink_@와 app2다. (app1 번들을 시작(start)한 결과로..)첫 번째 덩어리가 리졸브 될 때, spring 번들은 esclipselink 패키지를 가져올 때 eclipselink_1 번들에 묶이게 된다. 이것을 콘솔에서 확인해보자.

osgi> bundle app1
file:/Users/robharrop/dev/resdiag/uses/app1/bin [3]
  Id=3, Status=ACTIVE      Data Root=/opt/springsource-dm-server-1.0.0.RELEASE/lib/configuration/org.eclipse.osgi/bundles/3/data
  No registered services.
  No services in use.
  No exported packages
  Imported packages
    spring.orm.hibernate; version="2.5.5"<file:/Users/robharrop/dev/resdiag/uses/spring/bin [1]>
    eclipselink; version="1.0.0"<file:/Users/robharrop/dev/resdiag/uses/eclipselink1/bin [2]>
  No fragment bundles
  Named class space
    app1; bundle-version="1.0.0"[provided]
  No required bundles

import packages 섹션에서 eclipselink 버전 1.0.0이 eclipselink_1 번들에서 가져온 걸 확인할 수 있다. 두 번째 덩어리를 설치하면 app2 번들은 eclipselink 버전 2를 필요로 하는데, spring이 이미 eclipselink 1.0.0 버전에 묶여 있어서 리졸브되지 못한다. 한 덩어리로 모든 번들을 설치하고 리졸브 할 때는, OSGi 리졸버가 spring.orm.hibernate의 uses 제약도 만족하면서도 다른 모든 제약사항을 만족하도록 시도할 것이다.

이 문제를 고치기 위해 우리 번들을 수정할 필요는 없다. 대신, 모든 번들을 한 덩어리로 설치하거나 spring 번들을 리프래쉬 하면 된다. 그렇게 해서 OSGi가 다시 리졸루션 과정을 거치도록 한다. 이제 eclipselink_2 번들이 설치되고 이번에는 다른 결과를 예상할 수 있다.

osgi> refresh spring

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       ACTIVE      app2_1.0.0

osgi> bundle spring
file:/Users/robharrop/dev/resdiag/uses/spring/bin [1]
  Id=1, Status=RESOLVED    Data Root=/opt/springsource-dm-server-1.0.0.RELEASE/lib/configuration/org.eclipse.osgi/bundles/1/data
  No registered services.
  No services in use.
  Exported packages
    spring.orm.hibernate; version="2.5.5"[exported]
  Imported packages
    eclipselink; version="2.0.0"<file:/Users/robharrop/dev/resdiag/uses/eclipselink2/bin [4]>
  No fragment bundles
  Named class space
    spring; bundle-version="2.5.5"[provided]
  No required bundles

spring 번들을 리프래시해서 app2 번들도 리졸브 된 걸 볼 수 있다. spring 번들에서 연결할 eclipselink 패키지가 eclipselink_2 번들의 2.0 버전으로 바꼈다.

dm 서버에서 uses 제약 사항

uses 제약 위반이 dm 서버에서 발생하면, 여러분이 해야할 분석 절차를 알아서 제공해준다. 특히 불일치하는 패키지를 담고 있을 가능성이 있는 의존성 제약을 식별할 때 도움이 된다.

Could not satisfy constraints for bundle 'app2' at version '1.0.0'.
 Cannot resolve: app2
  Resolver report:
    Bundle: app2_1.0.0 - Uses Conflict: Import-Package: spring.orm.hibernate; version="0.0.0"
      Possible Supplier: spring_2.5.5 - Export-Package: spring.orm.hibernate; version="2.5.5"
        Possible Conflicts: eclipselink

uses 제약사항은 엔터프라이즈 라이브러리에서 매우 흔히 사용하며 손수 실패 원인을 분석하는 것은 악몽같은 일이다. 특히, uses를 사용하는 패키지가 10 개 이상 있을 때는, 가용한 충돌을 판별하는 작업은 상당한 시간-낭비를 초래한다. 따라서 자동화 검진은 필수이며, 나는 dm 서버에서 진당 코드가 향상되어 흔히 발생하는 문제가 아무것도 아닌 것처럼 다룰 수 있게 되길 바란다.

다음 배포판에서는, 진단 도구를 dm 서버 이클립스 툴에 바로 포함시켜서 dm 서버에서 이런 문제들을 대부분 자동으로 분석하도록 할 수 있게 할 계획이다.
신고
top


OSGi "uses" 지시어 이해하기

Spring DM/etc : 2008.11.23 17:08


참조 및 번역: Understanding the OSGi "uses" Directive

스프링 DM 서버 또는 다른 어떤 OSGi 플랫폼 기반의 애플리케이션을 빌드 할 때, 여러분은 아마도 머지않아 "uses"라는 지시어를 보게 될 것이다. 이 지시어의 목적을 분명하게 이해하지 않는다면, 여러분은 언제 그것을 사용해야 하는지도 모를 뿐더러, "uses" 충돌("uses" conflict)로 인해 번들 resovle가 되지 않을 때 의문만 생길 것이다. 본 기사에서 "uses" 지시어를 이해하고, 언제 사용해야 하는지, 그리고 어떻게 "uses" 충돌을 디버깅하는지 살펴보겠다.

번들 리졸루션(Resolution)


OSGi는 일단 번들이 "리졸브"(resolve) 상태가 되도록 설계되어 있다. 클래스 캐스트 예외나 타입이 맞지 않아서 발생하는 그와 비슷한 문제들이 발생하지 않도록 해야 한다. 이는 OSGi가 각각의 번들마다 하나의 클래스 로더를 사용하기 때문에 사용자들이 타입 불일치 문제를 만나게 될 여지가 많다. 그래서 매우 중요하다.

런타임에 사용하려면 일단 클래스 로더에 의해 자바 타입이 로딩이 되어야 해당 타입의 클래스나 객체 같은 것을 사용할 수 있다. 런타임 타입은 타입의 전체 클래스 이름과 해당 타입을 정의한 클래스 로더의 조합으로 정의한다. 만약 동일한 전체 클래스 이름이 두 개의 다른 클래스 로더를 사용하여 정의되어 있다면, 두 개의 호환하지 않는 런타임 타입을 생성한다. 이런 비호환성으로 인해 두 타입의 어떤 "접촉"(contact)을 하게 될 경우 런타임 에러를 발생한다. 예를 들어, 이 두 타입 중 하나를 다른 타입으로 캐스팅을 시도할 때 클래스 캐스트 예외가 발생한다.

OSGi는 유일한 클래스 로더 기반 자바 모듈 시스템이 아니지만 지금까지 가장 성숙한 시스템이다. 즉 OSGi 설계자들은 오랫동안 힘들게 이런 종류의 문제들을 다려왔고 그 해결책을 OSGi 스펙에 포함시켜왔다. OSGi 설계는 이런 문제들을 애플리케이션 코드가 동작하기 전에 발경하는 것이다. 즉 리졸루션(resolusion)이라는 단계에서 말이다. 리졸루션(Resolution)은 자바와 같은 엄격한 타입 제한 프로그래밍 언어에서 애플리케이션 코드를 실행하기도 전에 특정 문제들을 발견할 수 있는 컴파일과 유사하다. 여러분의 번들을 resovle 하려면 가끔 머리가 아플 수도 있다 하지만 이는 클래스 캐스트 예외와 같은 런타임 에러 진단을 해준다.

그래서 번들 리졸브(resolve)는 무엇을 의미하는가? 이것은 번들의 의존성을 확인했다는 뜻이다. 일반적으로 해당 번들이 사용하는(import) 패키지를 공개한(export) 번들들을 찾았고 그 버전 제약을 만족시킨다는 뜻이다. 가장 명확한 제약 사항은 모든 공개된(export) 패키지 버전이 사용하려는(import) 패키지 버전 범위 내에 포함되어야 한다. 또 다른 제약 사항으로는 패키지 임포트(import)에 기술 할 수 있는 임의 속성이 그에 대응하는 패키지 익스포트(export) 속성과 일치해야 한다는 것이다.

여러 번들에 의해 공개된 패키지


우리가 곧 살펴볼 uses 지시어는 하나 이상의 번들에 의해 공개되는 패키지에서 발생하는 타입 불일치를 해결할 목적으로 사용한다. 어떤 한 번들의 타입을 다른 번들의 타입으로 사용할 필요가 있을 때, 런타임 타입이 호환되지 않기 때문에, 타입 불일치 문제가 발생한다. 예를 들어, 어떤 번들에서 다른 번들의 클래스 이름이 같지만 다른 타입으로 타입 캐스팅을 시도할 때 클래스 캐스팅 예외가 발생한다. 어떻게 이런 일이 발생할까? 번들은 동일한 패키지를 하나 이상의 번들에서 가져올(import) 수 없기 때문이다. 상충하는 타입을 접촉(contact) 시킬 어떤 방법이 있어야 한다. It happens by a type being passed "through" a type in another package..

어떤 타입을 다른 타입으로 전달(pasess through)하는 방법은 두 가지가 있다. 첫 번째 방법은 어떤 타입이 다른 타입을 명시적으로 참조하는 것이다,. 예를 들어, 다음은 org.bar 패키지에 있는 Bar 타입의 어떤 메소드는 org.foo 패키지의 Foo 타입을 참조할 수 있다.

public Foo getFoo();

어떤 타입을 다른 타입으로 암묵적으로 전달하는 두 번째 방법은 서브타입을 이용하는 것이다, 예를 들어, 다음은 서브타입을 참조하는 메소드 시그너쳐다.

public Object getFoo();

암묵적인 경우, 서브타입의 객체는 어느 순간에는 상충하는 타입으로 캐스팅될 것이다.

자바 코드 수준에서 그런 타입 불일치가 어덯게 발생하는가. 번들 manifest가 어떻게 생겼는지 살펴보자.

필요한 타입 Foo는 org.bar 패키지를 공개하는(export) 번들과 동일한 번들이 공개하거나

bundle-symbolicname: B
bundle-manifestversion: 2
export-package: org.foo,org.bar

또는 다른 번들(F)이 공개할 수도 있을 것이다.

bundle-symbolicname: B
bundle-manifestversion: 2
export-package: org.bar
import-package: org.foo

bundle-symbolicname: F
bundle-manifestversion: 2
export-package: org.foo

"uses" 지시어는 OSGi가 위와 같은 타입 불일치를 번들 리졸루션 과정에서 진단할 수 있도록 도입되었다.

"uses" 지시어


위와 같은 잠재적인 타입 불일치를 리졸루션 과정에서 찾아내기 위해, 자바 코스 수준에서의 명시적인 또는 암묵적인 타입을 그에 상응하는 번들 manifest에 선언해야 한다. 공개하는 패키지는 "uses" 지시어를 붙여서 해당 패키지가 참조할 패키지를 선언해준다.

위 예제에서, 공개하는 패키지 org.bar는 org.foo 패키지를 "사용"(use) 한다고 선언한다.


export-package: org.bar;uses:="org.foo"


"uses" 지시어에서 사용하는 패키지나 패키지들은 "uses" 지시어를 사용하고 있는 번들 manifest에서 공개(export) 또는 가져올(import) 패키지에 명시되어 있는 것들이어야 한다. 따라서 다음은 유효한 manifest지만


export-package: p;uses:="q,r", q
import-package: r


다음은 유효하지 않은 manifest다.(q 패키지를 export 또는 import 하고 있지 않기 때문에)


export-package: p;uses:="q,r"
import-package: r


추이적인 "ueses"


타입 참조는 추이적이다. 예를 들어, 타입 C를 참조하는 타입 B를 타입 A가 참조할 경우에, A의 사용자는 B를 통해서 C를 참조할 수 있다.

타입 참조가 이렇게 추이적이기 때문에, OSGi는 자동적으로 이를 고려했다. "uses" 지시어의 "추이적인 클로져"(transitive closure)라고 알려져 있는 것이 바로 그것이다. 이것은 "uses" 지시어를 사용하기만 하면 OSGi가 알아서 추이적인 타입 참조를 다뤄준다는 것이다.

예를 들어, 다음 번들 manifest를 보자


export-package: p;uses:="q,r", q;uses:="r"
import-package: r


문법에 맞다. 다음 번들 manifest는 "p에서 q", "q에서 r" 그리고 "(추이적으로) p에서 r" 타입 참조를 충분히 잘 표현한 것이다.


export-package: p;uses:="q",q;uses:="r"
import-package: r


(역자 주, 위랑 아래랑 같으니까 아래처럼 사용해도 된다는 뜻입니다.)

"uses" 충돌 감지하기(Diagnosing)


번들 레졸루션 과정은 모든 제약 사항을 확인하는 것이 주목적이다. 따라서 모든 "uses" 제약 사항이 만족하지 않을 경우 "uses" 충돌을 보고할 것이다. 스프링 dm 서버가 주는 진단 이슈는 이런 문제를 해결하는데 도움을 준다.

원리를 이해하기 위해 만든 예제를 살펴보자. 클라이언트 번들 C가 사용할 몇몇 유틸리티 번들 F와 B을 만들고 있다고 가정해보자. 새로운 버전의 F를 추가하고다음 mainfest들을 가지고 서버에 배포한다고 가정해보자.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: F
Bundle-Version: 1
Bundle-Name: F Bundle
Export-Package: org.foo;version=1

(역자 주, 버전이 1이니까 이전에 사용하던 F 유틸 번들 이겠네요.)

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: F
Bundle-Version: 2
Bundle-Name: F Bundle
Export-Package: org.foo;version=2

(역자 주, 버전이 2니까 이번에 새로 추가한 F 유틸 번들인가 봅니다.)

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: B
Bundle-Version: 1
Bundle-Name: B Bundle
Export-Package: org.bar;uses:="org.foo"
Import-Package: org.foo;version="[1,2)"

(역자 주, 이것도 유틸 번들인데, F 유틸 번들 1와 2가 공개하는(export) org.foo 패키지 버전 1 이상 2 미만을 사용하고 있군요. 결국 F 유틸 번들 버전 1을 사용하겠네요.)

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: C
Bundle-Version: 1.0.0
Bundle-Name: C Bundle
Import-Package: org.bar,org.foo;version="[2,3)"

(역자 주, 이건 클라이언트 번들인 C 인데 org.foo 패키지를 사용하는 데 그 버전이... 이런.. 2 이상 3 미만을 사용합니다. 그러면 이 번들은 지금 새로 설치한 F 유틸 번들 버전 2를 사용하게 됩니다. 뭔가 꼬였군요. 왜냐면 여기서 또 사용하기로(import)되어 있는 org.bar 패키지에서는 F 유틸 번들 버전 1의 org.foo 패키지를 사용하니까요. 두 패키지가 호환되지 않자나요. 같은 패키지지만 다른 번들이 공개한 거니까 런타임 타입이 다르죠. 왜냐면 클래스로더가 다르니까.)

C 번들을 설치하려고 하면, dm 서버는 다음과 같은 로그 메시지를 출력한다,

<SPDE0018E> Unable to install application from location 'file:/xxx/C.jar/'. Could not satisfy constraints for bundle 'C' at version '1.0.0'.
Cannot resolve: C
Resolver report:
Bundle: C_1.0.0 - Uses Conflict: Import-Package: org.bar; version="0.0.0"
Possible Supplier: B_1.0.0 - Export-Package: org.bar; version="0.0.0"
Possible Conflicts: org.foo

이 중에서

Bundle: C_1.0.0 - Uses Conflict: Import-Package: org.bar; version="0.0.0"

이 줄은 org.bar 패키지 임포트와 관련하여 "uses" 제약 위반이 있다는 것을 알려준다. 즉, C가 사용하려고 하는 공개된(export) org.bar의 "uses"가 만족스러운 상황이 아니라는 것이다.

Possible Supplier: B_1.0.0 - Export-Package: org.bar; version="0.0.0"

이 줄은 org.bar 공급자가 의심스럽다는 것이고

Possible Conflicts: org.foo

이 줄은 어떤 패키지에서 "uses" 제약 사항이 위반되는지 알려준다.

구체적인 것에서 다시 돌아와서, 우리는 "uses" 충돌이 발생한 이유를 알고 있다. 번들 C가 가져오는 org.foo 패키지가 번들 B가 가져오는 것과 버전이 다르기 때문이다. B가 최신 버전의 F를 사용하도록 설정하는 것을 깜빡했다.

B의 manifest를 다음과 같이 수정한다.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: B
Bundle-Version: 1
Bundle-Name: B Bundle
Export-Package: org.bar;uses:="org.foo"
Import-Package: org.foo;version="[2,3)"

이제 번들 C를 성공적으로 배포할 수 있다.

복잡한 "uses" 충돌 진단하기


의도적으로 만든 "uses" 충볼은 번들 manifest를 보고서로 알 수 있을 만큼 간단한 문제였다. 하지만 매우 많은 충돌 가능성이 있는 "uses" 지시어 목록과 같은 좀 더 복잡한 "uses" 충돌의 경우, Equinox 콘솔(2401포트로 telnet)을 사용하여 성공적으로 설치된 번들을 확인해 볼 수 있다.(dm 서버는 성공적으로 배포하지 못한 번들은 uninsatll 시킨다.)

이퀴녹스 콘솔 명령어를 사용하여 설치된 번들 목록을 확인할 수 있다.,

osgi> ss

위에서 만들어본 문제 상황에서 다음과 같은 목록을 확인할 수 있다.


82 ACTIVE F_1.0.0
84 ACTIVE F_2.0.0
85 ACTIVE B_1.0.0

B 번들 manifest를 보려면 다음과 같이 한다.

osgi> headers 85

그리고 패키지 org.foo 패키지를 공개한 번들과 사용하는 번들을 보려면 다음과 같이 한다.

osgi> packages org.foo

요약


본 기사는 "uses" 지시어 필요성을 살펴봤고, 이를 사용하여 타입 불일치 에러 문제를 조기에 진단할 수 있는 방법을 보았다. 그리고 dm 서버 진단과 이퀴녹스 콘솔을 사용하여 "uses" 제약 위반을 확인하는 방법도 살펴보았다.

(마지막 단락은 번역 스킵)

You may think the "uses" directive is more trouble than it is worth, but when you consider the alternative of tracking down the reason for a possibly obscure class cast exception while your application is running, you should start to see the rationale for "uses". Indeed any Java module system which doesn't provide the equivalent of "uses" constraints is likely to give you class cast exceptions at runtime once you have gotten to the point of having multiple versions of your application modules. The OSGi "uses" directive solves a general problem of Java modularity.
신고
top


SpringSource DM Server 실습할 것 1

Spring DM/etc : 2008.11.11 23:01


서버 로그 확인
- cd serviceability/trace/
- less trace.log

서버 실행 할 때 옵션주기
- bin/startup.sh -jmxremote
- jconsole

덤프뜨기(jconsole에서)
- 덤프 버튼 클릭
- 생성된 덤프 파일 확인(amte 파일경로)

웹 프로젝트 만들기
- new -> project -> springsource dm server -> module project
  - 모듈 타입을 web으로 설정 할 것
  - 페이지 컨텍스트 설정 할 것
- MODULE-INF 폴더 만들기(웹 기본 폴더가 되는 듯), 그 뒤에 웹 리소스 쫘르륵..
- 컨트롤러 추가하기
- Manifest.mf에 Import-Library: org.springframework.spring;version="[2.5.5.A,3.0.0)" 추가
- META-INF 밑에 spring 폴더 만들고 스프링 설정 파일 추가.
  - module-context.xml
  - 컴포넌트 스캔
  - 뷰 리졸버
  - AnnotationMethodHandlerAdapter
- 프로젝트를 S2DM 서버로 드래그 앤 드랍
- localhost:8080/페이지 컨텍스트 경로 확인.

동영상을 보고 따라해보려고 해봤지만, 굵은 글씨 부분에서 막혔습니다. 저렇게 추가를 해도 라이브러리를 못찾습니다. 번들 클래스 패스에 추가가 되어야 할텐데 그게 안 되네요. 흠.. 플러그인 문제인듯.. 그게 잘 되야 좀 편하게 개발할텐데..
 
신고
top


SpringSource Application Platform(S2AP)은?

Spring DM/etc : 2008.11.09 21:34


S2AP랑 S2DS랑 햇갈려서 찾아 봤더니 S2AP는 S2DS와 S2E를 포함한 것을 말하는군요.

참조: http://www.springsource.com/products/suite/applicationplatform

The SpringSource Application Platform is an end-to-end platform that is designed from the ground up for complete portability and scalability for today’s data center and for next-generation virtualized, grid, and cloud computing deployments. The Platform is a collection of products designed to provide the optimal environment to build, run and manage enterprise Java applications that utilize Spring based technologies, including:

[막 번역]
S2AP는 단대단 플랫폼으로 요즘 데이터 센서에 완전히 호환가능하며 확장성 좋도록 설계했고 또한 다음 세대의 가상화, 그리드 그리고 클라우드 컴퓨팅 배포를 고려하여 설계했다. 이 플랫폼은 스프링 기반 기술을 사용하는 엔터프아리스 자바 애플리케이션을 빌드, 실행 그리고 관리하는데 최적의 환경을 제공하는 제품들로 구성되어 있다. 다음을 포함하고 있다.

    *  SpringSource Enterprise delivers the software, services, and technical support necessary to ensure that your organization develops and runs Spring-powered enterprise applications more productively, securely and with the greatest uptime.
    * SpringSource dm Server is a completely modular, OSGi-based Java server designed to run enterprise Java applications and Spring-powered applications with a new degree of flexibility and reliability.

S2E: 스프링을 사용하는 엔터프라이스 애플리케이션을 보다 효율적이고, 잘 사용할 수 있도록 소프트웨어, 서비스 그리고 기술 지원을 한다.
- Spring Enterprise Edition
- SpringSource Perfomance Suite
  - SpringSource Tool Suite
  - SpringSource Application Management Suite
  - SpringSource Advanced Pack of Oracle
- SpringSource Support

S2DS: 완전 모듈화한, OSGi-기반 자바 서버로, 엔터프라이즈 자바 애플리케이션과 스프링을 사용하는 애플리케이션을 새로운 수준의 유연성과 신뢰도를 가지고 실행할 수 있다.
사용자 삽입 이미지




신고
top

TAG S2AP, S2DS, S2E

OSGi 툴 세트 Pax

Spring DM/OSGi : 2008.10.21 00:16


홈피 http://wiki.ops4j.org/confluence/display/ops4j/Open+Participation+Software+for+Java

관련글 http://www.jroller.com/habuma/entry/is_your_osgi_toolset_pax

신고

'Spring DM > OSGi' 카테고리의 다른 글

OSGi 툴 세트 Pax  (0) 2008.10.21
Shared Mutable State  (2) 2008.09.25
The Price of Freedom  (0) 2008.09.25
Concurrency and OSGi  (0) 2008.09.25
BundleContext로 할 수 있는 일  (0) 2008.06.25
2 Security Layer  (0) 2008.02.18
1. Introduction  (0) 2008.02.17
top

TAG OSGi, tool

스프링 DM 프로젝트 빌드하기

Spring DM/exercise : 2008.10.16 14:59


메이븐 기반 프로젝트기 때문에, 간단하게 mvn package로 빌드 할 수 있을 거라고 생각했는데;;; 땡.. 틀렸습니다. mvn packae로 빌드하면 다음과 같은 에러를 볼 수 있습니다.

[ERROR]

Mojo:

    org.apache.maven.plugins:maven-compiler-plugin:2.0.2:compile

FAILED for project:

    org.springframework.osgi:spring-osgi-mock:bundle:1.2.0-m1

Reason:

C:\java\spring-osgi-1.2.0-m1\src\mock\src\main\java\org\springframework\osgi\mock\MockServiceReference.java:[23,25] package org.osgi.framework does not exist

OSGi 플랫폼이 없어서 발생하는 에러로, 스프링 DM 프로젝트를 빌드 할 때 프로파일을 선택해줘야 한다는 군요. 그래서 스프링 DM 프로젝트에 있는 프로파일을 살펴봤습니다.

사용자 삽입 이미지

여러가지가 있었습니다. 맨 위에 세 개는 OSGi 플랫폼이고, jdk 버전을 1.5 이상용도로 빌드해서 애노테이션 지원 기능을 사용할 수 있게 빌드 할 수 있나보네요. it은 통합 테스트(이 옵션을 안 주면 단위테스트만 합니다.)

mvn -Pequinox

통합 테스트까지 하면서 빌드 하려면

mvn -Pequinox,it

굳이 빌드를 안 해도 dist 폴더에 들어있긴 하지만... 오픈 소스쓰는 기본 자세라는 사부님 말씀. 캬~ 덕분에 오늘도 한 수 배웠습니다.

메이븐 프로파일은 안 써봤는데, 저걸 사용해서 빌드 하면 여러 환경에 따른 빌드 커스터마이징이 가능하군요. 특히 저 통합테스트가 눈에 띄는데 빌드 시간을 엄청 오래 잡아먹는 통합 테스트들은 주기 적으로만 실행하고 한 번의 커밋당 실행하는 빌드는 단위테스트만 실행하게 할 수도 있겠습니다.. 흠.. 프로파일 좋구나.


신고
top


Spring DM 1.1.2 릴리즈~

Spring DM/etc : 2008.10.04 18:58


http://www.springframework.org/node/776

이번엔 그닥 눈의 띄는 changelog가 없네요.
신고
top


Shared Mutable State

Spring DM/OSGi : 2008.09.25 11:33


공유하는 불변 객체

가능한한 최소한의 객체만 공유하고, 가능한한 공유하는 객체를 immutable하게 유지함으로써, 기본적으로 "동시성 문제" 크기를 줄인다. 불행히도 이 방법으로는 문제 크기를 0으로 만들지는 못한다. 실제 대부분의 애플리케이션에서 공유하는 불변 객체 사용을 완전히 없애진 못하기 때문에, 그럴 때 안전한 방법을 찾아야 한다.

서비스 기반 코드 예제를 살펴보자. 등록된 메일 박스 서비스의 Map을 관리한다고 가정해보자. 이름을 키로 사용하고 getMailboxByName 이라는 public 메소드를 제공하여 특정 메일 박스 또는 대응하는 박스가 없으면 null을 반환하도록 한다. 이 예제 코드는 6.1에서처럼 자바 synchronized 블럭을 사용하여 쓰레드 세이프티를 보장한다. 이 클래스는 잘 동작한다. 동일한 객체에 접근할 땐 해당 객체의 롹을 지니고 접근해야 하기 때문이다. 비록 맵 필드 자체는 final 이지만, map이 가지고 있는 내용물은 mutabl하며 여러 쓰레드가 공유하고 있다. 따라서 lock으로 보호해야 한다. 또란, 동기화 블럭은 가능한한 짧고, 빨리 롹을 반환해야 한다.

=> 음.. 글쿤 mutale한 객체를 공유하는 경우가 어떤건지 감이 오는군. 역시 예제가 있어야 이해하기 쉽네.

하지만, 코드 6.1은 Java 5에 도입된 새로운 동시성 기능의 장점은 하나도 이용하고 있지 않다. 자바 5의 기능을 사용하면 동시에 여러 쓰레드가 getMailboxByName 메소드를 호출하는 것이 가능하다. 이전 동기화 블럭은 읽기와 쓰기를 구분할 수 없었다. 모든 메소드 접근시에 불필요하게 롹 객체를 요구했다. 하지만 Java 4에 도입된 Read/Write 롹은 이를 구분할 수 있게 해준다. 코드 6.2는 이 기능을 사용하여 여러 쓰레드가 동시에 맵에서 읽기 작업을 할 수 있게 해준다. 물론 동시에 변경은 못하게 막고 있다.

만약 자바 5를 사용할 수 있는 환경이라면, 그 안에 들어있는 새로운 concurrnt 라이브러리를 확인해보는게 좋겠다. 자바 1.4를 사용하고 있다면 동기화 블럭 사용을 주저하지 말아라. 많은 개발자들은 성능 문제로 동기화 블럭 사용을 주저하지만, 실제로 동기화 블럭을 최대한 작게 유지만 한다면 그렇게 성능이 나쁘진 않다.  그리고 무엇보다 성능 조금 높이자고 동기화 문제를 방치한다는 건 말이 안 된다.

=> 옳커니~. 자바 5에 그런 게 있었구나.. 우와;; 평소에 쓰레드 다룰 일이 거의 없으니 완전 몰랐네.

=> 살펴 볼 클래스
- ReadWriterLock
- ReentrantReadWriteLock



신고

'Spring DM > OSGi' 카테고리의 다른 글

OSGi 툴 세트 Pax  (0) 2008.10.21
Shared Mutable State  (2) 2008.09.25
The Price of Freedom  (0) 2008.09.25
Concurrency and OSGi  (0) 2008.09.25
BundleContext로 할 수 있는 일  (0) 2008.06.25
2 Security Layer  (0) 2008.02.18
1. Introduction  (0) 2008.02.17
top


The Price of Freedom

Spring DM/OSGi : 2008.09.25 11:13


참조 : http://neilbartlett.name/blog/osgibook/

자유의 댓가.

=> 쓰레드를 맘대로 만들어 사용할 수 있는 자유의 댓가.

상상으로 만든 A, B, C 번들에 대한 간다한 시나리오를 살펴보자. 그림 6.1에 UML 시퀀스 다이어그램으로 나타냈다. 번들 A가 쓰레드를 시작시키고 어느 순간 번들 B에 접근하여 해당 쓰레드에서 번들 B의 start 메소드를 호출한다. 그러면 번들 B가 활동을 시작하고(active), 번들 B 액티베이터의 start 메소드가 번들 A가 만든 쓰레드에서 호출될 것이다. 게다가, B의 start 메소드에서 어떤 서비스를 등록하고, C가 서비스 트래커로 이 서비스 타입을 리스닝하고 있다. 번들 C 트래커의 addingService 메소드가 호출되고, 이 역시 A가 만든 쓰레드에서 호출된다. 마지막으로 C가 B가 등록한 서비스를 주기적으로 호출하는 쓰레드를 만들었다고 가정해보자.

=> 아.. 너무해. 이게 뭔리야. 좀 차근 차근 얘기해주지. -_-;; 그러니까...
1. 번들 A가 쓰레드를 만들고 거기서 번들 B의 start 메소드를 호출해서 번들 B를 활성화 시킨다.
2. 번들 B의 start 메소드에서는 번들 C가 리스닝하고 있는 서비스를 서비스 레지스트리에 등록한다.
3. 번들 C는 새로운 쓰레드를 만들어서 주기적으로 B가 등록한 서비스를 가져온다.
이말인가? 그렇다 치고..

사용자 삽입 이미지

클라이언트가 서비스 레지스트리에서 서비스를 가져갈 때, 프록시나 랩퍼가 아닌 진짜 서비스 객체를 찾는다. 따라서 클라이언트가 서비스에 메소드를 호출할 때, 해당 호출들은 기본적으로 동기적인 메소드 호출이다. 즉, 쓰레드에서 실행하는 서비스 메소드를 클라이언트 번들이 "쥐고있다."(owned)라는 뜻이다.

=> 넹.

또한, 많은(전부는 아님) OSGi 내의 알림은 동기적으로 발생한다. 프레임워크가 콜백을 사용하는 메소드(ServiceEvent를 등록되엉 있는 서비스 리스너로 보내는 것이나 번들 엑티베이터의 start 또는 stop 메소드를 호출하는 것 같은)에 의해 호출될 때, 그런 콜백들은 동일한 쓰레드에서 실행되고, 이전 제어권이 프레임워크 메소드를 호출한 쪽에 되돌아가기 전에 완료해야 한다.

=> 아.. 어렵다. 프레임워크의 어떤 메소드에 콜백을 넘겨줬을 때, 그 콜백도 같은 쓰레드에서 호출된다는 것이고, 해당 콜백 실행이 완료한 다음에, 제어권을 넘겨줘야 한다는 것이군.

위와 같은 상황에는 세 개의 주요 가정이 존재한다.
  • 콜백과 서비스 메소드는 어떤 쓰레드에서든 호출될 수 있다. 여러 쓰레드에서 동시에 호출될 수도 있을 것이다. 이를 주시하지 않고 코딩했을 때는 예상하지 못한 문제를 발생시킬 수 있다.
  • 우리가 작성할 콜백과 서비스 메소드를 호출하는 쓰레드는 우리가 만들 것에 "포함되어 있지 않다." 만약 오랜 시간 동작하거나, blocking I/O를 이런 콜백에서 사용한다면 전체 시스템을 지연시킬 수 있다.
  • OSGi API 메소드를 사용하면, 우린 해당 프레임워크가 어떤 리스너나 콜백을 사용하는지 예측할 수 없고, 따라서 해당 콜백에서 어떤 롹을 취하려는지도 알 수가 없다. 만약 그런 메소드를 호출하는 도중 다른 롹을 가지고 있다면, daedlock을 발생키질 위험이 있다.
이런 문제에 대한 해결책은 좋은 동시성 프로그래밍 프랙티스를 사용하는 것이다. 하지만, 안전한 동시성은 그렇게 어렵지 않다. 최소한 블라 블라 하는 것처럼. 천재만 할 수 있는 것이 아니다. 핵심은 (많은 천재들이 하지않는) 훈련이다. 몇 가지 규칙을 적용하여, 우리가 맞닥들이게 될 대부분의 상황을 쉽게 처리할 수 있다.

1. 변하는(Immutable) 객체는 자동적으로 쓰레드 세이프하며, 여러 쓰레드에 걸쳐 공유될 객체가 아니라면 쓰레드 세이프 해야할 이유가 없다. 따라서 가능한 공유할 것을 최소화 하고 가능한 immutable 객체를 사용하라.

2. 공유하는 불변의(mutabl) 객체가 정말로 꼭 필요한 경우, 모든 접근(읽기 쓰기)을 막아서 동일한 객체의 롹을 가지고 필드를 보호하거나 volatile 변수를 사용하라.

3. 이미 롹을 가지고 있는 상태에서 새로운 롹을 얻으려고 하지 말아라. 이 규칙을 따르면 자연스래, 롹을 얻으려는 시도를 할지도 모르는 "아는바없는" 혹은 "외부" 코드를 호출할 때는 어떤 롹도 쥐고 있어서는 안 된다. 이는 서비스 또는 OSGi API를 호출할 때를 말하며, 이들 중 대부분이 다른 번들의 콜백을 우리가 만든 쓰레드에서 실행하게 된다.

=> 글쿤, 롹을 쥐고 있는 상태에서 롹을 가지려고 할지도 모르는 어떤 서비스 또는 OSGi API를 호출하면 deadlock이 발생할 수 있으니, 그럴 땐 롹을 쥐고 있지 말라는 것이로군요.

=> 한가지 궁금한건 2번에서 volatile을 사용하면 모든 쓰레드에서 동일한 값을 사용하게 될텐데 그렇게 되면, 결국엔 mutable 하지 못한게 된느거 아닌가.. 흠.. A 쓰레드에서 foo.name을 a라고 하고 B 쓰레드에서 foo.name을 찍으면 a가 찍힐테고 B 쓰레드에서 다시 foo.name을 b라고 하면, 이번엔 A 쓰레드에서 foo.name을 찍으면 b가 찍힐텐데... 내가 volatile을 잘못이해한건가.. 아닌데, 맞을텐데, 아니면, mutable->immutable하게 사용하라는 것인가.. 차리리 ThreadLocal을 사용하는게 낫지 않을까. 아닌데 저자가 그걸 모를리도 없고, 아. mutable이니까, setter를 막아둬서 값 변경을 막아뒀겠구나.. 위와 같은 내 생각은 immutable객체를 공유할 때 생기는 문제지;. (흠.. 이것도 아닌가 위에선 분명 '읽기와 쓰기'라고 '쓰기'를 언급하고 있자나..) 흠..그럼 뮤터블 객체를 왜 공유해서 쓰는거지. 그럴 때 그 객체 값을 변경하지 못하면, 멀티 쓰레드 걱정 안해도 되는거 아니야? 아.. 다음 챕터를 읽어보자. 아 내 머리.
신고

'Spring DM > OSGi' 카테고리의 다른 글

OSGi 툴 세트 Pax  (0) 2008.10.21
Shared Mutable State  (2) 2008.09.25
The Price of Freedom  (0) 2008.09.25
Concurrency and OSGi  (0) 2008.09.25
BundleContext로 할 수 있는 일  (0) 2008.06.25
2 Security Layer  (0) 2008.02.18
1. Introduction  (0) 2008.02.17
top


Concurrency and OSGi

Spring DM/OSGi : 2008.09.25 10:25


참조 : http://neilbartlett.name/blog/osgibook/

J2EE 같은 무거운(heavyweight) 프레임워크에 비해, OSGi는 쓰레드를 포함한 JVM의 모든 리소스를 제어하려 들지 않는다. J2EE에선 직접 쓰레드를 만들거나 명시적인 동기화(synchronization)를 하는 코드를 작성하는 것을 금하고, 대신에 제한적인 "작업 관리" 프레임워크를 제공한다. OSGi는 여러분이 직접 애플리케이션에서 쓰레드를 만들고 스케쥴링을 할 수 있다. 그렇게 하려면 OSGi 라이브러리들은 쓰레드 세이프해야 하며 어떤 쓰레드에서도 호출할 수 있어야 한다.

=> 즉, OSGi에서는 쓰레드를 직접 다루는 코드를 작성할 수도 있으니, 쓰레드 세이프한 라이브러리를 만드는 것이 중요하다는 뜻인듯..

하지만, 이런 자유에는 댓가가 따르듯이, 우리가 만들 번들에서 쓰레드를 생성하여 사용하는것이 가능하듯이, 우리가 만들 번들이 단일 쓰레드 환경에서만 사용되리라는 보장은 못한다. OSGi는 암묵적으로 멀티 쓰레드다. 따라서 반드시 작성하는 코드가 쓰레드 세이프해야 하며, 특히 이벤트나 콜백을 다른 프레임워크 또는 번들에서 받아올 때 주의해야 한다.

=> 흠. 당연한 말씀.

Brian Goetz의 "Java Concurrency in Practice"에서 자바 동시성에 대해 자세히 다루고 있으니, 프로페셔널 자바 프로그래머라면 항상 이 책을 가까이 하라.

=> 넵.
신고

'Spring DM > OSGi' 카테고리의 다른 글

OSGi 툴 세트 Pax  (0) 2008.10.21
Shared Mutable State  (2) 2008.09.25
The Price of Freedom  (0) 2008.09.25
Concurrency and OSGi  (0) 2008.09.25
BundleContext로 할 수 있는 일  (0) 2008.06.25
2 Security Layer  (0) 2008.02.18
1. Introduction  (0) 2008.02.17
top


OSGi 개발에 PDE가 필요한가?

Spring DM/etc : 2008.09.15 20:21


절대로 그렇지 않습니다. 오히려 OSGi를 처음 접할 때 이클립스 PDE(Plug-in Development Environment)로 시작하면, 더 낯설고 복잡해 보입니다. 왠지 꼭 그런 도구가 있어야 개발할 수 있을 것 같은 기분이 들죠. 그래서, 오히려 처음 OSGi 개발을 시작하거나 공부할 때는 PDE를 사용하지 않는게 더 좋은 방법이라고 생각합니다. 최소한의 도구만을 사용하는것이 오히려 OSGi 학습에 도움이 될 수 있습니다.

또한, 도구들은 어느정도 학습자로써 반드시 알아야 할 것을 감추는 경향이 있습니다. 도구를 사용하는 것은 좋치만, 마치 자바를 배울 때 javac Hello.java 랑 java Hello도 안 해보고 이클립스에서 Run As -> Java Application만 실행하는 것에는 큰 차이가 있듯이..말이죠.

그래서 OSGi 학습을 할 때 권장하는 도구는 최소한의 자바 프로젝트 편집기 + bnd 입니다. bnd는 MANIFEST.MF 생성과, 해당 프로젝트를 번들로 묶어주는 역할을 합니다. MANIFEST.MF 파일을 bnd로 만드는 이유는 MANIFEST.MF 파일이 단순한 텍스트 파일이 아니기 때문입니다. 한 행당 길이 제한이 있으며, 사용할 수 있는 헤더와 값을 지켜서 만들어야 합니다. bnd는 그런 불편함을 최소화 해줍니다. 그리고 번들로 만들어 주는 기능을 제공하는 이유는 이 MANIFEST.MF 파일이 jar 파일의 젤 상위 META-INF라는 폴더의 젤 처음에 위치해야 합니다. 그래야 일반 jar가 아닌 OSGi 번들로 인식합니다. 그렇게 패키징 해주는 기능을 제공하는 겁니다.

물론 Maven을 사용한다면, 이야기가 조금 달라집니다. 이때는 M2Eclipse 기반의 메이븐 프로젝트 + 메이븐 번들 플러그인입니다. 메이븐 번들 플러긴은 bnd 툴을 그대로 메이븐 플러긴으로 만든 것인데, 이 플러긴이 메이븐 페이스(phase)에 끼워져있어서, 해당 mvn package를 실행할 때, 해당 프로젝트를 번들화 하는 작업이 추가됩니다. 번들화라고 해봤자, MANIFEST.MF를 생성해서 제 위치에 넣어주는 것 뿐입니다. 따라서 Maven 프로젝트 관리 + 플러긴 하나로 OSGi 개발을 할 수 있습니다.

bnd에서 MANIFEST.MF 파일을 만들기 위한 설명서로 .bnd 파일을 만드는데, 이 파일은 properties 파일 처럼 키= 값 형태 입니다. 이 때 사용하는 키는 Manifest 헤더와 비슷한 것들이 많기 때문에 Manifest 헤더를 이해하는데 도움이 되고, 이클립스 플러긴으로 사용할 수도 있어서 .bnd 파일을 우클릭하면 make bundle이라는 메뉴가 생기는데 이것을 클릭하면 바로 MANIFEST.MF 파일 생성하고 해당 프로젝트를 번들로 만들어줍니다. 이클립스에서 export 하면 길고 긴 마법사 쭉 따라가야 하는데 그런 불편함이 없죠. 그야말로 OSGi 학습과 개발에 매우 유용한 툴이 아닌가 싶습니다.

OSGi를 학습하시는 분들에게 PDE 보다는 bnd 사용을 권해 보면서 마무리 하겠습니다.

2008/06/22 - [Spring DM/exercise] - bnd를 소개합니다.
2008/07/08 - [Screen Casting] - Eclipse에서 bnd 사용해서 번들 만들기
2008/07/10 - [Spring DM/exercise] - bnd 사용해서 API 가져오기(Import)
2008/07/13 - [Spring DM/exercise] - bnd에 번들 실행환경 설정하기
2008/08/18 - [Spring DM/exercise] - pom.xml에서 bnd 설정 파일 분리하기


신고
top

TAG Bnd, OSGi, pde

스프링 DM 1.2.0 M1 배포

Spring DM/etc : 2008.09.05 20:43


참조 : http://www.springframework.org/node/754

눈에 띄는 변경 사항은 딱 하나

"스프링 MVC 예제, 그것도 애노테이션 기반의 예제를 추가했다."
신고
top


OSGi에서 SessionFactory(Hibenate) 사용하기

Spring DM/exercise : 2008.08.25 14:59


참조 :
http://www.osgi.org/blog/2007/06/osgi-and-hibernate.html
http://notehive.com/wp/2008/07/23/osgi-hibernate-spring-dm-sample/

번들 세 개만 살펴보겠습니다.

1. hibernate-class
2. hibernate-session
3. model-a

1. hibernate-class

이 녀석은 하이버네이트 라이브러리를 묶어놓은 번들입니다. 얘가 담고 있는 라이브러리는 다음과 같습니다.
사용자 삽입 이미지

이렇게 묶어놓은거 말고 스프링 번들 저장소에서 다운로드해서 일일히 설치해도 되야 할 것 같은데, 저번에도 해봤고, 오늘도 다시 시도 해봤는데, 똑같은 문제가 발생하고 있어서 실패했습니다. 아무래도 스프링 DM 지라에 올리던가 포럼에 올려서 물어봐야 할 것 같네요.

2. hibernate-session

이 녀석이 하는 일은 많습니다. 테스트 DB를 만들고, 하이버네이트 애노테이션을 사용한 도메인 클래스들도 있고, SessionFactory도 만듭니다. 단, SessionFactory를 만들 때 좀 특이하게 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration 클래스를 사용하여 생성합니다. 실질적으로 SessionFactory를 만들어 내는 클래스입니다. 이 클래스의 핵심 메소드인 createNewSessionFactory() 메소드에서 JDK Proxy 클래스를 사용해서 프록시 객체를 생성하고 있습니다.

OSGi 서비스로 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration를 공개하고 있습니다.

3. model-a

이 번들에는 하이버네이트 애노테이션을 사용한 모델과, DAO 구현체가 들어있습니다. SessionFactory와 TransactionManager를 내부에서 빈으로 정의하고 있는데, SessionFactory를 만들 때 위에서 살펴본 hibernate-session 번들이 공개한 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration 서비스를 사용합니다. SessionFactory를 빈 설정만 보면, hibernate-session이나 model-a나 동일합니다.

단, 이 빈은 com.notehive.osgi.hibernate_samples.session.DynamicConfiguration 서비스를 가져옵니다. 그리고 DAO에서는 해당 서비스를 사용해서 만든 SessionFactory를 사용하죠.

그리고 DynamicConfigurationListener 라는 빈을 등록해서 DynamicConfiguration 이 객체에다가 하이버네이트 애노테이션이 붙어있는 클래스를 추가하거나, 제거하는 코드를 넣어뒀습니다.

마지막으로 주목할 것은 osgi.bnd 파일의 설정인데..

Hibernate-Contribution: default; \
    classes="com.notehive.osgi.hibernate_samples.model.a.A1"

이런식으로 속성/값을 추가해뒀고, 이 값을 hibernate-session 번들의 BundleTracker가 읽고 DynamicConfiguration에 애노테이션이 붙은 클래스를 추가/제거 합니다. 그 뒤엔 당근 새로운 SessionFactory를 만들어 가지게 됩니다.



캬...이제야 OSAF를 돌릴 수 있는(정확하겐 하이버네이트 App를 돌릴 수 있는) 플랫폼을 구성하는 실마리를 찾은 것 같습니다.

신고
top


OSGi 패키지가 아니라 서비스야 말로 진정한 Dynamic

Spring DM/exercise : 2008.08.20 22:05


번들과 번들 사이에서 자신이 가지고 있는 정보를 공유하는 방법은 두 가지 입니다. 패키지 안에 있는 클래스들을 공개해서 상대방이 내가 가진 클래스의 객체를 만들어서 사용하게 할 것이냐, 아니면 내가 패키지 말고 내가 객체를 만들어서 제공할 것이냐. 후자가 바로 서비스. 전자는 패키지입니다.

차이는 매우 큽니다. Dynamic Module System에서 Dynamic 이라고 할려면 사실 상 패키지 공개로는 아무 의미가 없고,  Service-Export/Import를 해야 의미가 있습니다. 왜냐면 말이죠... 생각을 해보면 됩니다.

A 번들 whiteship 패키지에 Whiteship.java 클래스가 있고,
B 번들 blueship 패키지에 Blueship.java 클래스가 있다고 하겠습니다.

이 때 B 번들에서 A 번들에 있는 Whiteship 타입의 객체가 필요합니다. 그래서 A 번들에서 Export-Package로 whiteship 패키지를 등록하고, B 번들에서는 Import-Package로 whieship을 등록했습니다. 그런 다음 B 번들에서 Whiteship 타입 객체를 만들어서 사용합니다.

자 A 번들의 Whiteship.java 클래스가 바꼈습니다. 어떡할건가요? A 번들을 다시 설치합니다. B 번들에서 사용하고 있는 Whiteship 타입 객체는요?? 그대로죠. 뭐 변한게 없습니다.  뭐가 동적으로 바뀌죠? 바뀌는거 없죠? 이제 뭔가요? 이제 Dynamic 인가요? 아니죠.

패키지 대신 서비스로 단어를 바꿔서 다시 생각해보시면 뭔가가 달라집니다.

다시, (서비스를 사용한다는 가정하에) A 번들의 Whiteship.java 클래스가 바꼈습니다. A 번들을 다시 설치해야겠군요. 이건 당연한 겁니다. 설마 A 번들도 다시 설치하는데 이게 뭐가 동적이야??? 라고 생각하시는 분은 안 계시죠? 만약에 그러면 그건 좀 코메디입니다. ㅋㅋ 아무튼 잡담이었구요. 자. 이 다음엔 어떤 일이 벌어질까요? B 번들이 사용하면 Whiteship.java 타입의 서비스까지 바뀝니다. 캬~~ 놀랍죠? 어떻게 바뀌냐구요? A 번들이 죽을 때 자기가 등록한 서비스들도 전부 죽입니다. 그럼 B 번들이 사용하고 있던 Whiteship 타입의 서비스도 죽었겠죠. 그런 다음 A 번들이 다시 살아나면, 서비스를 등록하고 그럼 그 서비스를 기다리고 있던 B 번들이 다시 Whiteship 타입의 서비스를 사용하는 겁니다.

복잡하죠? 네.. 사실 이렇게 해피한 시나리오대로 흘러가지 않을 가능성도 많습니다. 설정하기 나름입니다. 대기 시간 설정이라덩가. 서비스의 필수 여부 설정이라덩가. 덩덩덩.

그리고 또 있습니다.

패키지로 export/import  할 때는 impl 까지도 export 해줘야겠죠? 객체를 생성하려면 어차피 구현한 클래스까지 알아야 할테니까요. 그런데 서비스로 공개할 떄는 구현체까진 안 알려줘도 됩니다. 구현은 감추고 인터페이스만 공개할 수 있는거죠. 캬~

Anyway!! 패키지를 사용하는거 보다는 서비스를 사용하는게 진정한 Dynamic 이라는거 아시겠죠?

그럼? 서비스만 쓰지 패키지는 왜 있는거야?? 라는 생각.. 드시죠??

저도 좀 생각을 해봤는데요. GenericDao 같은 클래스의 서비스가 필요한가요? 그냥 상속해서 쓰면 그만이죠? 즉 이렇게 패키지로 공개할 것인가 서비스로 공개할 것이냐는 용도에 따라 좀 달라질 것 같습니다. 클래스가 필요하면 패키지로, 객체가 필요하면 서비스로. 글쵸? 그런거 같죠? ㅎㅎ; 저도 잘 몰라요.

신고
top


흠... Hibernate Annotation 번들 왜이래 왜 ㅠ.ㅠ

Spring DM/exercise : 2008.08.19 12:20


osgi> diag 13
initial@reference:file:com.springsource.org.hibernate.annotations-3.3.1.ga.jar/ [13]
  Constraints from the fragment conflict with the host: Import-Package: org.apache.commons.logging; version="[1.1.1,2.0.0)"
  Missing Constraint: Fragment-Host: com.springsource.org.hibernate; bundle-version="[3.2.6.ga,3.3.0)"

osgi>

흠... 이상하네. host(org.hibernate) 랑 dep 충돌이 난다는데, host도 commons.logging 1.1.1 사용하고, 이 녀석도 1.1.1 참조하는데, 뭐가 충돌이 난다는거얌 ㅠ.ㅠ

왜그러니.. 내가 널 만들어줄까??
신고
top


pom.xml에서 bnd 설정 파일 분리하기

Spring DM/exercise : 2008.08.18 15:29


사용자 삽입 이미지


bnd 설정 파일을 pom.xml에서 분리하고 pom.xml의 bnd 플러긴 설정은 다음과 같이 수정합니다.

            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <version>1.4.0</version>
                <configuration>
                    <instructions>
                        <_include>-osgi.bnd</_include>
                    </instructions>
                </configuration>
            </plugin>       

pom.xml은 훨씬 가벼워지고, bnd 설정과 pom.xml을 유지보수 할 때도 이렇게 나눠 두는게 좋을 듯 합니다.
신고
top

TAG Bnd, maven

OSGi 기반 프레임워크과 애플리케이션 아키텍처 진화 과정

Spring DM/exercise : 2008.08.14 18:11


대체 어떻게 모듈화 해야 할까...
어떻게 나눌 것인가..
어떻게 구성해야 번들간의 상호참조(CD)를 없앨 수 있을까..
어떻게 나눠놔야 개발을 할 때 여러 번들을 뒤적거리지 않을까..
번들헬이 발생하지 않게 하려면...

위와 같은 고민들은 OSGi와 스프링 DM을 학습하다보면, 자연스레 맞닥드리게 되는 문제들입니다.

이 질문에 대한 답은 모르겠습니다. 사실 답은 있죠. "잘". 그러려면, 많이 실험을 해봐야 합니다. 때마침 저한텐 아주 좋은 실험체가 있습니다. 임상 실험 프로젝트랄까요.ㅎㅎ 스프링 하이버기반으로 세 달에 걸쳐서 만든 시스템이 하나 있습니다. 규모가 크지도 작지도 않고 좋습니다. 도메인 모델이 한 40개 정도되는 프로젝트입니다. 비즈니스 로직도 포함하고 있어서 서로 얽히고 섥혀있지요.

이 프로젝트에서 OSAF15에 들어갈 코드를 분리해냈습니다. 그게 1단계였죠. 분리해낸지는 꽤 됐지만, 주석이랑 테스트 코드를 추가하느라 시간이 좀 지연됐습니다. 어제부로 그 작업도 끝났습니다. 1.5 단계랄까요. 정리하는 단계는 그렇게 끝났습니다.

이제는 본격적으로 2단계로 돌입해서 쪼갠 것을 적용해봐야 합니다. 그래서 검증이 되는거죠. 일단은 OSGi화 하지 않았던 기존 시스템과 동일하게 동작하는것을 목표로 적용합니다.

2단계가 잘 돌아가면, 그 뒤엔 쪼갠 것을 돌리는 상태에서 OSAF 번들만 수정해서 업데이트를 하는 겁니다. 이게 마지막인 3단계입니다.

오늘은 2단계에 막 들어선 날로, 코딩은 별로 못하고 낙서와 그림을 그리고 웹 서핑을 하면서 다른 자료를 찾는데 시간을 많이 보냈습니다. 다행히 어느 정도 성과가 있었습니다.

사용자 삽입 이미지
처음에 그린 그림입니다. OSAF15 번들 자체가 너무 커서, 그 안에 들어있는 몇 개의 패키지를 별도의 모듈로 쪼개는 걸 구상하여 그린 겁니다. OSAF, OSAF-App 이렇게 둘로 쪼개고, 일반 App 번들과 OSAF-App 번들을 WAR 번들에서 참조하는 걸 그리다가.. 문제를 발견했습니다. 그게 바로 아래에 있는 S/F SessionFactory 입니다.

저 때는 아직 문제를 발견했다기 보다.. 뭐랄까.. 냄새가 나고 있었다고 할까요.. 저 땐 단순하게 SessionFactory를 사용한다고만 생각했지 SessionFactory에서 저 번들들 안에 들어있는 모델을 참조해야 한다고.. 즉 상호참조가 발생하리라곤 미쳐 생각을 못하고 있었습니다.

사용자 삽입 이미지
(여러 색의 형광펜을 발견하고, 잘 나오나 확인을 해보는 그림이 좀 멋있어 졌습니다.ㅋㅋㅋㅋ)

두 번째 그림입니다. 첫 번째와 비슷하게 OSAF에서 이번엔 Security 부분을 떼어 내야겠다는 생각이 들었습니다. OSAF-App에는 User, Role, Audit과 같은 인증, 권한 과 관련된 기본 도메인들과 그 도메인이 사용하는 Audit이라는 클래스가 있었습니다. 그리고 User, Role에 대한 Dao, Service, Controller 까지도 들어있었죠.

문제는 Security가 저 녀석들을 사용하고 있다는 겁니다. User, UserDao를 사용합니다. 그렇게 되면 OSAF와 OSAF-App 두 번들이 CD에 빠집니다. 그래서 Security를 빼내면 될 줄 알고 저렇게 OSAF-Security를 빼내기로 결정.

실제 코드 작업을 좀 하다가 보니... 크헉!!!! osaf.service에서 osaf.security를 참조하고 있었습니다. 이러면 이거 때어낸다고 해서 해결될 문제가 아닌게 되는거라.. 다시 고민에 빠짐...

사용자 삽입 이미지
(이때부터 그림에 좀 신경을 쓰기 시작했죠.)

맨 왼쪽에 X 표를 친 부분이 바로 그 좌절하는 순간입니다.

여차저차해서 SessionFactory에 대한 실마리를 찾았고, 다시 OSAF는 좀 크지만, 한 덩어리로 가기로 했습니다.
사용자 삽입 이미지
(네모와 동그라미를 그리는 연습을 자주 해야겠습니다.)

실제 OSAF 내부에선 저런 순환 구조는 아닙니다. base쪽에 패키지를 세세하게 나눠뒀기 때문에 패키지 순환 참조는 발생하지 않습니다. CD는 하나도 없습니다.

오늘은 여기까지 구상하고 마치고 내일 다시 재도전해야겠습니다. "잘" 나누는 방법을 찾기란 이렇게 힘들고 재밌는 일이더군요. 캬캬캬.
신고
top

TAG OSAF, OSGi

OSGi에서 Hibernate의 SessionFactory 문제

Spring DM/exercise : 2008.08.14 15:34


대체 어떻게 해야 할까? 뭘? @Entity 달려있는 클래스들이 여러 번들들에 분포되어 있고, 애플리케이션이 돌아가는 도중에 번들이 추가되고, 없어지고, 다시 설치되고, 업데이트 되는 와중에 SessionFactory는 그에 따라 계속 바껴야합니다.

Spring이 제공하는 AnnotationSessionFactoryBean 클래스로 만드는 SessionFactory는 정적입니다. 한 번 만들고 다른 빈들이 주입받아서 사용하는데, 도통 어떻게 변경해야 할지 모르겠습니다.

이게 문제는 OSGi, Hibernate, Spring DM, JPA를 사용하려다 보면 자연스럽게 다가오는 문제입니다. 저 말고도 이미 예전부터 이 문제를 당면한 여러 개발자들이 있었습니다. 지금 이 순간 "나는 iBatis를 쓰고 있어서 다행이야!!!" 라고 외치고 계신 분이 혹시 계신가요??? ㅎㅎㅎ 어림없습니다. 이 문제에서 못 벗어납니다. SessionFactory 대신에 SqlMapClient로 놓고 생각해 보시면 똑같습니다.

설정 파일을 번들 하나에 전부 넣어 놓고(애노테이션 붙인 도메인 객체들을 모두 한 번들에 놓고), 그걸로 SessionFactory 만들면 되지 않겠냐구요? 아니.. 미래에 추가될 번들에 들어있는 도메인을 어떻게 지금 추가할 수가 있나요? 백투더퓨쳐가 아닌이상 불가능할 뿐더러, 그럴 바엔 아예 OSGi 번들로 나누지 말고 그냥 기존의 애플리케이션처럼 사용하는게 좋을 거 같습니다. 뭐 잠깐 서버좀 껐다 키죠 뭐.ㅎㅎ

다행히도 이 문제에 대한 해결책이 나왔고, 그걸 구현한 예제까지도 제공하고 있습니다.
http://notehive.com/wp/2008/07/23/osgi-hibernate-spring-dm-sample/
전 이런 개발자가 정말 멋져보입니다. 이력서를 보니까, 88/89년에 인턴쉽 하고, 92년도부터 계속 개발을 해온 사람이네요. 그럼.. 지금.. 16년째.. 캬;;;; 장난 아니셤!!!
신고
top


번들을 찾으려면.. http://www.springsource.com/repository/

Spring DM/etc : 2008.08.13 12:04


http://www.springsource.com/repository/ 필요한 번들을 찾으려면 왼쪽 사이트에 가셔서 검색하시면 됩니다. 다소 복잡한 dep 구조를 가지고 있는 하이버네이트도 잘 정리되어 있었습니다.

사용자 삽입 이미지

위에 링크에서 번들 파일을 바로 다운로드 할 수 있으며, Maven을 사용할 때는 아래 dependency 덩어리를 pom.xml에 추가하면 됩니다. 그리고 이 번들이 의존하는 다른 번들들의 링크까지 확인할 수 있습니다.

하단의 Required Dependencies 바를 펼치면 해당 링크로 바로 이동할 수 있죠.
사용자 삽입 이미지

이렇게 위 사이트의 도움으로 OSAF 1.5의 모든 의존성을 해결해서 ACTIVE 상태로 만들 수 있었습니다.

사용자 삽입 이미지

차근 차근 진행이 되어 갑니다. 멀지 않았습니다. 하지만, 한 발짝 물러나야 할 일이 생겼군요.

1. OSAF 1.5 모듈에서 스프링 DM이 해줄 일이 생겨서, 빈 몇 개를 서비스로 등록을 해야겠습니다. 컴포넌트 스캔 확인 좀 해야겠네요. 컴포넌트 스캔까지 되면...

2. 다음은 예제 만들어서 저 번들이 제공하는 서비스와 패키지를 제대로 쓸 수 있는지 확인하고..

3. 간단 튜토리얼 만들고...

4. OSAF 웹 사이트좀 꾸민 다음..

5. 최종 배포!!!

멀지 않았습니다. 배포한 뒤에는 좀 더 심화 작업을 진행할 생각입니다.

6. 기존 시스템 OSGi화 하기

7. 코드 제너레이터 만들기

8. 이클립스 플러긴 만들기
신고
top


맥북에서도 Spring DM 웹 번들 설치 성공

Spring DM/exercise : 2008.07.31 00:03


인증샷 1. 번들 목록

사용자 삽입 이미지

인증샷 2. simple-web-app 첫 화면

사용자 삽입 이미지
인증샷 3. 서블릿

사용자 삽입 이미지
인증샷 4. JSP는.. 또 실패;;

사용자 삽입 이미지
흠... 리소스가 제대로 등록이 안 되있는건지.. 원인을 좀 찾아봐야겠습니다.


맥북에서 Spring DM 웹 번들 돌린게 왜 기쁘냐면요;; 안 해보신 분들은 몰라요... 윈도에서 돌리는 Equinox(줄여서 윈E)랑 맥에서 돌리는 Equinox(맥E)가 좀 차이가 나는 것 같습니다. 버그 같은데, 그게 맥E 의 버그인지, Spring DM web extender의 버그 인지, catalina의 버그인지 도통..잘 모르겠습니다.

spring web extender가 catalina 번들이 제공하는 서비스를 필요로 하는데, 만약에 catalina 보다 먼저, start 시키면 당연히.. resolved 상태로 못가고 해당 서비스가 들어올 때까지 좀 기다립니다. 그러다가 특정 시간이 되면 타임되서 넘어갑니다. 이게 정상이죠. 윈E에선 이렇게 정상적으로 동작합니다. 그래서 설치할 번들 목록에서 spring web extender 가 catalina 보다 위에 있어도(즉 먼저 start를 시도하겠죠.) 상관없습니다. 기다리다 보면, 다른 번들들 모두 Active 상태가 되고, spring web extender만 Resolved 상태로 남아있습니다.(catalina도 Active 상태가 됐으니 web extender가 필요로 하는 서비스가 제공 되서 상태가 변한겁니다.) 그러면... 이제 web extender만 다시 start 명령어로 Active 상태로 만들어 주면 됩니다.

하지만.... 맥E에선, 한 번 해보세요~ 해보셨어요? 안 해보셨으면 말을 하지마세요.

사용자 삽입 이미지
사용자 삽입 이미지


참.. 테스트 환경은. Eclipse 3.4. Spring DM 1.1.1 입니다.

ps: Bad case에 걸렸을 때 Good case를 찾아 빠져 나가는 방법이 있긴 있는데.. 그건 비밀입니다. 캬캬캬
신고
top


Spring DM 1.1.1 배포

Spring DM/etc : 2008.07.29 23:44


http://www.springframework.org/node/718

버그들을 좀 수정했나봅니다. 눈에 확 들어오는 뭔가는 없어서 코멘트 할 께 없네요;;
신고
top


스프링 DM 모듈에서 단위 테스트하기(링크)

Spring DM/etc : 2008.07.23 08:53


http://springtips.blogspot.com/2008/07/unit-test-with-spring-dynamic-modules.html

제목은 단위 테스트인데, 사실 OSGi 환경에서 번들로 설치한 담에 실행하는 것이고, 스프링 ApplicationContext도 사용하고 있으니까 정확하게는 통합 테스트 입니다. 제목이 굳이 단위 테스트인 이유는 몰겠네요. 흠.. 단위 테스트를 왜 OSGi 환경에서 실행했을라나..

어쨌든, 스프링 DM에서 테스트를 작성하는 방법을 설명해주고 있는 괜춘한 글입니다. 벌써 저렇게 자기 애플리케이션을 스프링 DM 번들로 전환하는 작업을 마친 사람들도 많은데, 저도 좀 분발해야겠습니다.
신고
top


Late Binding in Java

Spring DM/exercise : 2008.07.20 17:04


참조 : http://neilbartlett.name/blog/osgibook/

OOP의 목적 중 하나는 의존성을 최대한 낮춰서 코드의 재사용성과 유연함을 늘리는 것이다.

자바에서는 인터페이스를 사용해서 이런 목적에 접근 했다. 인터페이스는 불편하고 그것을 구현한 구현체만 바꾸면 인터페이스를 사용하고 있는 클라이언트 코드는 변경할 필요가 없었기 때문이다. 하지만, 한계가 있는데, 객체를 생성하려면 어차피 구현한 클래스를 클라이언트 쪽에서 알고 있어야 한다는 것이다.

그래서, 스캐너의 생성자를 사용해서 문자열을 받고 그 문자열로 분기문을 돌려서 구현체를 기반으로 객체를 만드는 코드를 사용하기도 하는데, 역시나 새로운 구현체가 생기거나 하면, 또 코드를 바꿔야 된다.

이에 대한 대안으로 스캐너를 사용하지 않고, "다른 뭔가"가 그 객체를 제공해주게 하는 것이다. 그래서 등장한게 "Assembler" 다. "Assembler"를 여러 곳에서 만들어 쓰다가 패턴이 발견되었고, 그 패턴을 구현한 프레임워크가 스프링과 구글쥬스다.

이 들을 Dependency Injection 프레임워크라고 한다. (물론 스프링은 그게 전부는 아니지만) 불행히도, 이런 Assembler Pattern도 정적이라는 특성 때문에 몇 가지 문제가 있다. 객체들의 연관 관계를 정적으로 한 번 생성하고 말기 떄문에, 객체 생성 순서를 신경 써야 한다. B가 A 객체를 참조하려면 A 객체를 먼저 만들어야 된다. 그리고 객체간에 상호 참조(Circular Dependency)도 조심해야 된다.

또 다른 문젠 동적으로 업데이트 하는 것이 불가능하다. 이렇게 정적으로 묶여있는 의존성 그래프에는, 아주 작은 객체 연관 관계를 변경하려고 해도 전체 시스템을 껐다가 켜야 한다.

OSGi는 바로 이 문제를 동적인 "서비스"를 이용해서 해결한다.

서비스는 DI 프레임워크에서의 빈 처럼 평번한 자바 객체(POJO)다. 서비스는 하나 이상의 인터페이스 이름으로 OSGi 서비스 레지스트리에 의해 제공된다. 서비스는 다른 서비스를 사용할 수 있고 고정적인 그래프로 묶이는게 아니라, 서비스는 언제든지 동적으로 등록되고 해지될수 있다. 따라서 서비스들 사이의 관계는 임시적인 관계이다.

객체 생성 순서 문제는 다음과 같이 해결한다. B가 A를 필요로 하는 상황에서 B 객체를 만들 때 A 객체가 있는지 화인하고 안 만들어져있으면 이 객체를 이용할 수 있을 때 까지 잠시 대기한다. 그리고 A 객체를 B가 이용하고 있는 도중에 A가 사라지고 새로운 A' 객체를 등록하면 서비스 B한테 이벤트를 날려서 교체하게 해준다.


인터페이스 -> Scanner -> Assembler -> DI Framework -> OSGi


신고
top


Whiteship's 스프링 DM 레퍼런스 1.0 m3 배포

Spring DM/etc : 2008.07.20 12:20



지난 배포 뒤에 시간좀 오래 걸렸습니다. 크게 달라진 건 없고, 10장과 Appendix A, B, C, D, E를 추가했습니다.


생략한 표들을 추가하는 작업까지 완료하면, 1.0 정식판이 완성 될 것 같습니다.
신고
top


bnd에 번들 실행환경 설정하기

Spring DM/exercise : 2008.07.13 09:29


Bundle-RequiredExecutionEnvironment: J2SE-1.5, J2SE-1.4

이런식으로 설정하면 이 설정 그대로 MANIFEST.MF에 복사해서 붙여넣어줍니다. 모든 번들에 이런 실행환경을 설정해주는것이 좋겠죠. 가용한 설정 값드은 다음과 같습니다.

CDC-1.0/Foundation-1.0
CDC-1.1/Foundation-1.1
JRE-1.1
J2SE-1.2
J2SE-1.3
J2SE-1.4
J2SE-1.5
J2SE-1.6
OSGi/Minimum-1.0
OSGi/Minimum-1.1

1.5 환경에서 1.4 용 번들을 만들고 싶을 때, -source 와 -target을 사용해서 컴파일 하면 되지만, -source는 애노테이션이나 제네렉, for-each문과 같은 기능을 꺼버리고, -target은 클래스 파일 버전을 1.4 환경이 읽을 수 있도록 설정하는 것일 뿐, 실제 API 상의 차이는 잡아내지 못합니다. 예를 들어, String의 contains() 메소드는 1.5에 추가되어서 JDK 1.5 이상이 환경에서 얼마든지 저 메소드를 사용할 수 있습니다. 저 코드를 담고 있는 번들을 -target과 -source를 사용해서 1.4 번들로 만들고 JDK 1.4 위에서 돌리면, 예외가 발생합니다. 당연한거죠. 따라서, 1.4 용 번들을 만들고자 한다면, JDK 1.4 위에서 해당 번들을 만들고 패키징하는 것을 권장합니다.
신고
top




: 1 : 2 : 3 : 4 :





티스토리 툴바