Whiteship's Note


Eclipse에서 Felix 사용하기

Spring DM/exercise : 2008.06.22 11:39


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

OSGi 스펙 4.0 구현체 중 하나로, 아파치 재단의 프로젝트입니다. Equinox가 OSGi 구현체로 많이 사용되고 있지만, Felix는 Equinox에 비해 상당히 Compact하게 구현한거라 jar 파일 용량이 반 밖에 안 되며, 스펙도 매우 철저하게 따르고 있기 때문에 Felix에서 구동한 번들이 Equinox나 Knopflepfish에서도 무난히 동작한다고 합니다.

1. 먼저 Felix를 다운로드 받습니다.

http://felix.apache.org/site/downloads.cgi

2. 다음 압축을 풀고 원하는 위치로 이동시킵니다.

저는 C:\java\felix-1.0.4 로 이동시켰습니다.

3. 이클립스에 라이브러리를 등록합니다.

사용자 삽입 이미지
위의 화면을 보시면 아시겠죠? Preferences에 Java -> Build Path -> User Libraries에 New를 클릭한 뒤 Felix라고 입력합니다.

사용자 삽입 이미지
다음은 실제 라이브러리를 추가하는 과정으로 Add Jar 버튼을 누른다음 2번 과정에서 옮겨둔 폴더로 이동한 다음 bin/felix.jar 파일을 선택해줍니다. 그럼 위의 화면과 같이 jar 파일이 추가된 걸 확인할 수 있습니다.

4. Felix 프로젝트 만들기

일반 Java 프로젝트 하나를 생성합니다.
사용자 삽입 이미지
이름에는 전 OSGi Felix라고 줬습니다. 다음 Next를 클릭합니다. 라이브러리를 추가하기 위해섭니다.

사용자 삽입 이미지
Add Library를 클릭하고 User Library를 클릭하면 3번에서 추가한 Felix 라이브러리를 선택할 수 있습니다.

5. 프로젝트 세팅하기

Felix를 구동하는데 필요한 번들과 설정파일을 복사해서 위에서 만든 프로젝트로 붙여넣어 줍니다. 해당 번들과 설정파일은 2번에서 작업한 폴더에 보시면 bundle과 conf라는 폴더 안에 들어있고 그 두 개의 폴더를 복사해서 붙여주면 됩니다.

사용자 삽입 이미지

사용자 삽입 이미지

다음은 설정파일을 변경해서 로그 메시지를 좀 더 많이 뿌리도록 설정합니다. 위에 보이는 config.properties파일을 열고 felix.log.level=4 를 felix.log.level=1로 변경해줍니다.

이제 프로젝트 세팅은 끝났습니다. 실행해 봐야겠죠.

6. 실행 환경 설정하기

사용자 삽입 이미지
Run Dialog로 들어가서 Java Application에 하나의 인스턴스를 만들고 Name에는 Felix를 주고, Project에는 위에서 세팅을 마친 프로젝트 OSGi Felix를 선택해줍니다. 다음 Main은 Search 버튼을 눌러보면 두 개의 클래스가 찾아지는데 그 중에서 아래에 있는 Main을 선택합니다.

사용자 삽입 이미지
자 그럼 이 상태가 되었고 이제 실행할 준비도 끝났습니다.

7. 실행하기

Run을 클릭합니다.

사용자 삽입 이미지

프로파일 이름을 달라고 하네요. 아무 이름이나 줍니다. 전 tutorial이라고 줬습니다.

사용자 삽입 이미지
그럼 뭔가가 설치되는게 보입니다. 뭔 뜻인지는 모르겠습니다. 패스.

현재 설치된 번들들의 상태를 참조하려면 ps를 입력합니다.
사용자 삽입 이미지
음.. 총 네개의 번들이 동작중이군요.

사용할 수 있는 명령어를 참조하려면 help를 입력합니다.

사용자 삽입 이미지

끝~
top

TAG Eclipse, Felix

머리를 볶았습니다.



난생첨 파마라는 걸 해봤네요. 전에 올렸던 사이트 오프라인 매장에 가서 머리를 했습니다. 지우 쌤이라는 분이 해주셨는데, 자신의 직업을 좋아하시는 분 같아서 참 보기 좋았습니다.

