5. Spring DM을 사용하여 서비스 사용하기.

1. StoreManager 번들 정리하기.

– Activator를 없애버립니다.
– ServiceTracker도 없애버립니다.

둘다 일단 MENIFEST.MF의 Dependencies에서 제거하고 소스코드도 제거합니다.
이 번들이 필요한 건 오직 Store 번들의 Service 패키지에 있는 Greeting이라는 인터페이스 뿐입니다.

StoreManager의 MENIFEST.MF 파일이 다음과 같으면 깨끗하게 정리가 된 것입니다.

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: StoreManager Plug-in
Bundle-SymbolicName: StoreManager
Bundle-Version: 1.0.0
Import-Package: service
Eclipse-LazyStart: true

2. 구현하기

Keesun이라는 클래스를 하나 만들고 다음과 같이 구현했습니다.

public class Keesun {

    private Greeting greeting;

    public void setGreeting(Greeting greeting) {
        this.greeting = greeting;
    }

    public void start(){
        System.out.println(greeting.hi(“기선”));
    }
}

Setter Injection을 사용하기로 했고, start() 메소드는 제대로 세팅됐나 확인하기 위해 만들어 뒀습니다.

3. Bean 설정하기

META-INF 폴더에 spring 폴더를 만들고 스프링 설정 파일 하나를 만듭니다.

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

    <bean class=”storemanager.Keesun” init-method=”start”>
        <property name=”greeting” ref=”greeting” />
    </bean>

    <osgi:reference id=”greeting” interface=”service.Greeting” />

</beans>

Keesun 클래스에 start라는 init-method를 등록해두고, <osgi:reference /> 엘리먼트로 서비스를 참조합니다. 그러면 이 내부에서는 마치 자기가 원래 가지고 있던 bean 처럼 사용할 수 있습니다.

4. 테스트

사용자 삽입 이미지
Run Dialog에서 Spring OSGi만 체크하고 Run 시킵니다. 나머지는 install을 사용해서 설치합니다.

osgi> install file:c:/plugins/Store_1.0.0.jar
Bundle id is 22

osgi> install file:c:/plugins/StoreManager_1.0.0.jar
Bundle id is 23

osgi> ss

Framework is launched.

id    State       Bundle
0    ACTIVE      system.bundle_3.2.2.R32x_v20070118
1    ACTIVE      org.springframework.osgi.log4j.osgi_1.2.15.SNAPSHOT
2    ACTIVE      org.springframework.bundle.spring.context.support_2.5.1
3    ACTIVE      org.springframework.bundle.osgi.core_1.0.0
4    ACTIVE      org.springframework.osgi.aopalliance.osgi_1.0.0.SNAPSHOT
5    ACTIVE      org.springframework.bundle.osgi.extender_1.0.0
6    ACTIVE      org.springframework.bundle.spring.context_2.5.1
7    ACTIVE      org.springframework.osgi.cglib-nodep.osgi_2.1.3.SNAPSHOT
8    ACTIVE      org.springframework.bundle.osgi.extensions.annotations_1.0.0
9    ACTIVE      org.springframework.osgi.junit.osgi_3.8.2.SNAPSHOT
10    INSTALLED   org.springframework.bundle.osgi.test_1.0.0
11    ACTIVE      org.springframework.bundle.osgi.io_1.0.0
12    ACTIVE      org.springframework.osgi.asm.osgi_2.2.3.SNAPSHOT
13    ACTIVE      jcl104.over.slf4j_1.4.3
14    ACTIVE      org.springframework.spring.source_2.5.1
15    ACTIVE      org.springframework.bundle.spring.core_2.5.1
16    ACTIVE      org.springframework.osgi.source_1.0.0
17    ACTIVE      slf4j.log4j12_1.4.3
18    ACTIVE      org.springframework.osgi.backport-util-concurrent.osgi_3.1.0.SNAPSHOT
19    ACTIVE      org.springframework.bundle.spring.beans_2.5.1
20    ACTIVE      slf4j.api_1.4.3
21    ACTIVE      org.springframework.bundle.spring.aop_2.5.1
22    INSTALLED   Store_1.0.0
23    INSTALLED   StoreManager_1.0.0

osgi> start 22

