Whiteship's Note

'OSGi'에 해당되는 글 42건

  1. 2008.12.05 S1A - Spring Dynamic Modules Updates : Costin Leau
  2. 2008.12.04 S1A - OSGi best practive by 코스틴 리우
  3. 2008.11.27 오호.. 스프링소스 manifest 헤더가 OSGi에 추가되는군요
  4. 2008.11.23 OSGi uses 충돌 감지하기
  5. 2008.10.21 OSGi 툴 세트 Pax
  6. 2008.09.25 Shared Mutable State (2)
  7. 2008.09.25 The Price of Freedom
  8. 2008.09.25 Concurrency and OSGi
  9. 2008.09.15 OSGi 개발에 PDE가 필요한가?
  10. 2008.08.25 OSGi에서 SessionFactory(Hibenate) 사용하기
  11. 2008.08.20 OSGi 패키지가 아니라 서비스야 말로 진정한 Dynamic
  12. 2008.08.16 하이버네이트 3.3.0 GA 릴리즈~
  13. 2008.08.14 OSGi 기반 프레임워크과 애플리케이션 아키텍처 진화 과정 (2)
  14. 2008.08.14 OSGi에서 Hibernate의 SessionFactory 문제 (2)
  15. 2008.08.12 국내 최초 OSGi 기반 애플리케이션 프레임워크 OSAF 1.5 - 멀지 않았다. (2)
  16. 2008.07.20 Late Binding in Java (2)
  17. 2008.07.13 bnd에 번들 실행환경 설정하기
  18. 2008.07.13 OSGi에서 클래스 로딩 순서
  19. 2008.07.12 버전 매기기와 범위 설정
  20. 2008.07.10 Required-Bundle을 비추하는 이유
  21. 2008.07.10 bnd 사용해서 API 가져오기(Import)
  22. 2008.07.10 Java의 Classpath 한계와 OSGi
  23. 2008.07.10 bnd 사용해서 API 공개(Export) 하기
  24. 2008.07.10 유용한 OSGi 팁
  25. 2008.07.09 Spring Dynamic Modules Maven Archetype
  26. 2008.07.08 Eclipse에서 bnd 사용해서 번들 만들기
  27. 2008.07.07 Spring DM Extentions
  28. 2008.07.07 A.1. Configuration Admin
  29. 2008.07.07 Compendium Services
  30. 2008.07.07 Eclipse에서 Felix 사용하기

S1A - Spring Dynamic Modules Updates : Costin Leau

Spring/S1A : 2008.12.05 12:33


스프링 DM 기본 설명

스프링 애플리케이션에서 추가 코드 없이 OSGi를 사용할 수 있다.
=> 스프링 철학과 일맥상통한다. non-invasive

스프링 DM
- 오라클(/BEA)와 함꼐 협업하고 있다.
=> 스프링 DM이 OSGi 스펙을 주도 하고 있다.

Raw OSGi
=> 다이나믹스를 다루기 위한 반복적인 코드가 필요하다.
=> OSGi 번들은 일반 JAR 파일로 무엇을 사용하고공개할지 정의한 파일을 가지고 있다.
=> 손수 해야 할 일이 많다.

OSGi에서 스프링 사용하기
=> OSGi 서비스를 룩업하지 말고 DI하기

POJO developement in OSGi

기능 살펴보기

번들 == ApplicationContext
=> 하나의 번들은 하나의 application context를 가지고 있다. 직접 만들 필요는 없다. 모듈을 정의하고 설정을 만들고 배포하면 되지.. 스프링을 이용하려고 뭔가를 하지 않아도 된다.

OSGi-aware Contexxt
=> OSGi 환경에 대해 알고 싶다면(예를 들어, BundleContextAware)같은 인터페이스를 사용할 수 있다.
=> bundle 스코프 제공
=> 여러 모듈에 걸친 application context 설정파일 사용가능

애플리케이션 == 모듈 집합

OSGi 서비스 == 스프링 빈

=> 서비스 레지스트리는 loose coupling을 실현해준다.

서비스 공개하기(export)
=> 보통 인터페이스를 기준으로 공개한다.
=>  auto-export 속성

서비스 참조하기(import)
=> 서비스 다이나믹스를 내부에서 다뤄준다.

데모
1. STS에서 dm 서버 실행한다.
2. localhost 2401로 telnet한다.
3. osgi> 콘솔 확인 help로 기본 명령어 확인
4. ss로 설치된 번들 확인
5. bundle 번들id로 번들 정보 확인

1. 간단한 서비스 공개(하나는 all-classses, 하는 interface)
2. 번들을 dm 서버에 설치하고 공개된 서비스 확인

1.  shape 번들 만들고 서비스 세 개 공개
2. MF 파일 고칠 거 없다.
3. dm 서버에 배포하고 공개된 서비스 확인

1. painter manager 번들 만들고 painter와 packageAdmin 서비스 레퍼런스 가져온다.
2. osgi:list로 여러 서비스를 참조할 수 있다.
3. BundleLogger에  packageAdmin 주입.

서비스 다이나믹(dynamics)
=> dynamic은 서비스가 언제든지 새로 추가되거나 없어질 수 있다는 거다.
Dependency resilience

