2012-03-28 3 views
5

Eclipse RCP에서 응용 프로그램을 개발 중입니다. 서비스 설계와 관련된 설계 결정에 도움이 필요합니다.OSGi 서비스 아키텍처 : 소비자의 요청에 따라 서비스 생성

다른 모듈에 REngine 개체를 제공하는 데 사용되는 번들이 있습니다. REngine은 여러 가지 방법으로 구현 될 수있는 계산 엔진에 대한 인터페이스입니다. 번들은 원격 서버에 연결하거나 로컬 계산 스레드를 시작하여 REngine 인스턴스를 제공합니다. 일부 번들은 GUI로 구성해야합니다 (헤드리스 플랫폼에서도 사용할 수 있어야합니다). 클라이언트 번들은 병렬 계산을 위해 복수 REngine 개체를 요청할 수 있습니다.

나는 현재 REngine 서비스를 제공하기 위해이 모듈들을 등록하고 있습니다. 서비스는 로컬 계산 인스턴스 또는 원격 (서버) 인스턴스를 시작하는 ServiceFactory에 의해 작성됩니다. 클라이언트는 REngine 클래스의 모든 서비스 등록을 시도하고 올바른 서비스 등록을 선택해야합니다.

class API.REngine { ... } 

class REngineProvider.Activator { 
    public void start(BundleContext ctx) { 
     ctx.registerService(REngine.class.getName(), new REngineFactory(), null); 
    } 
} 
class REngineProvider.REngineFactory implements ServiceFactory { 
    public Object getService(Bundle bundle, ServiceReference reference) { 
     return new MyREngineImplementation(); 
    } 
    public void ungetService(REngine service) { 
     service.releaseAssociatedResources(); 
    } 
} 

class RConsumer.Class { 
    REngine getREngine() { 
     ServiceReference[] references = bundleContext.getAllServiceReferences(REngine.class.getName(), null); 
     for(ServiceReference ref: references) { 
      try { 
      return bundleContext.getService(ref); 
      } catch (Exception e) {} // too bad, try the next one 
     } 
    } 
} 

나는이 모델을 유지하고자 다음과 같이

이 작업을 수행하는 코드

요약 될 수있다. OSGi 서비스 스펙은 REngine 오브젝트가 더 이상 필요하지 않을 때 해제해야하는 살아있는 오브젝트라는 내 비즈니스 요구 사항과 일치합니다.

그러나 등록 된 서비스는 번들 당 하나의 서비스 인스턴스 만 제공 할 수 있습니다. 두 x 째 서비스가 요청되면 캐시 된 인스턴스가 리턴됩니다 (새 인스턴스를 작성하는 대신). 이것은 내 요구 사항과 일치하지 않습니다. 번들은 동일한 공급자로부터 여러 개의 REngine 객체를 가져올 수 있어야합니다.

다른 OSGi 프레임 워크 클래스를 살펴 보았지만 아무 것도 도움이되지 않습니다. 화이트 보드 모델이 있지만 REngineProvider 번들에서 사용하는 REngineRequestService를 등록하면 실제 REngine을 제공 할 수 있습니다.

OSGi에서 어떻게 구현합니까?

  1. 쉬운 사용 및 REngineProvider 번들 해제 : 참고로, 여기 요구 사항을 내 목록입니다. 클라이언트 코드는 대신 다른 공급자를 사용합니다.
  2. REngineProvider 번들 구성.
  3. 클라이언트 번들 당 복수 REngine 개의 인스턴스.
  4. REngine 인스턴스의 명시적인 릴리스
  5. REngine 생성이 실패 할 수 있습니다. 클라이언트 모듈은 이유를 알 수 있어야합니다.

그냥 내가 나중에 참조로 선택한 솔루션을 추가 할 수 있습니다. OSGi Services 플랫폼은 "서비스 요청"을 위해 만들어진 것이 아닙니다. 서비스를 생성하는 공급자 번들과 서비스를 찾고 사용할 수있는 클라이언트 번들입니다. 사용자 요청 당 서비스에 대해 자동 "공장"을 제공하는 것은 불가능합니다.

선택한 솔루션은 OSGi whiteboard model입니다. 첫눈에, 이것은 관리하기가 매우 어려울 것 같지만, Blueprint은 많은 도움이 될 수 있습니다!

공급자 청사진XML 파일 :

<reference-list interface="org.application.REngineRequest" 
      availability="optional"> 
    <reference-listener 
      bind-method="bind" unbind-method="unbind"> 
     <bean class="org.provider.REngineProvider"/>   
    </reference-listener> 