osgi> GreetingImpl Bean을 만들었습니다.
start 23

osgi> hi 기선

끝~ 이 아니고 이제부터 시작입니다.
설특집은 끝입니다.

4. Spring DM을 사용하여 서비스 노출하기.

1. Spring IDE 설치

http://www.springide.com/updatesite_nightly 를 이용해서 가장 최신의 Spring IDE 플러그인을 받을 겁니다. 그런데 처음 부터 저를 따라하셨으면, Eclipse를 새로 설치하셨을텐데, 그러면 Web Tools Plugin도 설치되어 있지 않아서, Spring IDE 플러그인을 설치하려고 하면, 종속성 문제 때문에 에러가 납니다.

그럴 때는 Eclispe Discovery Site도 같이 업데이트에서 선택한 다음에, Web 폴더를 왕창 선택해 줍니다.  스샷을 찍었어야 하는데, 깜빡하고 지나가서.. pass 합니다.

2. 필요한 번들 추가.

Target Platform 하단의 Pre Defined Target Plattform에서 Spring OSGi를 선택합니다. 그러면 끝입니다.

사용자 삽입 이미지
Spring IDE에서 제공해주는 기능입니다. 저걸 선택하면, 알아서 Spring OSGi를 사용할 때 필요한 번들들을 추가해 줍니다.

id    State       Bundle
0    ACTIVE      system.bundle_3.2.2.R32x_v20070118
1    ACTIVE      org.springframework.osgi.log4j.osgi_1.2.15.SNAPSHOT
2    ACTIVE      org.springframework.bundle.spring.core_2.5.1
3    ACTIVE      org.springframework.osgi.aopalliance.osgi_1.0.0.SNAPSHOT
4    ACTIVE      slf4j.api_1.4.3
5    ACTIVE      org.springframework.osgi.junit.osgi_3.8.2.SNAPSHOT
6    ACTIVE      org.springframework.osgi.source_1.0.0
7    ACTIVE      org.springframework.osgi.backport-util-concurrent.osgi_3.1.0.SNAPSHOT
8    ACTIVE      org.springframework.spring.source_2.5.1
9    INSTALLED   org.springframework.bundle.osgi.test_1.0.0
10    ACTIVE      org.springframework.bundle.spring.context_2.5.1
11    ACTIVE      org.springframework.bundle.osgi.io_1.0.0
12    ACTIVE      jcl104.over.slf4j_1.4.3
13    ACTIVE      org.springframework.bundle.osgi.extensions.annotations_1.0.0
14    ACTIVE      org.springframework.osgi.asm.osgi_2.2.3.SNAPSHOT
15    ACTIVE      org.springframework.bundle.spring.beans_2.5.1
16    ACTIVE      org.springframework.bundle.osgi.core_1.0.0
17    ACTIVE      org.springframework.osgi.cglib-nodep.osgi_2.1.3.SNAPSHOT
18    ACTIVE      org.springframework.bundle.osgi.extender_1.0.0
19    ACTIVE      slf4j.log4j12_1.4.3
20    ACTIVE      org.springframework.bundle.spring.aop_2.5.1
21    ACTIVE      org.springframework.bundle.spring.context.support_2.5.1

osgi.test 번들이 가동이 안 됐는데 뭔가 필요한게 없나 봅니다.

osgi> diag 9
initial@reference:file:plugins/spring-osgi-test-1.0.jar/ [9]
  Missing imported package org.apache.felix.framework_0.0.0.
  Missing imported package org.apache.felix.main_0.0.0.
  Missing imported package org.knopflerfish.framework_0.0.0.
  Missing imported package org.springframework.test_2.5.0.

확인해보니, 테스트 용도라서, 그런 것 같네요. 배포할 때 테스트 번들까지 추가할 필요가 없어서 그런가 봅니다.

암튼 패스하고 계속 진행하겠습니다.

3. 서비스 노출시키기

이전에 서비스를 노출할 때는, context.registerService() 라는 메소드를 사용했었습니다. 그런데 이제는 스프링 설정 파일에 bean으로 등록하면 됩니다.

먼저, MANIFEST.MF 파일을 수정합니다. overview탭에서 Activator를 지웁니다.(소스코드에도 Activator를 지워버립니다.)
사용자 삽입 이미지Activator 클래스는 아예 지워버립니다.

