본 내용은 실전 OSGi&SpringDM(위키북스) 책의 일부 내용입니다.
OSGi 서비스 사용
1. 서비스 구현을 위한 3요소 (chapter 4-p69)
SGi 서비스 등록을 위해서는 해당 서비스 객체의 인터페이스, 인터페이스 구현체, 서비스 속성 Dictionary가 필요하다. 그리고 기본적으로 모든 구현 번들 Manifest.mf의 Import-Package에는 인터페이스 패키지(믿의 예에선 SearchEngine 인터페이스)를 추가해 주어야하며 인터페이스 패키지는 Manifest.mf에 Export-Package되어야 한다.
1-1. 서비스 3요소
1-1-1. 인터페이스
public interface SearchEngine {
List<String> search(String query);
List<String> searchImage(String query);
}
1-1-2. 구현체
public Google implements SearchEngine {
List<String> search(String query) {
...
}
List<String> searchImage(String query) {
...
}
}
public Naver implements SearchEngine {
List<String> search(String query) {
...
}
List<String> searchImage(String query) {
...
}
}
1-1-3. 서비스 속성
Dictionary props = new Properties();
props.put(org.osgi.framework.constants.SERVICE_VENDOR, "Google");
props.put("searchable", "Text,Image");
//서비스를 등록할 때 개발자가 지정할 수 있는 랭킹 값으로, 만약 같은 인터페이스에 대해
//여러 개의 서비스 구현체가 있다면 이 랭킹값이 큰 순으로 우선순위를 가진다.
//기본값은 0이다. 만약 랭킹값이 같다면 id값이 작은 것이 더 높은 우선순위를 가진다.
props.put(org.osgi.framework.Constants.SERVICE_RANKING, 5);
2. 서비스 구현
2-1. 서비스 등록 구현
public class Activator implements BundleActivator {
//인터페이스
private SearchEngine service;
//서비스에 대한 접근자인 ServiceReference를 읽어오거나, Service의 등록을 해지할 때 사용
//즉, 서비스 등록은 Bundlecontext.registerService가 하지만 서비스 해지는 ServiceRegistratio 을 통해서만 가능
private ServiceRegistration registration;
public class Activator implements BundleActivator {
//서비스 속성
Dictionary props = new Properties();
props.put(org.osgi.framework.Constants.SERVICE_VENDOR, "Google");
props.put("searchable", "Text,Image");
props.put(org.osgi.framework.Constants.SERVICE_RANKING, 5);
//인터페이스 구현체
service = new Google();
//서비스 등록
//context.registerService(인터페이스,구현체,서비스속성)
registration = context.registerService(SearchEnglish.class.getName(), service, props);
//여러게 서비스 등록
//bundlecontext.registerService(String[] clazzes, Object service, Dictionary properties);
}
public void stop(BundleContext context) throws Exception {
//서비스 해지(꼭하지 않아도 됨)
registration.unregister();
}
}
2-2. 서비스 실행
2-2-1. 서비스 정보를 가져오는 ServiceReference 인터페이스
//BundleContext.getServiceReference(String interfaceName);
//BundleContext.getService(ServiceReference refenece);
//BundleContext.getServiceReference에서 서비스레퍼런스 정보를 객체로 가져와
//이 객체를 통해 BundleContext.getServiceReference함수로 서비스를 가져올 수 있다.
public interface ServiceReference extends Comparable {
//속성 값을 읽어 온다.
public Object getProperty(String key);
//속성의 키 값을 배열로 읽어온다.
public Stiring[] getPropertyKeys();
//이 서비스를 등록한 번들 객체를 리턴한다. 만약 서비스가 unregister 되었다면
//null을 리턴한다.
public Bundle getBundle();
//이 서비스를 사용하는 번들의 배열을 리턴
public Bundle[] getUsingBundles();
}
2-2-2. 서비스 실행 구현
public class ClientActivator implements BundleActivator{
ServiceReference reference;
SearchEngine engine;
public void start(BundleContext context) throws Exception {
//ServiceReference객체를 가져옴
reference = context.getServiceReference(SearchEngine.class.getName());
//ServiceReference객체를 통해 서비스를 가져옴
engine = (SearchEngine) context.getService(reference);
//검색엔진을 사용하여 검색기능 호출
List result = engine.search("query string");
}
public void stop(BundleContext context) throws Exception{
context.ungetService(reference);
engine = null;
}
}
2-3. 서비스 검색
2-3-1. SerivceTracker
2-2-2와 같이 서비스를 가져오면 OSGi 동적 환경에서 서비스가 언제 존재 할지 모르기 때문에 서비스를 기다려야 한다. 이런 서비스를 찾고 기다리기 위해 ServiceTracker가 필요하다.
2-3-1-1. ServiceTracker 메서드
//세 개의 생성자를 가지고 있음 ServiceTrackerCustomizer는 추적하는 방식을 개발자가
//원하는데로 변경(자세한 설명 책에 없음)
ServiceTracker(BundleContext, ServiceReference, ServiceTrackerCustomizer)
ServiceTracker(BundleContext, String, ServiceTrackerCustomizer)
ServiceTracker(BundleContext, Filter, ServiceTrackerCustomizer)
//ServiceTracker 사용전 open() 서비스 사용 끝난 후 close()
open(), close()
//서비스 리턴 getService()는 랭크값이 크고 ID가 가장 작은 서비스, getServices()는 해당
//모든 서비스 리턴
getService(), getServices()
//해당 ServiceReference또는 그 배열 리턴
getServiceReference(), getServiceReferences()
//timeout시간동안 서비스 검색 후 서비스 반환, 0일경우 무한 루프(데드락이 걸릴수있음 스레드 사용 권장)
waitForService(timeout)
2-3-2. ServiceTracker 구현
public void run() {
//context는 스레드 인자값으로 값음, ServiceTrackerCustomizer는 null
ServiceTracker tracker = new ServiceTracker(context, SearchEngine.class.getName(), null);
track.open();
SearchEngine engine;
try {
//파라미터 0은 무한 검색
engine = (SearchEngine) tracker.waitForService(0);
//서비스 실행
List results = engine.search("query string");
...
} catch (InterruptedException e) {
e.printStackTrace();
}
tracker.close();
}
3. OSGi Service를 구현한 jar파일
Maven을 사용한다면 dependency를 추가 하거나 아니며 OSGi Service를 구현 jar파일이 필요
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<version>3.1.200.v20071203</version>
</dependency>