만약
- 대응하는 서비스가 없다면
- 대응하는 서브시가 여러 개라면
- 대응하는 서비스가 사용 도중 없어지면
- 더 잘 매칭하는 새로운 서비스가 배포 되면

import cardinality
- 1..X: 애플리케이션 시작할 때 필요하다
=> X .. 1 일 때 서비스가 사라지면 다른 서비스 참조한다.
=> X .. N 일 때 서비스가 사라지면 컬렉션에서 빼준다.

데모

1. 쓰레드로 2초마다 그림그리는 메소드 실행하는 번들 만듬
2. painterManager 번들 stop
3. 다시 start
4. 로깅을 stop(등록한 서비스를 제거한다.)
=> 없어지면 대체제를 찾고 대체제가 없으면 기다린다.
5. 로깅 다시 start

리스닝
=> 메소드 매개 변수에서 서비스를 필터링할 수 있다.

통합 테스트 데모
1. AbsractConfigurableBundleCreatorTests 상속 받기
2. bundleContext.getBundles() 사용하기
3. getPlatformName으로 테스트할 플랫폼 선택가능. Platform.EQUINOX

1.2.0은 Compendium Services Integration
- Configuration Admin 속성을 참조하라.
- osgix 네임스페이스 공부할 것...

OSGi 4.2 계획
- Spring DM은 OSGi 4.2를 기준으로 한다.
RFC 124의 RI가 된다.
- 2009년 5/6월을 배포를 목표로..
=> 스프링 네임스페이스랑 OSGi 네임스페이스가 거의 비슷한 형태로..

로드맵
- 1.2.0은 2009년 1/2월
- 2.0(Spring, 3.0, JDK 5.0, RFC 124 RI) 2009년 5/6월

신고
top


S1A - OSGi best practive by 코스틴 리우

Spring/S1A : 2008.12.04 06:53


자바 애플리케이션 모듈화는 어렵다. 하지만 해결책은 있다.

개요
- 모듈성 개요
- 클래스 & 리소스 로딩
- 서비스 다아나믹스

모듈화 목적
=> 차 사고 났을 때 헤드라이트 나가면 거기만 갈아 낄 수 있도록.
=>

모듈성이 없는 app
- web/facade/repository 한 덩어리

모듈성이 있는 app
- ADao, BDao, CService

OSGi
- 1999년부터 사용 가능
- JDK 1.2 호환

모듈화 대안 - JSR277/JAM
- JAva Module
- "Opaque" 스펙 진행중
=> 어떻게 되가고 있는지 모르겠다.
- JDK 7.0 호환
=> 왜냐면 새로운 키워드를 사용해야 해서...
- OSGi 호환

모듈화 대안 - HK2
=> glassfish 팀이 사용하고 있다.
- 2007년 말에 밸표됨
- 애노테이션 기반 간단 IoC
- 정적인 시스템

OSGi/JSR 277 비교
- http://www.osgi.org/blog/
- http://underlap.blogspot.com/

클래스로딩
- 모듈은 자기 내부 패키지와 다른 모듈에서 가져온 패키지만 로딩할 수 있다.
- 모든 패키지는 버전을 가지고 있다.

Type Leakage
  - 공개한 클래스 계층 구조에서 내부 클래스
  - 공개한 시그너쳐에 있는 내부 클래스
