Whiteship's Note


5.7. Diagnosing problems

Spring DM/Chapter 5 : 2008.05.25 22:40


여러분이 사용하기로 선택한 OSGi 플랫폼 구현체는 현제 OSGi 환경 상태에 대한 정보를 잘 제공해 주어야 한다. 예를 들어, -console 아규먼트를 Equinox 시작시 추가하면 커맨드 라인 콘솔을 제공한다. 이것을 통해 어떤 번들들이 설치되어 있고 그들의 상태와, 해당 번들에 의해 공개된 패키지와 서비스, 번들 Resolve 실패 원인, 번들 라이프사이클 다루기 등을 할 수 있다.

게다가, 스프링 자체와 스프링 DM 번들은 문제의 원인을 조사할때 사용할 수 있는 확장 가능한 로깅 체계가 마련되어 있다. Simple Logging Facade for Java(slf4j) slf4j.jar 와 slf4j-log4j13.jar 번들을 설치하길 권장한다. 그렇게만 하면, 번들 클래스패스 루트에 log4j.properties 파일을 생성하여 사용할 수 있다.

스프링 DM 모듈은 commons-logging API를 내부적으로 사용하고 있는데, 이것은 로깅 구현체가 완전히 끼워맞출 수 있는pluggble 형태로 개발되었다는 것을 의미한다.
top

Write a comment.


5.6. Considerations when using external libraries

Spring DM/Chapter 5 : 2008.05.24 23:08


대부분의 엔터프라이즈 애플리케이션 라이브러리들은 context class loader를 통해서 타입과 리소스를 로딩할 수 있다고 가정한다. 보통 개발자가 이 것을 직접 다루지는 않지만, 애플리케이션 서버, 컨테이너 또는 멀티 쓰레드로 동작하는 애플리케이션들은 context class loader를 사용하고 있다.

OSGi R4에서는 context class loader를 통해 가용한 타입이나 리소스 집합에 대해 정의되어 있지 않다. 이것은 OSGi 플랫폼이 쓰레드 context class loader 값을 보장하지 못한다는 것이고 다시 말하자면, ccl을 관리하지 않는다는 것이다.

따라서 클래스 로딩을 하거나 동적으로 새로운 클래스를 생성하는 코드가 OSGi 환경에서는 제대로 동작하지 않을 수 있다.

스프링 DM은 해당 번들의 application context를 생성하는 도중에 번들의 클래스패스에서 가용한 모든 타입과 리소스들을 ccl을 통해 접근할 수 있도록 보장한다. 또한 스프링 DM은 외부 서비스를 호출할 때와 공개한 서비스에 대한 요청에 서비스를 할 때 CCL을 통해서 접근 가능한 클래스와 리소스를 설정할 수 있다. 방법은 5.5에서 설명했다.

OSGi R5에서는 제 3의 라이브러리에 의해 추가된 암묵적인 클래스 패스와 생성된 클래스를 지원하기 위한 스펙을 정하고 있다. 그전까지는 DynamicImport-Package manifest 헤더를 사용하거나,  Equinox의 버디buddy 매커니즘을 사용할 수 있을 것이다.
top

Write a comment.


5.5. Importing and Exporting packages

Spring DM/Chapter 5 : 2008.05.24 00:19


Import-Package와 Export-Package manifest 헤더에 대한 자세한 내용은 OSGi 스펙을 참조하도록.

번들은 자신이 의존성을 가지는 모든 외부 패키지들을 Import-Package를 사용해서 설정한다.

만약 다른 번들들이 사용할 필요가 있는 타입을 제공해야 한다면, Export-Package를 사용하여 외부 번들에서 사용할 수 있는 모든 패키지를 설정한다.
top

Write a comment.


5.4. Spring XML authoring support

Spring DM/Chapter 5 : 2008.05.19 22:44