그리고 META-INF 폴더 밑에 spring 폴더를 만들고 springOSGi.xml 이라는 이름으로 파일을 만들어 줍니다. 꼭 이 이름일 필요는 없습니다. spring 폴더 밑에 있는 xml 파일을 전부 읽어 들일테니까요.

그리고 다음과 같이 XML을 작성합니다.

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

    <bean id=”greeting” class=”service.impl.GreetingImpl” init-method=”start” />
   
    <osgi:service interface=”service.Greeting” ref=”greeting” />
   
</beans>

bean이 만들어졌는지 확인하기 위해서, init-method 속성을 사용했습니다. GreetingImpl에는 start 메소드 하나를 추가해줍니다.

public class GreetingImpl implements Greeting {

    public String hi(String name) {
        return “hi ” + name;
    }
   
    public void start(){
        System.out.println(“GreetingImpl Bean을 만들었습니다.”);
    }

}

그리고 이 번들을 플랫폼에 올리면 다음과 같이 applicationContext가 만들어 진 것을 확인할 수 있습니다.

osgi> log4j:WARN No appenders could be found for logger (org.springframework.util.ClassUtils).
log4j:WARN Please initialize the log4j system properly.
GreetingImpl Bean을 만들었습니다.
ss

Framework is launched.

id    State       Bundle
0    ACTIVE      system.bundle_3.2.2.R32x_v20070118
1    ACTIVE      org.springframework.osgi.log4j.osgi_1.2.15.SNAPSHOT
2    ACTIVE      org.springframework.bundle.spring.context.support_2.5.1
3    ACTIVE      org.springframework.bundle.osgi.core_1.0.0
4    ACTIVE      org.springframework.osgi.aopalliance.osgi_1.0.0.SNAPSHOT
5    ACTIVE      org.springframework.bundle.osgi.extender_1.0.0
6    ACTIVE      org.springframework.bundle.spring.context_2.5.1
7    ACTIVE      org.springframework.osgi.cglib-nodep.osgi_2.1.3.SNAPSHOT
8    ACTIVE      org.springframework.bundle.osgi.extensions.annotations_1.0.0
9    ACTIVE      org.springframework.osgi.junit.osgi_3.8.2.SNAPSHOT
10    INSTALLED   org.springframework.bundle.osgi.test_1.0.0
11    ACTIVE      org.springframework.bundle.osgi.io_1.0.0
12    ACTIVE      org.springframework.osgi.asm.osgi_2.2.3.SNAPSHOT
13    ACTIVE      jcl104.over.slf4j_1.4.3
14    ACTIVE      org.springframework.spring.source_2.5.1
15    ACTIVE      org.springframework.bundle.spring.core_2.5.1
16    ACTIVE      org.springframework.osgi.source_1.0.0
17    ACTIVE      slf4j.log4j12_1.4.3
19    ACTIVE      org.springframework.osgi.backport-util-concurrent.osgi_3.1.0.SNAPSHOT
20    ACTIVE      org.springframework.bundle.spring.beans_2.5.1
21    ACTIVE      slf4j.api_1.4.3
22    ACTIVE      org.springframework.bundle.spring.aop_2.5.1
23    ACTIVE      Store_1.0.0

osgi>

끝! 그냥 서비스로 제공할 클래스를 bean으로 등록한 다음에 <osgi:service/> 엘리먼트의 interface와 ref 속성으로 해당 bean을 서비스로 등록해둡니다.

OSGi at The Spring Experience 정리1

작년 Spring Experience에서 아드리안이 발표했던 OSGI에 관한 발표 영상이 조금 전에 올라왔습니다. 다음 한국 스프링 사용자 모임 세미나의 주제이기도 하니까… 미리 봐두면 좋겠다 싶어서. 예습 삼아 동영상을 보며 정리해보았습니다. 물론 영어라 많이 놓칩니다.

발표 순서는 다음과 같습니다.
1. OSGi란 무엇인가?
2. 어떤 도움을 주는가?
3. 어떻게 동작하는가?
4. Spring이 들어맞는 곳은 어디?
5. Spring-OSGi