볶은 머리의 제 모습이 아직 제 눈에도 익숙치가 않아서 뭔가 거시기 합니다.

사용자 삽입 이미지

이거 올리고 있는데 전화가 왔네요;

사용자 삽입 이미지
어서 마무리하고 자야지..

ps: 내일 아침에 놀랄 우리 어머니... 넘 놀라지 마시길..
top


스프링 DM 레퍼런스 편역(not 번역) 완료

Spring DM/etc : 2008.06.22 00:32


파트 3 Other Resouces와 파트 4 Appendixes를 제외한 파트 1, 2, 3(1장부터 9장까지 편역을 드디어 완료했습니다. 얼마 되지도 않는데 정말 오래도 걸리네요. 어찌됐든 일독, 정독, 요약, 편역 했다는데 의미를 두고 링크를 정리해봅니다. 원하시는 분이 계시다면, PDF나 웹 페이지로 정리해서 배포할 생각도 있는데, 원하시나요?

1 장. Why Spring Dynamic Modules?
2 장. Requirements
3 장. What is new?
4 장. Bundles and Application Contexts
    4.1. The Spring Dynamic Modules Extender bundle
    4.2. Application Context Creation
    4.3. Bundle Lifecycle (2)
    4.4. The Resource abstraction
    4.5. Accessing the BundleContext
    4.6. Application Context Destruction
    4.7. Stopping the extender bundle
5 장. Packaging and Deploying Spring-based OSGi applications
    5.1. Bundle format and Manifest headers
    5.2. Extender configuration options
    5.3. Required Spring Framework and Spring Dynamic Modules Bundles
    5.4. Spring XML authoring support
    5.5. Importing and Exporting packages
    5.6. Considerations when using external libraries
    5.7. Diagnosing problems
6 장. The Service Registry
    6.1. Exporting a Spring bean as an OSGi service
    6.2. Defining references to OSGi services
    6.3. Exporter/Importer listener 베스트 프랙티스
    6.4. Service importer global defaults
    6.5. 서비스 Exporter와 서비스 Importer의 관계
7 장. 번들 다루기
8 장. Web Support
    8.1. 지원하는 웹 컨테이너
    8.2. Web support 사용법
    8.3. WAR classpath in OSGi
    8.4. web extender 설정하기
    8.5. Customizing the standard deployers
    8.6. OSGi-ready libraries and web development
    8.7. Spring-MVC Integration
9 장. Testing OSGi based Applications
    9.1. OSGi Mocks
    9.2. Integration Testing
top


9.2. Integration Testing

Spring DM/Chapter 9 : 2008.06.22 00:15


OSGi처럼 제한적인 환경에서는 여러분들이 작성한 클래스의 가시성과 버전관리, 번들이 다른 번들과 제대로 동작하는지를 확인하는 것이 중요하다.

통합 테스트를 편하게 하기위해, 스프링 DM 프로젝트는 테스트 클래스 계층구조를 제공한다(org.springframework.osgi.test.AbstractOsgiTests를 기반으로) . 이걸 사용해서 자동으로 OSGi 환경에서 실행되는 일반적인 JUnit 테스트 케이스를 작성할 수 있다.

보통 스프링 DM 프로젝트가 지원하는 시나리오는 다음과 같다:
  • OSGi 프레임워크 시작하기(Equinox, Knopflerfish, Felix)
  • 테스트에 필요하다고 기술된 번들 설치 및 시작
  • 테스트 케이스를 fly 번들 안으로 패키징하고, manifest 작성하고 OSGi 프레임워크에 해당 번들을 설치하기
  • OSGi 프레임워크 안에서 테스트 케이스 실행하기
  • 프레임워크 종료하기
  • 테스트 결과를 OSGi 밖에 있는 원래 테스트 케이스 객체에 전달하기

주의할 것
테스팅 프레임워크의 목적은 OSGi 통합 테스트를 OSGi 환경 밖에서 테스트 하는 것이다(Ant/Maven 같은 곳에서). 테스팅 프레임워크는 OSGi 번들로 사용하기 위해 만들어 둔 것이 아니다.

다음을 쭉 살펴보면 JUnit 기반 통합 테스트를 작성하는 것이 쉬워질 것이다.

본 챕터의 나머지는 스프링 DM 테스팅 스위트가 제공하는 기능들을 설명한다.

9.2.1. 간단한 OSGi 통합 테스트 작성하기

진단 프레임워크에는 특정 기능을 제공하는 여러 클래스들이 있는데, 여러분이 작성한 대부분의 클래스들은 org.springframework.osgi.test.AbstractConfigurablBundleCreatorTests를 상속하면 된다.

이 클래스를 확장하고 BundleContext 필드를 사용하여 OSGi 플랫폼을 사용해보자.

public class SimpleOsgiTest extends AbstractConfigurableBundleCreatorTests {

public void testOsgiPlatformStarts() throws Exception {
    System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VENDOR));
    System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_VERSION));
    System.out.println(bundleContext.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT));
    }
}

