Equinox 을 이용해서 OSGi 번들을 만들고 실행해보는 방법을 이해하고, Equinix 의 사용현황을 알아본다.
Equinox 개요
Equinix 는 Eclipse 재단에서 만들고 있는 OSGi Core Framework 및 기타 부속물의 구현물이다. Eclipse 재단은 Eclipse 3.0 버전부터 Eclipse 의 내부 프레임워크로 OSGi 를 채택했으며, OSGi 구현을 위한 프로젝트가 Equinix 이다.
현재 Equinix 는 별개의 프로젝트가 아니라 Eclipse RCP 와 IDE 플랫폼 개발 프로젝트로 흡수되었다.
Equinix 는 OSGi 가 (웹애플리케이션으로서의) Server Side 에서 주목받게 됨에 따라 Eclipse 플랫폼으로서가 아니라 Server Side 의 독자적인 플랫폼으로서의 가능성에 주목받고 있다. Equinox 를 Server Side 에서 쓰기 위한 작업도 진행되고 있다.
Eclipse 재단은 EPL (Eclipse Public License) v1.0 라이선스을 사용하는데, 이 라이선스에 의하면 상업적인 목적으로 소스 및 오브젝트 파일들을 쓰는 것은 허용되나 이로 인해 발생되는 모든 책임을 질 것과 EPL v1.0 라이선스 파일을 제품에 포함시킬 것을 요구하고 있다.
Equinox 사용하기
Equinox 는 Eclipse 플랫폼의 기반 Framework 이지만, Eclipse 와 관계없이 Equinox 만을 쓰는 것도 가능하다.
Eclipse 설치본에서 다음 파일을 사용하면 osgi> 로 표기되는 Equinox 런타임의 콘솔을 볼 수 있다.
다음은 org.eclipse.osgi_3.3.0.v20070530.jar 파일을 써서 콘솔을 띄운 모습이다.
Equinox 에서 실행할 Bundle 은 jar 파일 형태를 가지며, jar 파일내에는 org.osgi.framework.BundleActivator 인터페이스를 구현한 Activator 클래스가 포함되어 있어야 하고, MANIFEST.MF 파일에는 Bundle 이 구동되기 위한 정보가 담겨 있어야 한다.
이런 Bundle 을 만드는 데에는 Eclipse 를 이용하면 편리하다. 이에 앞서 Bundle 의 구조를 간단하게 살펴보기 위해 Console 에서 직접 만드는 예를 먼저 살펴본다.
Console 에서 Equinox 용 Bundle 작성 및 실행
Bundle 소스코드 작성과 컴파일하기
Console에서 텍스트 편집기로 직접 작성해서 빌드하고 실행하는 예이다.
먼저, org.eclipse.osgi_3.3.0.v20070530.jar 파일이 있는 디렉토리로 이동한다.
public class MyFirstBundle implements BundleActivator { public void start(BundleContext bc) { System.out.println("생애 첫 번들 시작~ 2번째~"); }
public void stop(BundleContext bc) { System.out.println("생애 첫 번들 끝~ 2번째~"); } }
stop() 메소드가 호출되는 것은 이전 소스코드 내용이고, 다시 한 번 update 1 을 실행하면 수정된 소스코드 내용이 실행된 것을 알 수 있다.
다음 그림은 다시 한 번 update 1 을 실행한 모습이다.
Eclipse 에서 Equinox 용 Bundle 작성 및 실행
Eclipse에서 Bundle 을 작성해서 빌드하고 실행하는 예이다.
Project Wizard 를 이용한 Bundle Project 만들기
Eclipse에는 명시적으로 OGSi Bundle 을 만들 수 있는 Project Wizard 가 없는 것처럼 보인다. 하지만, Eclipse Plug-in 이 사실 OSGi Bundle 이기 때문에 Eclipse Plug-in Project Wizard 를 이용하면 Eclipse 에서 OSGi Bundle 을 만들 수 있다.
다음 그림처럼 Plug-in Project Project Wizard 를 선택해서 예제 Project 를 선택한다.
이제 Project name 을 입력하고, Target Platform 으로 OSGi 를 선택한다. OSGi framework 으로는 standard 와 Equinox 를 선택할 수 있는데, 여기에서는 Equinox 를 선택한다.
그 다음 화면에서 Finish 버튼을 누르지 말고, Next 버튼을 눌러야 예제 소스코드를 선택할 수 있다.
Hello OSGi Bundle 예제를 선택하고 Finish 버튼을 누르면 다음 화면과 같이 예제 Project 를 볼 수 있다.
이 화면에서는 MANIFEST.MF 파일의 내용을 바로 수정하거나 OSGi framework 런타임을 기동/기동시키는 등의 조작이 가능하다.
이제, 왼쪽 Package Explorer 에서 mindwing_bundle.Activator.java 파일을 연다.
이 상태에서 다음 그림과 같이 실행환경을 만든다.
Target Platform 은 다음과 같이 하나만 선택하도록 한다.
이제 Run 버튼을 누르면 다음 그림과 같이 Equinox 의 Console 이 뜨면서 Bundle 이 실행되는 것을 볼 수 있다. (ss 명령으로 현재 실행중인 Bundle 의 상태도 조회하였다.)
Bundle 이 실행된 상태에서 소스코드를 수정하면 Eclipse 에서 알아서 빌드 후 Bundle jar 파일까지 만들어준다. 소스코드를 수정한 다음 Bundle 의 ID 인 1 번으로 update 를 하면 별도로 컴파일을 하고 Bundle jar 파일을 만드는 과정이 없이 바로 결과를 확인할 수 있는 것을 볼 수 있다.
Bundle 간 메소드 호출하기
Bundle 은 package 단위별로 외부에 자신을 노출시킬 수 있다.
노출시킬 package 와 pacage 의 버전등에 관한 정보는 모두 MANIFEST.MF 파일에 기재되어야 하는데, Eclipse 에서는 MANIFEST.MF 파일을 수정하기 위한 다양한 view 를 제공한다.
Package 노출하기
A Bundle 과 B Bundle 이 있을 때, B Bundle 이 노출시킨 package 를 A Bundle 이 사용하는 예이다.
다음과 같이 A 와 B 라는 이름으로 2개의 Bundle 프로젝트를 만든 상태에서 설명을 시작한다.
B Bundle 에는 b_export 패키지가 있는데, MANIFEST.MF 파일에 패키지 이름을 써주면 된다. Eclipse 에서 B Bundle 의 MANIFEST.MF 파일을 더블클릭하면 다양한 view 로 편집할 수 있는 편집기를 볼 수 있다.
다음 그림과 같이 아래에 있는 탭에서 Runtime 을 선택한다.
Export Packages 부분에 있는 Add... 버튼을 눌러서 다음 화면을 띄우고, b_export 패키지를 선택한다.
그러면, 다음과 같이 b_export 가 export 되고 있다는 것을 알 수 있다.
여기에서 Properties... 버튼을 눌러서 다음 그림과 같이 버전을 1.0.0 으로 기입한다. (기입하지 않았을 때의 기본값은 1.0.0 이다. 최대 4자리까지 숫자를 입력할 수 있다.)
이제, 아래 탭에 있는 MANIFEST.MF 를 눌러서 실제 파일에는 어떻게 기재되어 있는지 살펴본다.
이제 이 파일을 저자한 다음에 다음 그림과 같이 export 된 package 를 이용할 A Bundle 의 MANIFEST.MF 를 더블클릭해서 열고, Dependency 탭을 누른 다음 Imported Packages 의 Add... 버튼을 누르고. b_export 을 선택한다.
다음 그림과 같이 MANIFEST.MF 파일에서 수정내용을 확인할 수 있다.
실행결과를 보기전에 관련 소스코드를 살펴보면, B Bundle 의 노출된 패키지에 속한 클래스인 b_export.B_Export 클래스는 다음과 같다.
package b_export;
public class B_Export { public void b_export() { System.out.println(" === B번들의 b_export() 메소드 호출됨."); } }
이 클래스를 사용하기 위한 A Bundle 에서 a.Activator 클래스와 a.A_Import 클래스는 각각 다음과 같으며, 클래스를 바로 사용할 수 있는 것을 알 수 있다.
이제 Equinox 를 기동하면 다음과 같은 화면과 같이, dependency 가 걸려있는 Bundle B 가 먼저 start 되고, 그 다음에 Bundle A 가 start 되고, Bundle A 에서 Bundle B 의 b_export() 메소드가 호출되는 것을 볼 수 있다.
Service 등록과 사용하기
Eclipse에서 Service 를 작성해서 다른 Bundle 에서 이를 이용하는 예이다.
Service 는 어떤 Bundle 이 다른 Bundle 에게 자신을 노출할 수 있는 또 하나의 방법이다. Bundle 의 Package 노출은 Package 이름이나 Class 이름을 원치 않는 상황에서도 노출해야만 하며, 노출된 Class 가 정확히 노출된 목적에만 맞게 만들어진 것이 아닐 수도 있다.
이에 비해 Service 를 이용하면 잘 알려진 Interface 를 이용해서 구현 및 탐색이 이루어지기 때문에, Bundle 상호간 정확한 목적하에 상호작용이 이루어질 수 있으며, Service 구현체는 해당 Interface 의 뒤에 가려져있기 때문에 상황에 따라 런타임에 구현체만 바꾸는 것도 가능하다.
Service 는 일반적인 Java 인스턴스면 모두 Service Registry 에 등록이 가능하며, 명시적으로 BundleContext 에서 unregister 하거나 Service 를 제공한 Bundle 이 stop 되면 자동으로 Service Registry 에서 제거된다.
Service 를 만들고 등록하고 사용하기
앞서 설명한 Bundle 만드는 방식대로 S1 Bundle 을 만들고, 다음 소스코드를 참고해서 인터페이스인 hello.HelloService 클래스와 구현체인 hello.impl.HelloService 클래스를 만든다. 그리고, 이를 Service Registry 에 등록하기 위한 코드도 Activator 클래스에 추가한다.
package hello;
public interface HelloService { public void sayHello(); }
package hello.impl;
import hello.HelloService;
public class HelloServiceImpl implements HelloService { public void sayHello() { System.out.println(" === S1서비스의 sayHello() 메소드 호출됨."); } }