OSGi deklarative Services (DS): Was ist eine gute Möglichkeit Instanzen der Verwendung von Service-Komponente

StackOverflow https://stackoverflow.com/questions/1102754

Frage

Ich bin gerade mit OSGi und deklarativem Service (DS) mit Equinox und Eclipse PDE getting started.

Ich habe 2 Bundles, A und B. Bundle A stellt eine Komponente, die von Bundle B. Beide Bündel verbraucht wird diesen Service auch auf den wieder Registry OSGi Service aussetzen.

Alles funktioniert so weit in Ordnung und Equinox ist wireing die Komponenten zusammen, die das Bündel A und B Bundle bedeutet, werden durch Equinox instanziiert (durch den Standard-Konstruktor aufrufen) und dann passiert das wireing die bind / unbind Methoden.

Jetzt, da Equinox ist die Instanzen dieser Komponenten erstellen / Dienstleistungen Ich möchte wissen, was der beste Weg ist, um diese Instanz zu bekommen?

So nehme an, es ist dritte Klasse Klasse, die nicht von OSGi instanziiert wird:

Class WantsToUseComponentB{
public void doSomethingWithComponentB(){
 // how do I get componentB??? Something like this maybe?
 ComponentB component = (ComponentB)someComponentRegistry.getComponent(ComponentB.class.getName());
}

Ich sehe die folgenden Optionen jetzt:


1. Verwenden Sie einen Servicetracker in der Activator , um den Dienst von ComponentBundleA.class.getName zu bekommen () (Ich habe versucht, das schon und es funktioniert, aber es scheint zu viel Aufwand für mich) und machen es über eine statische Factory-Methoden zur Verfügung

 
public class Activator{

   private static ServiceTracker componentBServiceTracker;   

   public void start(BundleContext context){

     componentBServiceTracker = new ServiceTracker(context, ComponentB.class.getName(),null);
   }

   public static ComponentB getComponentB(){
     return (ComponentB)componentBServiceTracker.getService(); 
   };

}

2. Erstellen Sie eine Art von Registry , wobei jede Komponente registriert, sobald die activate () -Methode aufgerufen wird.

public ComponentB{

public void bind(ComponentA componentA){
   someRegistry.registerComponent(this);
}

oder

public ComponentB{

   public void activate(ComponentContext context){
      someRegistry.registerComponent(this);
   }

}

}

3. Verwenden Sie eine vorhandene Registrierung innerhalb osgi / Tagundnachtgleiche , die diese Instanzen hat? Ich meine OSGi ist bereits Instanzen und Drähte ihnen zusammen zu schaffen, so hat es die Objekte schon irgendwo. Aber wo? Wie kann ich sie bekommen?

Fazit Woher kommt die Klasse WantsToUseComponentB (die nicht Bestandteil und nicht die von OSGi instanziiert) erhalten eine Instanz von ComponentB aus? Gibt es irgendwelche Muster oder Best Practices? Wie gesagt habe ich es geschafft eine Servicetracker in den Aktivator zu verwenden, aber ich dachte, dass es ohne sie möglich wäre.

Was ich suche, ist eigentlich so etwas wie die BeanContainer von spring, wo ich gerade so etwas wie Container.getBean (ComponentA.BEAN_NAME) sagen kann. Aber ich will nicht Frühling DS verwenden.

Ich hoffe, dass klar genug war. Ansonsten kann ich auch einige Quellcode veröffentlichen näher zu erklären.

Danke Christoph


AKTUALISIERT: Antwort auf Neil Kommentar:

  

Danke für diese Frage gegen die ursprüngliche Version zu klären, aber ich glaube, Sie müssen noch angeben, warum die dritte Klasse kann nicht über so etwas wie DS erstellt werden.

Hmm weiß es nicht. Vielleicht ist es eine Möglichkeit, aber ich müsste meinen ganzen Rahmen Refactoring auf DS zu stützen, so dass es mehr keine „neue MyThirdClass (arg1, arg2)“ Aussagen. Sie nicht wirklich wissen, wie das zu tun, aber ich las etwas über ComponentFactories in DS. So zu tun, anstatt ein

MyThirdClass object = new MyThirdClass(arg1, arg2);

Ich könnte ein tun

ComponentFactory myThirdClassFactory = myThirdClassServiceTracker.getService(); // returns a 

if (myThirdClassFactory != null){
  MyThirdClass object = objectFactory.newInstance();

   object.setArg1("arg1");
  object.setArg2("arg2");
}
else{
 // here I can assume that some service of ComponentA or B went away so MyThirdClass Componenent cannot be created as there are missing dependencies?

}

Zum Zeitpunkt des Schreibens ich weiß nicht genau, wie die ComponentFactories zu verwenden, aber dies soll eine Art Pseudo-Code sein:)