간단하게 JUnit 테스트를 실행하듯이 테스트를 실행하면 된다. Equinox 3.2.x 에서 실행하면 다음과 같은 결과를 얻을 수 있다

Eclipse
1.3.0
OSGi/Minimum-1.0,OSGi/Minimum-1.1,JRE-1.1,J2SE-1.2,J2SE-1.3,J2SE-1.4}

보시다시피, 테스팅 프레임워크는 테스트 실행에 필요한 번들들 필요한 번들들(스프링, 스프링 DM, slf4j ...)을 자동으로 설치해준다.

9.2.2. 테스트에 필요한 것들 설치하기

스프링 DM jar와 테스트 자체를 제외하면 몇몇 라이브러리나 통합 테스트 대상이 되는 코드에 대한 의존도가 높다.

아파치 커먼스 Lang에 의존하고 있는 다음의 테스트 코드를 살펴보자.

import org.apache.commons.lang.time.DateFormatUtils;
    ...
      public void testCommonsLangDateFormat() throws Exception {
        System.out.println(DateFormatUtils.format(new Date(), "HH:mm:ssZZ"));
    }
}

위 코드를 실행하면, 다음과 같은 예외가 발생할 것이다.

java.lang.IllegalStateException: Unable to dynamically start generated unit test bundle
     ...
Caused by: org.osgi.framework.BundleException: The bundle could not be resolved.
Reason: Missing Constraint: Import-Package: org.apache.commons.lang.time; version="0.0.0"
    ...
    ... 15 more

테스트는 org.apache.commons.lang.time 패키지를 필요로 하지만, 이걸 공개한 번들은 존재하지 않는다. 이 문제를 해결하기 위해 commons-lang 번들을 설치해본자.(2.4 이상의 버전을 설치해야 한다. 그래야 OSGi 라이브러리다.)

설치되어야 할 번들을 getTestBundlesNames 또는 getTestBundles를 사용해서 명시할 수 있다.

기본적으로 테스트 스위트는 로컬 maven2 저장소를 사용하여 구성물을 위치시킨다. 구성물 그룹 아이디, 이름, 버전을 콤마로 구분한 문자열로 나열한 것을 기본 locator가 읽어서 해당 구성물을 찾아서 설치한다. 커스텀 locator를 구현하여 설정할 수 있다. org.springframework.osgi.test.provisioning.ArtifactLocator 인터페이스를 구현한 다음 끼워 맞추면 된다.

통합 테스트를 다음과 같이 수정하여 필요한 번들을 설치하자.

protected String[] getTestBundlesNames() {
     return new String[] { "org.springframework.osgi, cglib-nodep.osgi, 2.1.3-SNAPSHOT",
         "org.springframework.osgi, jta.osgi, 1.1-SNAPSHOT",
         "commons-lang, commons-lang, 2.4" };
     };
}

테스트를 다시 실행하면 위의 번들들이 OSGi 플랫폼에 설치된다.

노트

위에서 언급한 구성물들이 여러분의 로컬 메이븐 저장소에 있어야 한다.

9.2.3. Advanced testing framework topics

테스팅 프레임워크는 커스터마이징을 많이 할 수 있다. 이 번 챕터에서 여러분에게 유용한 후킹을 소개하고자 한다. 하지만, 이런 팁들이 테스트 코드의 복잡도를 높일 수도 있다.