클래스 REngineRequest 공유 API 입력에 제공 그의 REngine 개체를 허용하는 클래스 또는 인 설정 작성이 작동하지 않은 이유를 설명하는 예외입니다. 클라이언트에 대한

는 REngine를 사용하여 수행으로 이제 쉽게 :

REngineRequest req = new REngineRequest(); 
ServiceRegistration reg = bundleContext.registerService(req, REngineRequest.class.getName(), engineCreationProperties); 
req.getEngine().doSomeStuff(); 
reg.unregister(); 

우리는 클라이언트가 REngine을 사용하는 동안 공급자가 멈추지 않을 것이라는 가정을합니다. 이 경우 REngine이 유효하지 않게됩니다.

답변

3

ComponentFactory에서 Declarative Services이 필요합니다. 대부분의 경우 수동으로 서비스를 등록하고 찾는 대신 DS를 사용해야합니다.

공급자 측에서 REngine 팩토리 서비스를 등록해야합니다 (팩토리 자체를 구현할 필요가 없습니다. DS가 대신 해당 작업을 수행합니다). consmer는 일대 다 의존성을 REngine 서비스에 선언해야합니다. 런타임에 사용 가능한 모든 팩토리가 삽입되고 소비자는 실제 REngine 인스턴스를 만들 수 있습니다.

+0

DS 대신 BluePrint 및 PROTOTYPE 주석을 사용 하시겠습니까? 나는 그 차이를보기 힘들다. – parasietje

+0

나는 청사진과 프로토 타입 범위를 제안하려고했습니다. 청사진에는 선언적 서비스보다 더 많은 노브가있어 여기에서 유용 할 수 있습니다. –

+0

불행히도, 객체를 만들 때 컨텍스트 (속성)가 필요합니다. 간단한 팩토리 메서드를 지정할 수는 없지만 인스턴스화 된 클래스를 지정해야한다는 것은 큰 힘이됩니다. 청사진에 그런 희망이 있기를 바랍니다! – parasietje

1

한 가지 해결책은 REngine 구현 자체가 아닌 서비스로 REngineFactory를 등록하고 getService 메소드에서 팩토리를 반환하는 것입니다. 이렇게하면 고객이 공장을 검색하여 성공적으로 공장을 찾으면이를 사용하여 새로운 REngine 구현을 얻을 수 있습니다.

3

2 년 전 나는 정품 서비스 팩토리를 만들어 나중에 매개 변수화 서비스로 만들려고했습니다. 그러나 분석이 끝나면 아무 것도 필요 없다는 것이 판명났습니다. 공장을 서비스로 등록하십시오.

그러나.

서비스에 대해 충분히 알지 못하지만 클라이언트 번들에서 컨트롤을 제거하여 작업을 크게 단순화 할 수 있다고 생각됩니다. 클라이언트 번들은 서비스 레지스트리에서 사용할 수있는 모든 REngine 서비스를 사용해야합니다. REngine을 필요로하는 여러 묶음이 있고 거의 동일한 REngine을 공유하면 안된다.

해당 모델이 가능하면 대개 단순화됩니다. 일반적으로 DS를 사용하여 인스턴스를 구동하는 구성 관리자 구성 (DS의 가장 유용한 기능 중 하나 인 http://www.aqute.biz/Bnd/Components 참조)을 사용합니다. 메타 타입 통합을 사용하면 구성 등록 정보를 편집 할 수있는 사용자 인터페이스가 제공됩니다.

+0

이것은 아마도 가장 간단한 구현 일 것입니다. 서비스를받는 번들은 새로운 서비스의 등록을 트리거합니다. – parasietje

+0

아하! 따라서 해결책은 구성 관리자를 사용하여 "다음 REngine 인스턴스를 생성하십시오"라는 목록을 제공 한 다음 서비스를받는 것입니다. 아마도 REngine 객체 대신 예외를 게시하여 예외를 전달할 수 있습니다. 남은 문제는 서비스 요청과 서비스 가져 오기 사이의 타이밍 문제입니다. – parasietje

+2

서비스를받는 것은 새 등록을 시작하지 않습니다. 두 단계가 있습니다. 클라이언트 번들은 레지스트리에있는 모든 것을 가져 가고, 구성 관리자는 DS 구성 요소를 통해 사용할 수있는 것을 정의합니다. DS 구성 요소를 사용하면 종속성을 표현하기 때문에 타이밍에 문제가 없습니다. 미들웨어 개발자가 아니라면 ServiceReferences를 절대 사용하지 마십시오 ... 특히 주석이 포함 된 DS는 믿을 수 없을 정도로 깨끗합니다. –