스프링 2.0은 보다 쉬운 XML 설정과 확장 가능한 XML을 도입했다. 이 중 후자는 커스텀 스키마를 만들어 스프링 XML 인프라가 자동으로 해당 설정을 읽을 수 있는 것이 가능해졌다. 그냥 그것들을 클래스패스에 두기만 하면 된다.(이 부분은 토비 사부님이 1회 KSUG에서 발표하셨던 내용) 스프링 DM은 이 기본 지식을 활용해서 OSGi 환경에서 부가적인 코드나 menifest 선언 필요 없이 커스텀 스키마를 사용할 수 있도록 했다.

Spring DM은 OSGi 공간에 배포되는 모든 번들(스프링 DM 번들이든 아니든 상관없이)들을 조사하여 커스텀 스프링 네임스페이스 선언을 가지고 있는지 스캔한다.(META-INF/spring.handlers 와 META-INF/spring.schemas 번들 영역을 확인한다.) 만약에 해당하는 선언을 찾으면, 스프링 DM은 해당 스키마를 만들고 해당 네임스페이스는 OSGi 서비스를 통해서 자동으로 스프링 번들에 의해 사용이 가능해진다

=> 즉, 커스텀 스키마를 사용하는 번들을 배포할 때 필요한 건, 네임스페이스 파서와 스키마를 제공하는 라이브러리를 OSGi 플랫폼에 배포하기만 하면 된다는 것이다.

번들의 클래스 패스 내부에 있는 커스컴 스키마는 OSGi 공간에서 다른 번들들에 의해 사용될 수 있다. 하지만, 번들 내부 라이브리의 네임스페이스는 다른 번들들에의해 공유되지 않는다. 다른 번들들이 볼 수 없다.

=> 번들로 배포된 네임스페이스만 공개 되고, 내장된 라이브러리의 네임스페이스는 공개하지 않음.

스프링 DM을 사용하면, 커스컴 네임스페이스 기능을 어떠한 부가작없도 필요없이 투명하게 지원한다. 내장된 네임스페이스 제공자(Embedded namespace provider)들은 우선권을 가지지만 공유하지는 않는다. 이와 반대로 번들로 배포된 제공자(providers deployed as bundle)들은 다른 번들들에서 참조할 수 있다.
top

Write a comment.


5.3. Required Spring Framework and Spring Dynamic Modules Bundles

Spring DM/Chapter 5 : 2008.05.14 23:42


스프링 Extender가 제대로 동작하려면 OSGi 플랫폼에 배포해야 할 몇몇 번들 아티팩트들이 있다.
- org.springframework.osgi.extender : extender 번들 자신
- org.springframework.osgi.core : 스프링 DM을 지원하는 핵심 구현체 변들
- org.springframework.osgi.io : 스프링 DM I/O 지원 라이브러리 번들

여기에 추가로 스프링 라이브러리가 필요한데, 스프링 2.5부터는 OSGi 플랫폼에 바로 배포가 가능한 형태로 배포하고 있다. 그 중에 다음을 필요로 한다.
- spring-core.jar
- spring-context.jar
- spring-beans.jar
- spring-aop.jar

추가로 다음의 라이브러리 번들을 필요로 한다. OSGi 플랫폼에 배포 가능한 형태의 JAR 파일들을 Spring DM With Dependencies 형태로 배포한 파일에 들어있다.
- aopalliance
- backport-util(JDK 1.4에 돌릴 때만 필요)
- cglib-nodep
- commons-logging API(SLF4J 강추)
- logging 구현체
top

Write a comment.


5.2. Extender configuration options

Spring DM/Chapter 5 : 2008.05.14 23:29


번들과 관련된 설정이외에, 스프링 DM은 extender의 기본 행위를 설정할 수도 있다. 이것은 Spring-DM을 관리하는 환경Managed Environment에 포함시키거나 여러 번들에 걸친 기능이 필요할 때 유용하다. 확장 가능한 설정을 위해, extender는 OSGi의 fragment를 사용하여 기본 값을 재정의 할 수 있다. extender는 META-INF/spring 밑에 있는 모든 XML 파일을 읽어들이며 application context(OsgiBundleXmlApplicationContext)를 생성한다. extender의 기본 설정을 재정의하려면, 아래 테이블을 보고 원하는 빈을 읽어와서 정의를 하고 spring-osgi-extender.jar의 Fragment로 붙이면 된다.