9.2.3.1. 테스트 manifest 커스터마이징

자동 생성된 manifest가 테스트에 적당하지 않을 수도 있다. 예를 들어 manifest에 몇몇 새로운 헤더나 필수가 아니라 부가적인 import가 필요할때가 있다.

간단한 경우, 자동 생성된 manifest를 조작할 수 있다. 아래의 예제에서 번들 클래스패스를 명시적으로 설정하고 있다.

protected Manifest getManifest() {
      // let the testing framework create/load the manifest
      Manifest mf = super.getManifest();
      // add Bundle-Classpath:
      mf.getMainAttributes().putValue(Constants.BUNDLE_CLASSPATH, ".,bundleclasspath/simple.jar");
      return mf;
}

또 다른 방법으로 여러분이 직접 작성한 manifest 파일을 getManifestLocation() 메소드에 설정할 수도 있다.

protected String getManifestLocation() {
      return "classpath:com/xyz/abc/test/MyTestTest.MF";
}

둘 모두 manifest에 다음과 같이 설정되어 있어야 한다.

“Bundle-Activator: org.springframework.osgi.test.JUnitTestActivator”

저렇게 설정되어 있지 않으면, 테스팅이 제대로 동작하지 않을 것이다. 또한 JUnit, Spring, Spring DM의 특정 패키지들을 import 해줘야 된다.

Import-Package: junit.framework,
  org.osgi.framework,
  org.apache.commons.logging,
  org.springframework.util,
  org.springframework.osgi.service,
  org.springframework.osgi.util,
  org.springframework.osgi.test,
  org.springframework.context

테스트 클래스가 사용할 패키지 import에 실패하면 테스트는 실패할 것이고 NoDefClassFoundError가 발생할 것이다.

9.2.3.2. 테스트 번들 컨텐츠 커스터마이징

기본적으로, 테스트 대상이 되는 번들을 테스트 할 때 테스팅 인프라는 ./target/test-classes 폴더 밑에 있는 모든 클래스, xml, 프로퍼티 파일들을 사용한다. 이건 메이븐 구조에 맞게 설계된거다. 이런 설정을 두 가지 방법으로 변경할 수 있다.
  • AbstractConfigrableBundleCreatorTests getXXX 메소드를 구현하는 프로그래밍을 하는 방법.
  • 테스트 케이스와 비슷한 이름을 가진 프로퍼티 파일을 작성하는 선언적인 방법. 예를 들어, com.xyz.MyTest 가 사용할 설정 프로퍼티 파일은 com/xyz/MyTest-bundle.properties 파일이어야 한다.
표 9.1. 기본 테스트 jar 컨텐츠 설정

생략

이 옵션은 특정 리소스를 필요로 하는 테스트를 작성할 때 유용하다. AbstractConfigurableBundleCreatorTests와 AbstractOnTheFlyBundleCreatorTests를 살펴보면 보다 많은 후킹 메소드를 찾을 수 있을 것이다

9.2.3.3. MANIFEST.MF 생성 이해하기

테스트 번들 컨텐츠를 기반으로 테스트 manifest를 자동 생성 해주는 테스팅 프레임워크의 유용한 기능 중 하나다. 바이트코드를 분석하여 필요로 하는 페키지들을 import 하는 manifest를 작성해준다. 생성된 번들은 테스트를 실행하기 위한 용도기 때문에, 다음과 같은 가정을 전제로 한다.
  • 아무런 패키지도 export하지 않는다.
  • 페키지를 나누는 기능(서로 다른 번들에서 같은 패키지에 클래스들을 제공하는 기능)을 지원하지 않는다. Split package는 OSGi 스펙 3.13에 따라서 권장하지 않는다.
  • 테스트 번들은 오직 테스트 클래스들만 가지고 있다. 기본 설정을 변경하려면, createManifestOnlyFromTestClass 가 true를 반환하도록 재정의하라.

protected boolean createManifestOnlyFromTestClass() {
    return true;
}

노트

번들에 담겨있는 클래스들의 수와 크기에 Manifest를 작성하는데 필요한 시간이 비례한다.