=> 이런 일이 발생하면 안 돼. 그럼 어떻게 해야 할까?
- 내부 패키지를 공개해(
- '연결' 인터페이스를 축출해
- Generic public 타입을 사용해
- 검증 도구(bnd)를 사용해

추이적인 의존성
- A -> C1, B ->C2 => 이렇게 여러 버전 배포 가능하다. 이럴 때 X -> A, B 이렇게 되면.. C 패키지는 어떤 버전 사용하게 되는거야?? => A나 B가 사용하고 X가 직접 사용 안 하면 상관없겠지만 X가 직접 해당 패키지를 사용하게 되면 타입 캐스팅 충돌 발생할꺼다 그래서 바운더리를 만들어줘야 한다. X -> A, B, C1 이런식으로..
또는
=> A, B, X -> C2 이런식으로 한 버전을 참조하도록 한다.
- uses 지시어를 사용해서 둘 사이의 관계를 기술하라.

AOP
- 동적 클래스 확장
- 기존 모듈 경계를 깨트린다.
=> AOP의 아름다움은 바로 transparent하게  로깅이나 트랜잭션 등을 처리해 준다는 것이다.

(과거) 컴파일-타임 위빙
- Imports를 수정해야 한다.
- provisioning 을 통해서 한다.

로드 타임 위빙
=> 이미 리졸브 된 상태에서 추가로 필요한 패키지가 있으면 못 가져온다.
- Synthetic 클래스로더 하나가 Proxy Creator Module, Advoce Module, Target Module을 모두 관리해야 한다.

동적인 로드 타임 위빙
=> 위에서 설치한 모듈이 중간에 없어지면 어떡하냐.. 프록시를 없앴다가 다시 만들어야 돼.
- 의존하는 모듈을 update 해줘야 돼
=> SpringSource DM 서버에서는 알아서 해준다.

영속화/리모팅
- 클래스 로더 사용과 연관이 많다. => 해결책은 synthetic classloader

DynamicImport-Package
- 이 건 사용을 권장하지 않아.
=> 일관성이 없이 매번 실행할 때마다 문제가 있을 수도 있고 없을 수도 있다. 여러 버전을 사용할 수 있을 경우에 완전 운에 달린 게임이다.
- 프로토타입에서나 사용하고 제품에선 사용하지 말아라.

리소스 로딩
=> 클래스 로딩과 비슷한데 silent error가 발생한다.
- 리소르를 클래스와 동일한 곳에 둔다. 클래스에서 사용할 수 있도록 -> portable cnofig 자동으로 export 된다.

공유 자원
- META-INF/services
- 버저닝이 문제가 딜 수 있다.
=> 헤결 책은 extender

Externder 패턴
=> 번들 내부 리소스를 OSGi 서비스에서 사용가능하게 해준다.

웹 애플리케이션

오너쉽 문제 누가 로딩을 주도하는가?
- OSGi 플랫폼이?
- 웹 컨테이너가?
옵션
- HttpService
- Servlet Bridge
- ClassLoader bridge(스프링 DM 서버)

웹 애플리케이션에서 클래스 로딩
- WAR는 미리 정의되어 있는 클래스패스가 있다.
- OSGi에서는 뭔가가 필요하다. => 번들 처리 도구를 사용하거나, dm 서버가 해준다.

리소스 로딩
=> 스프링DM/dm 서버가 알아서 해준다.

서비스 Dynamics

OSGi 서비스
- 간적접인 계층
- 객체를 서비스 registry에 추가하거나 제거할 수 있다.
- 타입 필터링이 자동으로 적용된다.
- 서비스는 동적이다.(언제든 사라지고 나타날 수 있다.)
- OSGi 서비스는 싱글톤이다.

OSGi 서비스와 스프링 DM
- 그림
=> decoupling

서비스 Dynamics
- org.osgi.util.ServiceTracker
- Tracking Proxy(Spring DM) => 참조하던 서비스 없어지면 대체 가능한 다른 걸로 update 해준다.

다른 이슈
- 쓰레드 Context 클래스로더
- TCCL을 사용하지 말거나 스프링 DM/dm 서버처럼 관리하라.
- 쓰레딩
- 번들/애플리케이션 관리

결론
- STS, Spring DM, dm 서버를 사용하라. @.@

신고
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


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 툴 세트 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

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

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


하이버네이트 3.3.0 GA 릴리즈~

Hibernate/etc : 2008.08.16 11:04


http://in.relation.to/Bloggers/HibernateCore330GoesGA

주요 변경 사항
1. 빌드를 Maven기반으로 변경.
2. 여러 모듈 jar로 세분화 함.
3. 2차 캐시 SPI 재설계.
4. JBossCache 2.x를 2차 캐시 프로바이더로 통합.

http://www.infoq.com/news/2008/08/hibernate-33

대충 읽었는데, OSGi가 유명해 지면서, OSGi에서 발생하는 하이버네이트 문제들(SessionFactory의 동적인 변경, 클래스로딩 이슈)에 대해 알고는 있는데, 이번 배포판에서는 아직 해결이 안 됐다고 합니다. 하지만, 적극적으로 해당 이슈들을 모두 해결할 의사는 있다고 합니다. 시간 문제라는거죠. 캬~ 좋아 좋아.
신고
top


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


국내 최초 OSGi 기반 애플리케이션 프레임워크 OSAF 1.5 - 멀지 않았다.

모하니?/Coding : 2008.08.12 18:10


사용자 삽입 이미지

프로젝트와 프로젝트 사이에 텀이 생겨서, 요즘 다듬고 있는 OSAF 1.5 입니다. 범용성은 없고, 얼리어댑터에게만 유용한 프레임워크입니다. 초고속 애플리케이션 개발을 지원하는 OSAF의 맛보기 정도랄까요.

프로젝트를 만드는 김에 OSGi 번들로 만들생각입니다. 굳이 Spring DM 번들일 필요는 없지만, 일단 베이스는 Spring DM 번들로 시작했습니다. 보시면 이미 번들도 생성이 되었죠. 캬캬캬

설치도 해봤습니다. 맨 아래에 있습니다.

사용자 삽입 이미지

하지만... INSTALLED 상태로 짐작하실 수 있겠지만... 미싱 라이브러리가 장난 아닙니다.

사용자 삽입 이미지

그래서.. 걍 이 번들 안에 나머지 jar도 왕창 다 묶어서 배포해버릴 생각으로
bundle:bundleall을 사용했습니다.(무슨 말인지 이해 못하시겠다면, 두 번째 링크 참조) 하지만, jta 라이브러리를 손댈 때 문제가 발생하더군요.

사용자 삽입 이미지

멀지 않았습니다. 코드만 공개하려면 일찌감치 공개할 수 있었지만, 주석도 달고 테스트도 추가하면서 현재 커버리지 53%를 넘긴 상태 입니다. 핵심 코드 테스트는 오늘부로 모두 완료한 상태고, 나머진 테스트하기 귀찮은 것들이 몇 개 있는데, 그것들은 뭐 기계적으로 좀 추가해서라도 65% 정도는 넘길 생각입니다.  이 번들이 RESOLVED만 되면, 최종 관문으로 사부님한테 검사 받고, 그 관문이 통과되면 예제를 후루룩 만든담에.. 공개!!!

멀지 않았습니다.

참조
http://www.springsource.com/repository/ <-- 번들 많아요. 없는 것도 있어요.(전부 있다는 뜻이 아님.)
http://felix.apache.org/site/maven-bundle-plugin-bnd.html <-- bnd 메이븐 플러긴 공부좀 해야겠어요. 지금은 기본 설정으로 만들었지만;;)
http://notehive.com/wp/2008/07/23/osgi-hibernate-spring-dm-sample/ <-- JTA를 포함한 하이버네이트 관련 번들을 볼 수 있는 코드를 제공하는데.. svn 주소가 접속이 안 됨. 7월에 올린 글인데 벌써 코드를 지운거야?? ㅠ.ㅠ 왜..

ps: 과연 사부님이 최종 관문 통과 시켜주실까??
신고
top

TAG OSAF, OSGi, ㅁㄴ

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


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


OSGi에서 클래스 로딩 순서

Spring DM/exercise : 2008.07.13 09:16


사용자 삽입 이미지

먼저, java.* 에 들어있는 클래스거나, org.osgi.framework.bootdelegation 속성에 설정된 클래스면 Parent Class Loader에게 클래스로딩 책임을 위임합니다.

다음은 Import-Packaged에 명시된 패키지에 들어있는 클래스라면, 클래스로딩 책임을 해당 클래스를 Export 한 번들의 클래스로더에게 위임합니다.

다음은 Required-Bundle 설정으로 참조한 패키지에 들어있는 클래스라면, 클래스로딩 책임을 해당 번들의 클래스로더에게 위임합니다.

다음으로 자기 자신 내부에 해당 클래스가 있는지 찾습니다.

다섯번째는 자신에게 붙어있는 Fragment에서 해당 클래스를 찾아봅니다. 클래스로더는 자신의 클래스로더를 사용합니다.

여섯번째는 위 그림에 빠져있는데 동적 클래스로딩과 관련이있습니다. 이 부분은 나중에 살펴봅니다.

참조 : http://neilbartlett.name/blog/osgibook/
신고
top


버전 매기기와 범위 설정

Spring DM/exercise : 2008.07.12 00:56


버전 매기기

버전은 다음과 같이 구성되어 있다.

major.minor.micro.qualifier

major.minor.micro는 숫자고, qualifier는 알파벳이나 숫자를 사용한다. major 이 외에는 전부 생략이 가능하다. 예를 들어, 1 은 1.0 이고 이건 다시 1.0.0 이랑 같다. 다음으로 중요한 건 높낮이. 1.0 보다 2.0 이 높은 버전이라는 것에는 이견이 없을 것이며 실제로도 그렇다. 그러나 qualifier 쪽으로 가면 그렇게 쉽진 않다.

A. 1.0.0.whiteship1
B. 1.0.0.whiteship2
C. 1.0.0.whiteship10

이 셋 중에서 가장 높은 버전은 몇 일까? C라고 예상하신 분들도 있겠지만, 정답은 B다. Java의 String 클래스의 compareTo()로 비교해서 높은 값이 높은 버전이 된다. String의 compareTo()는 한 글자씩 왼쪽에서 부터 비교한다. 따라서 B < C < A 순으로 높은 버전이 된다.

버전 범위 설정하기

버전 범위는 Import-Package 또는 Required-Bundle 헤더에서 사용한다. 명시하지 않으면 기본 값은 다음과 같다.

"[0.0.0, *]"

0.0.0 부터 모든 버전을 나타낸다. Export-Package 또는 Bundle-Version에 버전을 명시하지 않은 경우 기본값으로 0.0.0이 설정되기 때문에 양쪽에서 모두 기본값을 사용하는 경우 문제없이 참조할 수 있다. 하지만 역시 버전은 명시적으로 관리해주는 것이 좋겠다.

[] 와 ()의 차이만 알면 되겠다. []는 이상 이하. ()는 초과 미만의 개념이다. [1.0.0, 2.0.0) 이렇게 설정되어 있다면 1.0.0 버전이 있으면 그걸 참조하고 2.0.0 만 있다면 그건 참조하지 않는다. 1.9.9와 1.0.0 두 가지 버전이 존재할 땐 높은 버전의 번들을 선택한다.

그렇다고 매번 "[1.0.0, 1.3.0]" 이런식으로 표기해야 하는 것은 아니다. Spring 2.5 이상 어떤 버전이든 관계가 없을 때는 그냥 "2.5." 라고 설정하면 OSGi 프레임워크는 "[2.5.0, *]" 이렇게 인식할 것이다. 따라서 상위 호환이 보장되는 라이브러리를 참조하고 있다면 버전을 저런식으로 명시해도 된다.

이와 반대로 특정 버전 하나 만 참조하는 라이브러리가 있을 수도 있다. 전~혀 상위나 하위 호환이 되지 않아서 딱 그 버전만 써야 한다면, 그때는 "[2.5.5, 2.5.5]" 이렇게 범위를 딱 해당 버전으로만 좁혀줘야 한다.

신고
top


Required-Bundle을 비추하는 이유

Spring DM/exercise : 2008.07.10 23:04


먼저 Required-Bundle이 뭔지 알아야겠다. Import-Package를 이해했으면 이건 뭐 아주 간단하다.

1. Resolved 상태가 되기 위한 조건

Import-Package 헤더에 명시한 패키지들이 어떤 번들들에 의해서 Export-Package 헤더이 설정 되어 있으면 해당 번들은  RESOLVED가 될 것이다.(물론 필수 였다는 가정하에.)

Required-Bunlde은 번들 단위로 바꿔서 생각하면 된다. 이 번들의 Required-Bundle에 설정한 번들이 RESOLVED 상태가 되어야 이 번들도 RESOLVED 상태가 될 수 있다.

2. Import 하는 패키지의 정적이냐 동적이냐

Import-Package로 패키지를 참조하면, 해당 패키지들만 참조할 수 있다. Required-Bundle로 참조하면 거기에 설정한 번들이 Export-Package에 명시한 모든 패키지들을 Import 한다. 따라서, Required-Bundle에 설정한 번들이 공개하는 패키지의 설정이 바뀌면 이 번들이 가져오겠다고 선언하는 패키지들도 달라지는 것이다.

자 그럼 이제 이 설정을 비추하는 이유를 살펴보자.

1. 위에서도 언급했듯이 Import 대상이 되는 패키지가 변한다. 그게 문제가 될 수 있다. 만약 이 번들이 꼭 필요로 하는 패키지를 저 번들이 가지고 있었는데, 저 번들이 갑자기 그 패키지를 Export-Package 목록에서 빼버렸다. 그래도 저 번들은 RESOLVED가 되었고, 그랬기 때문에 이 번들도 따라서 RESOLVED가 되었다. 하지만 이 번들이 동작하다가 ClassNotFoundException이나 NoClassDefinitionError를 발생시킬 여지가 다분하다.

2. 만약 Required-Bundle에 설정한 번들의 기능이 너무 많아져서 분리해야 된다고 생각해보자. 그럼 Requied-Bundle에 이 번들을 설정했던 모든 (소비자 격인) 번들들의 설정을 전부 고쳐줘야 한다. 얼마나 힘들고 고된 작업인가... 그냥 Import-Package를 썼었다면, 기능이 많아져서 분리를 해도 그냥 Export-Package도 같이 분리해서 가지고 가기만 하면 된다. 소비자 입장에선 아무것도 바꾸지 않아도 된다.

3. 낭비다. 필요 없이 Import 하는 패키지가 생길 것이다.

Required-Bundle 은 OSGi R4에 추가된 기능인데 Eclipse의 영향이 컸다고 한다.

신고
top


bnd 사용해서 API 가져오기(Import)

Spring DM/exercise : 2008.07.10 22:48


번들이 사용할 모든 라이브러리는 MANIFEST.MF 파일의 Import-Package에 기술 되어야 한다.

위의 문장은 맞는 문장일까 틀린 문장일까? 틀렸다. 예외가 있다. 바로 java.* 이하의 패키지들은 기술하지 않아도 된다. 별도의 import 없이도 사용할 수 있기 때문에 Import-Package에 굳이 명시할 필요가 없다. 하지만.. javax.*은 Import-Package에 명시해줘야 한다. javax.swing 이나 javax.awt  같은 것 들.. 또는 org.xml.sax와 같은 것들도 물론 명시적으로 선언해 줘야겠다.

그럼 bnd 설정 파일에는 어떻게 설정할까? bnd에도 Import-Package라는 헤더가 있고 필요한 모든 패키지를 import 하도록 * 로 설정해주면 된다.

Import-Package: *

이렇게.. 하지만 이미 이렇게 기본값(CoC)으로 설정되어 있어서 위의 설정을 아예 적지 않아도 알아서 저런 설정이 있는 것으로 인식해서 MANIFEST.MF 파일의 Import-Package를 만들어 준다. 좋다 좋아..

그래도 Import-Package: 헤더를 bnd  설정에서 사용해야 하는 경우가 있는데 바로. 버전을 명시할 때다. 개발 중이 아니라면 버전은 왠만해선 명시해 주는게 베스트 프랙티스라고 생각된다. 버전은 항상 범위로 설정된다. 보통 다음과 같다.

또 하나 필수 여부를 설정할 때도 Import-Package를 사용해야 한다. 기본은 필수 인데, 필수가 아니게 설정하고 싶을 때는 명시적 설정 해줘야 한다.

Import-Package: org.apache.log4j*;version="[1.2.0,1.3.0]",\
                         javax.swing*;resolution:=optional,\
                         *

위의 설정은 log4j 패키지 버전 1.2.0 이상 1.3.0 이하에 있는 클래스나 리소스를 참조하도록 설정했고, swing 패키지는 굳이 없어도 이 번들이 RESOLVE 상태가 되는데 지장이 없도록 설정했다. 마지막으로 그 외 필요한 모든 패키지들은 필수고 버전은 [0.0.0, *] 이렇게 설정되어서 어떤 버전이든 상관 없이 있기만 하면 된다.

마지막으로 Import-Package에 패키지 명을 명시적으로 선언하는 경우가 있는데, 특정 패키지를 아예 빼버리거나 무조건 추가한다. 왜일까? 특정 패키지를 빼는 경우는 번들의 코드 중에 일부는 절대로 실행이 되지 않을 꺼라는 전제가 있다면 그 부분에서 사용한 패키지를 굳이 Import 할 필요는 없을 것이다. 그리고 왜 bnd가 알아서 필요한 패키지를 찾아서 (MANIFEST.MF 에 있는) Import-Package 헤더에 추가해 줄텐데 명시적으로 등록을 하는 경우가 생길까? 그건 동적으로 로딩할 클래스 때문이다. 그런 클래스들을 담고 있는 패키지는 햇갈리게 * 를 사용하지 말고 명시적으로 전체 패키지 명을 적어주자.


신고
top


Java의 Classpath 한계와 OSGi

Spring DM/etc : 2008.07.10 22:28


자바에서 기본으로 제공하는 "모듈 시스템"이라고 할 수 있는 건 JAR 파일들을 모아둔 클래스패스 덩어리다. 이게 구린 이유는 의존성 관리를 하지 않기 때문이다. 그냥 암묵적으로 어떤 환경에서 실행되리라고 가정해버린다. 클래스패스에 필요한 것들이 있는지를 알 수도 없고 어떤게 필요한지도 알 수 없다. 따라서, 필요한 JAR 파일을 클래스패스에 추가하지 않고 애플리케이션을 실행하면 Runtime 시에 ClassNotFoundException이나 NoClassDefinitionFound 와 같은 에러를 종종 만나게 되고, 어떤 JAR가 빠졌는지 찾으면서 허송세월을 보낸다.

OSGi는 그럼 뭐가 다를까? OSGi는 명시적이며(Explicit), 선언적이고(Declarative) 버전을 적용해서(Versioned) 의존성들을 관리한다.

Explicite
- 번들이 필요로 하는 패키지 또는 서비스와 번들이 공개할 패키지나 서비스를 명시적으로 설정한다.

Declaritve
- 의존성을 기술하는 방법이 매우 간단한 텍스트 형식이다. 따라서 도구를 사용해서 쉽게 의존성을 기술하는 파일을 만들어 낼 수도 있다.

Versioned
- 라이브러리는 계속 변하기 마련이다. 따라서 같은 라이브러리라 하더라도 분명 차이가 있을 것이다. 따라서 OSGi는 모든 번들 의존성 사이에 버전 범위를 기술하도록 했다. 그래서 같은 라이브러리라 하더라도 여러 개의 버전이 동시에 사용될 수 있다.

참조 : http://neilbartlett.name/blog/osgibook/
신고
top


bnd 사용해서 API 공개(Export) 하기

Spring DM/exercise : 2008.07.10 22:17


Export-Package 헤더를 사용하면 된다. 예를 들어 다음과 같이..

Export-Package: whiteship.service.*;version=1.0.0

뒤에 버전은 해당 패키지를 1.0.0 버전으로 공개하겠다는 설정이다. 버전에 대해서는 조금 있다가 정리하자. bnd가 저 설정을 읽으면 다음 작업을 하게 된다.

1. 해당 JAR(번들) 안에 명시한 패키지가 들어있는지 검사한다.
2. MANIFEST.MF 파일에 대상이 되는 패키지를 Export-Package 헤더에 추가한다.

*와 !를 적절히 사용해서 다음과 같이 작성할 수 도 있다.

Export-Package: !com.*, *

com. 이하 모든 패키지는 제외하고 그 나머지 패키지들만 공개하겠다는 설정이다. 이 얼마나 간단한가.. 귿!
신고
top


유용한 OSGi 팁

Spring DM/Appendix E : 2008.07.10 10:58


E.1. OSGi Fragments

OSGi R4에 포함된, fragment는 매우 유용하면서도 강력한 기능이다. fragment는 "호스트 번들에 붙일 수 있는 번들"로써, 대상 번들에 컨텐츠를 추가할 수 있다. fragment는 자신의 클래스로더나 bundle activator를 사용할 수 없으며 호스트에 존재하는 정보를 재정의할 수 없다. 간략하게 fragment 번들을 사용해서 번들을 확장 할 수 있다. 따라서 resource, 클래스, 또는 manifest 요소들까지도 확장 가능한 형태가 된다. 스펙을 다시 인용하면 다음과 같다. "fragment의 주요 사용처는 로케일에 따른 번역 파일 제공이다. 이 것을 사용하여 주요 애플리케이션 번들에서 독립적으로 번역된 파일을 사용할 수 게 해준다."

Spring DM에서 이 기능은 extender와 같은 컴포넌트들을 설정할 때 매우 유용하다. 간단하게 추가할 리소스를 번들로 묶고 Manifest에 한 줄을 추가하면 된다.

Fragment-Host: <host bundle symbolic name>

위 설정을 가지고 있는 번들은 fragment이고 저기에 기술한 symbolic name을 가진 호스트 번들에 구성물들이 첨가가 된다. fragment와 host 번들 symbolic name은 달라야 한다. 예를 들어, Spring DM extender에 fragment를 추가하려면, 다음과 같은 manifest를 작성하면 된다.

Manifest-Version: 1.0                                                                    (1)
Bundle-ManifestVersion: 2                                                                (2)
Fragment-Host: org.springframework.bundle.osgi.extender                                  (3)
Bundle-SymbolicName: org.mydomain.project.fragment                                       (4)
Bundle-Name: my-fragment                                                                 (5)
Bundle-Description: Fragment attached to Spring-DM extender                              (6)

1    Manifest 버전
2    OSGi 번들 버전. 기본값인 1이면 OSGi R3 번들이고 2면 OSGi R4 번들이라 뜻.
3    이 번들을 부착할 번들의 symbolic name. 여기서는 spring-osgi-extender.jar를 가리키는 org.springframework.bundle.osgi.extender로 설정 함. Fragment-Host를 사용하여 OSGi 플랫폼에 자신이 fragment라는 특별한 번들임을 알려줌.
4    fragment symbolic name.
5    bundle name - 부가적이지만 유용한 헤더(가독성 측면에서)
6    bundle 설명 - OSGi 플랫폼이 사용하기 위한 것이 아니라, bundle name 처럼, 사람이 읽기 편한 헤더. 번들의 목적을 확인하기 위한 용도로 사용.

같은 symbolic name을 가진 호스트 번들이 여러 개일 때는 버젼을 명시해서 하나를 선택할 수 있다.

Fragment-Host: org.springframework.bundle.osgi.extender;bundle-version=1.1.0

버전의 기본값은 [0.0.0,∞) 다.


신고

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

유용한 OSGi 팁  (0) 2008.07.10
top


Spring Dynamic Modules Maven Archetype

Spring DM/Appendix D : 2008.07.09 11:16


스프링 DM은 메이븐 아키타입archetype을 제공하여 스프링 DM 번들 개발 시에 사용할 수 있는 자바 프로젝트 기본 틀을 제공한다. 아키타입을 실행하려면 다음의 명령어를 사용하면 된다.

mvn archetype:generate

메이븐 플러그인이 가용한 archetype을 보여줄 것이다. 그 중에서 spring-osgi-bundle-archetype을 선택하면 된다.(현재 32번으로 설정되어 있다.) 그리고 프로젝트에 필요한 몇 가지 정보를 입력한다.(그룹id, 아티팩트id, 버전, 패키지) 가용한 모든 아키타입과 버전은 여기를 참조하라.

물론 archetype:create를 사용해서 직접 아키타입을 설정하여 프로젝트를 생성할 수도 있다.

mvn archetype:create \
-DarchetypeGroupId=org.springframework.osgi \
-DarchetypeArtifactId=spring-osgi-bundle-archetype \
-DarchetypeVersion=   \
-DgroupId=<your-project-groupId>  \
-DartifactId=<your-project-artifactId> \
-Dversion=<your-project-version>

(과연 누가 저렇게 쓸까;;; 오타 없아 커맨드 창에 저걸 전부 입력 할 수 있는 사람~?)

둘 모두 같은 프로젝트 구조를 생성해준다. 그 안에 두 개의 스프링 설정 파일 src/main/resources/META-INF/spring/bundle-context.xml 와 src/main/resources/META-INF/spring/bundle-context-osgi.xml 가 있다. 프로젝트는 OSGi 번들로 패키지 형태가 설정되어 있다.

프로젝트에 MANIFEST.MF 파일이 없는데, 이 건 메이븐의 bnd 플러그인으로 자동 생성한다. 따라서 번들을 생성하고 싶으면 다음과 같이 하면 된다.

mvn package

번들 말고, MANIFEST.MF 파일만 생성하고 싶을 때는 다음과 같이 한다.

mvn org.apache.felix:maven-bundle-plugin:manifest

D.1. 생성한 프로젝트 살펴보기
  • OSGi 번들로 패키징 함.
  • MATA-INF/MANIFEST.MF 는 자동 생성함.
  • src/main/java/<package> 번들이 공개할 패키지
  • src/main/java/<package>/internal 번들이 공개하지 않을 패키지
  • src/main/resources/META-INF/spring/bundle-context.xml 번들 내부에서 사용할 스프링 설정 파일
  • src/main/resources/META-INF/spring/bundle-context-osgi.xml OSGI 관련 스프링 설정 파일
  • .project, .classpath, 그리고 build.properties 파일은 이 프로젝트를 이클립스 PDE 플러긴 프로젝트로 인식하게 해 줌.



신고

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

Spring Dynamic Modules Maven Archetype  (0) 2008.07.09
top


Eclipse에서 bnd 사용해서 번들 만들기



신고
top


Spring DM Extentions

Spring DM/Appendix B : 2008.07.07 23:32


이번 Appendix 장에서는 1.0 배포판부터 추가된 핵심 기능을 확장한 기능들을 다루지만, 이 다음 배포판에서도 그대로 확장으로 있을지는 보장하지 못한다. 이 기능들을 핵심 기능 쪽으로 옮기는 것을 생각하고 있기 때문이다.

B.1. 애노테이션 기반 주입

org.springframework.osgi.extensions.annotation 번들은 OSGi 서비스 레퍼런스를 주입하는 애노테이션을 제공한다. 이 기능을 사용하려면 JDK 1.5 이상을 사용해야 한다.

Bean 클래스 세터 메소드 위에 org.springframework.osgi.extensions.annotation.ServiceReference 애노테이션을 사용할 수 있다. 기본으로 속성 타입으로 OSGi 서비스 레지스트리에서 매치하는 서비스 인터페이스를 찾아서 주입해준다. 예를 들어,

<bean id="annotationDriven" class="MyAnnotationDrivenBeanClass"/>

위의 클래스를 다음과 같이 정의한다면,

public class MyAnnotationDrivenBeanClass {

  @ServiceReference
  public void setMessageService(MessageService aService) { ... }

}

MessageService 인터페이스를 구현한 서비스를 찾아서 가장 적합한 레퍼런스를 주입해준다.(이 때 적합한 레퍼런스를 찾는 방법은 reference 엘리먼트와 동일함)

서비스 룩업을 하는 과정에 몇 가지 설정을 할 수 있게 reference 엘리먼트에 상응하는 속성을 가지고 있다. 자세한건 javadoc을 참조하라.


신고

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

Spring DM Extentions  (0) 2008.07.07
top


A.1. Configuration Admin

Spring DM/Appendix A : 2008.07.07 23:20


A.1.1. Property placeholder support

스프링 DM은 빈 속성 값을 OSGi Configuration Administration 서비스에서 가져오는 기능을 지원한다. 이 기능은 property-placeholder 엘리먼트를 이용하여 사용할 수 있다.  property placeholder 엘리먼트는 "${...}" 이런 형태의 구분자를 사용한 부분의 빈 속성 값을 Configuration Administratino 서비스에서 가져와서 설정해준다. 이 때 persistent-id 속성으로 Configuration dictionary의 키에 해당하는 id를 설정해준다.

나중에 이 부분은 스프링 프레임워크에 있는 방법과 동일하게 변결 될 거라고 합니다.

<osgix:property-placeholder persistent-id="com.xyz.myapp"/>

<bean id="someBean" class="AClass">
  <property name="timeout" value="${timeout}"/>
</bean>

someBean의 timeout 속성 com.xyz.myapp 라는 persistent id로 등록된 Configuration Ditionary 안에 있는 timeout의 값으로 대치 한다.

placeholder 문자열은 빈을 생성할 시점에 대치가 된다. 프로퍼티 값을 변경했다고 해서 생성한 빈 속성을 다시 주입하지는 않는다. 이런 방법이 필요하면 Appendix B의 managed-service와 managed-service-reference를 참조하라. placeholder-prefix와 placeholder-suffix를 사용하여 구분자를 변경할 수 있다.

프로퍼티 값들을 Configuration Dictionary에 두지 않고 직접 생성해서 사용해도 된다. default-propertiies라는 내부 엘리먼트를 사용한다.

<osgix:property-placeholder persistent-id="com.xyz.myapp">
  <default-properties>
     <property name="productCategory" value="E792"/>
     <property name="businessUnit" value="811"/>
  </default-properties>
</osgix:property-placeholder>

이때 persistent-id 속성은 OSGi ManagerdService를 참조해야 한다. ManagedServiceFactory를 참조하면 에러난다.

A.1.2.  Configuration Dictionaries

설정 객체 및 그와 연관된 딕셔너리에 접근하는 방법을 제공하며, 설정 객체에서 직접 빈 객체를 생성하는 것이 스프링 DM 로드맵으로 잡혀있다. Appendix F. Roadmap을 참조하라.
신고

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

A.1. Configuration Admin  (0) 2008.07.07
Compendium Services  (0) 2008.07.07
top


Compendium Services

Spring DM/Appendix A : 2008.07.07 23:04


OSGi Service Platform Service Compendium 스펙에는 OSGi 구현체가 지원할 수도 있는(may be supported) 부가 서비스를 정의하고 있다. 스프링 DM은 추가로 "compendium" 네임스페이스를 지원하여 그런 서비스를 사용할 수 있게 해준다. 보통 해당 네임스페이스 이름으로 osgix를 사용한다.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/osgi"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
   xmlns:beans="http://www.springframework.org/schema/beans"
   xsi:schemaLocation="http://www.springframework.org/schema/osgi 
        http://www.springframework.org/schema/osgi/spring-osgi.xsd
        http://www.springframework.org/schema/osgi-compendium
        http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
        http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd">

   <!-- use the OSGi namespace elements directly -->
   <service id="simpleServiceOsgi" ref="simpleService"
       interface="org.xyz.MyService" />

   <!-- qualify compendium namespace elements -->
   <osgix:property-placeholder persistent-id="com.xyz.myapp"/>

</beans:beans>

현재 이 네임스페이스는 Configuration Admin 서비스만 지원하며 다른 서비스 지원 기능은 추후에 추가될 예정이다.
신고

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

A.1. Configuration Admin  (0) 2008.07.07
Compendium Services  (0) 2008.07.07
top


Eclipse에서 Felix 사용하기






신고
top







티스토리 툴바