Fragment-Host: org.springframework.bundle.osgi.extender

표생략

5.2.1. Listening to Extender events

번들의 application context 시작이나 실패시 로그를 남기고 싶을 수 있다. 이런 경우, 스프링 DM이 제공하는
org.springframework.osgi.context.event 패키지를 정의하여 OSGi application context가 보낼 수 있는 이벤틀를
정의할 수 있다.

현재 지원하는 이벤트는 딱 두개
- OsgiBundleContextRefreshedEvent
- OsgiBundleContextFailedEvent

이 이벤트들을 받길 원하는 쪽에서는 OsgiBundleApplicationContextListener를 구현해야 한다. 그리고 해당 서비스를
OSGi 서비스로 공개하야 한다. 그럼 스프링 DM이 알아서 리스너들을 찾아서 이벤트를 그쪽으로 보내줄 것이다.

이런식의 이벤트 처리는 OSGi의 장점을 모두 누릴 수 있다. 즉 extender가 이벤트 배포자나 이벤트 리스너로 부터
완전히 분리되어 있으며, 등록/해지 과정도 간단하다.

스프링 DM 이벤트와 스프링 이벤트와는 조금 차이가 있는데, 스프링 이벤트는 이벤트가 발생한 applicaion context
내부의 빈으로 이벤트를 보내지만, OSGi 이벤트는 자신을 지켜보고 있는 다른 application context의 빈으로 보내진다.

top

Write a comment.


5.1. Bundle format and Manifest headers

Spring DM/Chapter 5 : 2008.05.08 20:05


각각의 애플리케이션 모듈은 OSGi 번들로 패키징해야 한다. 번들은 META-INF/MANIFEST.MF 파일을 가지고 있는 jar 파일이다. OSGi 서비스 플랫폼 핵심 스팩 3.2에서 그 자세한 내용을 살펴볼 수 있다. 몇몇 OSGi 구현체들은 풀어헤쳐진 jar 파일을 지원하지만 형식은 동일하다.

스프링 Extender는 번들은 "스프링이 가미된"Spring-Powered 번들을 인식하고 해당 번들에 연관된 애플리케이션 컨텍스트를 번들이 시작할 때 다음의 조건 중에 하나라도 만족하면 만들어 준다.
  • META-INF/spring 폴더에 하나 이상의 .xml 파일을 가지고 있을 경우.
  • META-INF/MENIFEST.MF 파일에 Spring-Context라는 헤더가 있을 경우.
보태자면, 만약 부가적으로 SpringExtender-Version 헤더를 manifest 파일에 추가하면, extender는 명시된 버전 조건을 충족시키는 번들만 인식할 것이다. 버전은 Bundle-Version에 명시되어 있다. SpringExtender-Version의 값은 OSGi 스펙을 따라야 한다.

Spring-Context 헤더가 빠져있는 경우 extender는 META-INF/spring 폴더 안에 있는 모든 파일을 유효한 스프링 설정 파일로 인식한다.

Application Context는 이런 파일들의 집합으로 구성된다. 권장하는 방법은 Applicaion Context 설정을 최소한 두 개의 파일로 나누는 것이다. 하나는 모듈이름-contet.xml 이고 다른 하나는 모듈이름-osgi-context.xml 로 말이다.
  • 모듈이름-context.xml - OSGi와 상관없는 일반적인 빈 설정들을 담는다. 최상위 엘리먼트를 bean으로 사용.
  • 모듈이름-osgi-context.xml - OSGi 서비스로 import/export 하는 빈들을 설정한다. 최상위 엘리먼트를 Spring OSGi 네임스페이스로 사용한다.
menifest 파일의 Spring-Context 헤더는 설정 파일 집합을 기술하기 위해 사용한다. 자원 경로는 상대 경로로 인식하고 여기에 하나라도 설정을 하면 META-INF/spring 폴더에 있는 파일들은 무시한다. 다음과 설정할 수 있다.