1. OSGi란 무엇인가?
Open Services Gateway Initiative
자바를 위한 다이나믹 모듈 시스템

모듈 시스템?
시스템을 여러 모듈(번들)로 나눠 놓은 것
매우 엄격한 경계선(visibility role)
Resolution process(모듈 간의 종속성 해결)
Understand 버전잉

다이나믹?
런타임 시에 모듈들이 설치되고, 시작, 멈춤, 재설치, 수정이 가능하다.

그리고 서비스 지향적이기까지 하다.

2. 무엇이 어떤 도움을 주는가?(어떤 문제 해결에 도움이 되는가?)

무엇이?
Visibility
Versioning
Operatinal Control

Visivility
모듈들은 기본적으로 완전 블랙 박스다.
리플렉션이건 클래스로딩 트리커리건 안 통한다.
만약 다른 번들들에게 타입을 공개(expose)하고 싶다면 명시적으로 해야 한다.(버전과 함께)
번들은 하나 이상의 패키지를 공개(export) 할 수 있다.
오직 공개된(exported) 패키지들만 밖에서 참조할 수 있다.
– 개발 주기가 빨라지고,
– 독립적인 개발이 가능해 진다.
– 의도하지 않은 종속성이 생기지 않으며,
– 보안이 좋다.
사용자 삽입 이미지
Versioning
같은 타입의 모듈이 여러 개 있고, 그 중에 최신 버전으로 교체하고 싶다면, OSGI에서 런타임 때 이전 버전의 모듈을 새 버전의 모듈로 교체할 수 있다.

Operatinal Control
모든 모듈과 그들의 상태를 볼 수 있다.(JMX, OSGI 콘솔)
wiring에 관한 정보를 참조 할 수 있다.
새로운 번들 추가.
번들 활성화(서비스 퍼블리싱)
번들 비활성화(서비스 등록해지)
번들 리프래쉬
번들 멈추기
번들 제거하기.
– 이 모든 것들을 애플리케이션을 멈추거나 재시작 하는 일 없이 할 수 있다.

3. 어떻게 동작하는가?
번들 만들기
– 그냥 JAR 파일 만드는 거다.
사용자 삽입 이미지– 복잡한 툴이나 패키징은 필요 없다.
– Maven OSGI 플러그인
– 이클립스의 지원
    -이클립스에서 플러그인 만드는 것이 OSGI 번들 만다는 것이다.
    -Menifest 편집기

패키지 공개하기(Export-Package)
-Menifest  파일에 Export-Package 헤더를 사용하여 나타낸다.
-인터페이스와 구현체를 페키지로 분류해둬라.(어찌됐든, 이것이 베스트 프랙티스다!!)
-예) Export-Package: org.foo.service, org.bar.service
– 버전 넘버와 함께 공개하기
사용자 삽입 이미지
필요한 패키지 불러오기(Import-Package)
-역시 Import-Package 헤더 사용
-가장 최신 버전의 번들과 엮이게 된다.
-버전 제약 사항 기술하기
사용자 삽입 이미지
클래스로딩
– 플로우차트가 잘 안 보임. 발표 자료 구하고 싶어짐;

Resolutioning
– import와 Export 매칭 시키기
– 복잡한 알고리즘
– 가능한 최상위 버전으로 와이어링 함.

번들의 라이프사이클
사용자 삽입 이미지
BundleActivator

Service Registry
– 인터페이스를 기반으로 ServiceRegistry에 서비스를 공개할 수 있다.
– 번들들은 레지스트리에 등록된 서비스를 찾거나 엮을 수 있다.
– 런타임시에 서비스를 등록하거나 제거 할 수 있다.

JSR 277
– 자바 모듈 시스템
– OSGI의 RequireBundle과 비슷한 매커니즘이 있다.

JSR 291
– 자바 SE에서의 다이나믹 컴포넌트 서포트

======================================================================================
여기서 잠깐 자야겠습니다.
1시간 25분 19초 짜리 동영상인데 현재 45분 41초 까지 보면서 요약을 했습니다.
이 다음 부터는 본격적으로 Spring에 대한 내용으로 이어집니다.
4. Spring이 들어맞는 곳은 어디?
5. Spring-OSGi
두 개는 내일..