Danke Christoph

War es hilfreich?

Lösung

Christoph,

Danke für diese Frage gegen die ursprüngliche Version zu klären, aber ich glaube, Sie müssen noch angeben, warum die dritte Klasse kann nicht über so etwas wie DS erstellt werden.

DS verursacht Komponenten als Dienste veröffentlicht werden, damit die einzige Möglichkeit, eine beliebige Komponente von DS zu „get“ ist es über die Service-Registry zuzugreifen. Leider kann der Service Registry schwer richtig zu verwenden, um den niedrigeren Level-APIs verwenden, da es dynamisch ist, so muss man mit der Möglichkeit, Dienste bewältigen weggeht oder nicht zur Verfügung steht genau in dem Moment Sie sie zur Verfügung stehen sollen, und so weiter . Aus diesem Grund DS vorhanden ist. Es gibt Ihnen eine Abstraktion für die abhängig von Dienstleistungen und die Verwaltung des Lebenszyklus Ihrer Komponenten basierend auf der Verfügbarkeit von Diensten, die sie sich beziehen

Wenn Sie wirklich einen Dienst zugreifen müssen, ohne DS oder etwas ähnliches zu verwenden (und es ist durchaus eine Wahl von „Dingen wie es“ zum Beispiel Frühlings-DM, iPOJO, Guice / Peaberry, etc), dann sollten Sie Servicetracker verwenden. Ich stimme es eine Menge Aufwand ist -. Wieder, deshalb DS existiert statt

Um Ihren Vorschlag nicht (2) zu beantworten, nein, sollten Sie nicht Ihre eigene Registrierung der Dienste erstellen, da der Service-Registry ist bereits vorhanden. Wenn Sie eine separate parallele Registrierung erstellt dann würden Sie noch alle die Dynamik zu handhaben, aber man würde es an zwei Stellen zu behandeln haben statt einer. Das gleiche gilt für Vorschlag (3).

Ich hoffe, das hilft.

Viele Grüße, Neil

AKTUALISIERT: Übrigens, obwohl Frühling die Container.getBean () Backdoor hat, merkt man, dass in jedem Frühjahr Dokumentation dringend nicht, dass Backdoor zu verwenden empfohlen: Halten eines Spring-Bean zu erhalten, erstellen Sie einfach eine andere Bean, die sie referenziert . Das gleiche gilt für DS, das heißt der beste Weg halten, einen DS-Komponente zu erhalten, ist ein anderen DS-Komponente zu erstellen.

Beachten Sie auch, dass in der OSGi-Welt, auch wenn Sie Frühlings-DM verwenden es keine einfache Möglichkeit ist, einfach anrufen getBean (), weil Sie halten den Frühling Application ersten bekommen müssen. Das ist selbst ein OSGi-Service, so wie Sie diesen Dienst bekommen?

Andere Tipps

christoph, weiß nicht, ob ich das Problem wirklich zu verstehen. pro Ex. Bundle A ist eine Dienstleistung mit DS-Komponente bereitstellt:

<service>
  <provide interface="org.redview.lnf.services.IRedviewLnfSelectedService"/>

Bundle B erfordert diesen Service DS-Komponente:

<implementation class="ekke.xyz.rcp.application.internal.XyzApplicationLnfComponent"/>

sobald Bundle A den Service bietet, Bündel B "bekommt" es durch die bind () Methode der Implementierungsklasse:

public class XyzApplicationLnfComponent {
public void bind(IRedviewLnfSelectedService lnfSelectedService) {
    // here it is
}

hoffe, das hilft ekke

Die einfache Weg: Injizieren Sie den DS-Komponente in der Activator-Klasse mit Riena: http://wiki.eclipse.org/Riena_Getting_Started_with_injecting_services_and_extensions

Dann können Sie es von überall her rufen:. Activator.getDefault () getWhateverService ()

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top