Spring-Context: config/account-data-context.xml, config/account-security-context.xml

가용한 설정 옵션
  • create-asynchronosly(false|true): 애플리케이션 컨텍스트를 비동기적으로 생성(이게 기본값)할지 동기적으로 생성할지 설정.
Spring-Context: config/account-data-context.xml;create-asynchrously:=false

  • wait-for-dependencies (true|false):  필수 서비스 의존성을 만족 할 때 까지 대기할지(이게 기본값) 말지 설정.
Spring-Context: config/osgi-*.xml;wait-for-dependencies:=false

  • timeout (300): 대기 시간 설정 기본값은 5분. 300초. 초 단위로 설정. wait-for-dependencies가 false면 이 값은 무시함.
Spring-Context: *;timeout:=60

  • publish-context (true|false): application context 객체 자체를 서비스 레지스트리에 등록할지(이게 기본값) 말지 설정.
Spring-Context: *;publish-context:=false



top

Write a comment.


Chapter 5. Packaging and Deploying Spring-based OSGi applications

Spring DM/Chapter 5 : 2008.05.05 23:56


보통의 스프링 애플리케이션들은 단일 Application Context를 사용하거나, 서비스 계층, 데이터 계층 그리고 도메인 객체를 가지고 있는 부모 Context와 웹 계층 컴포넌트들을 가지고 있는 자식 Context로 나눠서 사용했을 것이다. Application Context는 여러 설정 파일들을 뭉쳐서 생성할 수 있었다.

애플리케이션을 OSGi에 배포할 때 자연스러운 방법은 애플리케이션을 OSGi 서비스 레지스트리를 사용하여 상호 작용하는 번들 집합체로 패키징 하는 것이다. 독립적인 하위 시스템은 독립적인 번들 또는 번들들의 집합체로 패키징해야 한다.(수직 파티셔닝) 하위 시스템은 단일 번들로 묶을 수도 있고, 레이어별로 번들을 구성할 수도 있다.(수평 파티셔닝) 예를 들어, 웹 애플리케이션은 간단하게 네 조각으로 나눌 수가 있다. 웹 번들, 서비스 계층 번들, 데이터 계층 번들, 도메인 모델 번들.
사용자 삽입 이미지

이 예제에서 데이터 계층 번들( 분홍색 Application bundles의 첫 번째 녹색 네모)은 데이터 계층 Application Context에 여러 내부 컴포넌트(bean들)들을 가지고 있으며 그 들 중에서 두 개의 빈을 공개적으로 외부에서 접근 가능하도록 그들을 OSGi 서비스 레지스트리에 등록했다.

서비스 계층 번들(Application bundles의 두 번째 녹색 네모)은 역시 여러 개의 내부 커포넌트를 가진 Application Context를 가지고 있고, 그 중 몇개가 데이터 계층 서비스들을 사용하려고 import 하고 있다. 서비스 계층 컴포넌트 중에 두 개를 외부에서 이용할 수 있도록 OSGi 서비스 레지스트리에 등록했다.(레지스트리 그림은 빠져있어서 2% 아쉽..아니면 서비스로 노출시킨 bean은 다른 색으로 그려주던지...)

웹 컴포넌트 번들(Application bundles의 세 번째 녹색 네모)은 Web application context에 여러 컴포넌트들을 가지고 있고 그 중 몇 개는 서비스를 OSGi 서비스 레지스트리로부터 참조해 온다.

도메인 모델 번들(Application bundles의 네 번째 녹색 네모)은 오직 도메인 모델 타입은 컴포넌트(걍 빈이라고 하지..)가 될 필요가 없기 떄문에 이 번들에는 Application context가 없다.

==============================

애플리케이션을 여러 번들로 쪼갤 때 가장 기본적으로 생각해 볼 수 있는 단서를 제공해 줍니다. 스프링 레퍼런스는 정말 잘 만드는 것 같습니다. 수평으로 쪼개기와 수직으로 쪼개기라.. 멋져부러...
top

Write a comment.