일반적인 OSGi 번들용 manifest를 작성하는 것이 목적이 아니라, 빠르고 간단하게 테스트를 위한 것을 만들기 위한 용도이다.

9.2.4. OSGi application context 만들기

스프링 DM 테스팅 스위트는 스프링 테스팅 클래스들을 기반으로 하고 있다. application context를 만들려면, getConfigLocation 메소드를 재정의하여 application context 설정파일 위치를 알려주면 된다. 실행시에, OSGi application context가 생성되고 테스트 케이스를 실행할 동안 캐쉬될 것이다.

protected String[] getConfigLocations() {
   return new String[] { "/com/xyz/abc/test/MyTestContext.xml" };
}

9.2.5. 사용할 OSGi 플랫폼 설정하기


테스팅 프레임워크는 3개의 OSGi 4.0 구현체, Equinox, Knopflefish, Felix를 지원한다. 이걸 사용하려면 테스트 클래스패스에 이들이 존재해야 한다. 기본적으로 테스팅 프레임워크는 Equinox를 사용한다. 이 설정을 바꾸는 방법은 두 가지다.
  • getPlatformName() 메소드를 사용하는 프로그래밍적인 방법.
Platforms 인터페이스 구현체의 이름을 설정하여 사용할 플랫폼을 알려준다.

protected String getPlatformName() {
   return Platforms.FELIX;
}
  • org.springframework.osgi.test.framework 시스템 속성을 사용한 선언적인 방법
만약 이 속성이 설정되면, 테스팅 프레임워크는 이 값을 플랫폼 구현체의 풀 네임 값으로 사용할 것이다. 만약 문제가 생기면, Equinox를 다시 사용할 꺼고 경고 메시지를 로깅한다. 이 옵션은 (Ant나 Maven같은) 빌드 툴에게 유용하다. 왜냐면 테스트 코드를 변경하지 않고도 특정 타켓 환경을 알려줄 수 있으니까.

9.2.6. 테스트 의존성 대기하기

테스팅 프레임워크에 내장된 기능 중 하나는 테스트를 실행할 때 필요한 의존성들이 설치 될 때까지 기다리는 것이다. OSGi 플랫폼의 동시성 때문에, 번들이 설치됐다고 해서 해당 번들이 제공하는 서비스가 동작중이라는 것을 보장할 수는 없다. 테스트가 필요로 하는 서비스가 완전히 가용하기 전에 테스트를 실행하는 건 테스트 결과를 더럽히는 일이다. 기본적으로 테스팅 프레임워크는 사용자가 설치한 번들을 모두 조사해서, 스프링을 사용한 번들일 경우 해당 번들이 완전히 시작될 때까지(시작 상태가 되면 서비스 설치된거니까..) 기다린다. 이 기본 행위를 shouldWaitForSpringBundlesContextCreation 메소드에서 변경할 수 있다. AbstractSynchronizedOsgiTests를 참조하라.

9.2.7. 테스팅 프레임워크 성능

테스팅 프레임워크가 제공하는 모든 기능을 고려했을 떄, 성능적인 측면에서 병목현상을 야기하지는 않을지 의심스러울 것이다. 먼저, 테스팅 프레임워크가 자동으로 해주는 모든 일들은 어떻게 해서든 해야만 하는 일들이다. 그 작업들을 손수하기에는 에러가 발생할 여지가 너무 많고 시간 소비도 만만치 않다.

현재의 인프라는 거의 반년간 사용해 왔다. 통합 테스트(120개 정도)를 실행하는데 노트북에서 3분 30초 가량 걸린다. 대부분의 시간은 OSGi 플랫폼을 시작하고 끄는데 소비된다. "테스팅 프레임워크"는 오직 10%가량의 시간만 소비한다.

하지만 우린 필요한 설정을 보다 최소화하고, 보다 더 빠르고 똑똑하게 만들려고 한다. 좋은 아이디어가 있으면 이슈트래커나 포럼을 통해서 언제든지 제안해달라. 

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

9.2. Integration Testing  (0) 2008.06.22
9.1. OSGi Mocks  (0) 2008.06.17
Chapter 9. Testing OSGi based Applications  (0) 2008.06.17
top