# OSGi Verteilte Anwendung?



## Kai2 (30. Jun 2011)

Hallo,
ich habe auf mehreren Rechnern Platformen laufen, wie ich mittels OSGi Bundels realisiert habe. Diese Plattformen stellen spezielle DIenste bereit, wobei jeder Dienst ein OSGi-Bundle ist. 

Ich möchte erreichen: Ist auf Plattform 2 ein Dienst d angemeldet, der auf Plattform 1 nicht läuft, so soll ein Nutzer von Plattform 1 trotzdem den Dienst d so aufrufen können, als wäre er an seiner PLattform da -> per remote Fernaufruf. (Transparenz der Verteilung) 

Erst wollte ich das händisch mit RMI machen. Nun bin ich aber darauf gestoßen, dass die OSGi Plattform schon verteilte Netzwerkkommunikation von Haus aus unterstützt (mit entsprechender schon exisiterender Zusatzsoftware), was natürlich super ist, da meine Plattformen ohnehin mit OSGi-Bundels aufgebaut ist. Ich habe da etwas von ECF (Eclipse Communication Framework), r-OSGi und d-OSGi (distributed OSGi) gehört/gelesen. Leider Blicke ich da nicht so ganz durch, was was ist. Auch finde ich keine wirklichen Tutorials dazu!

Was ich erreichen möchte, habe ich oben beschrieben. Könnt ihr mir helfen und mich beraten, was von den genannten Varianten (oder gar eine ganz andere?) für mich die richtige wäre? Ein gutes Online-Tutorial oder ne gute Buchempflehlung wäre dann natürlich noch der Hammer 

Schonmal vielen Dank!

MfG Kai


----------



## muckelzwerg (30. Jun 2011)

Ja, das geht/ging mit r-osgi und d-osgi. Ist jetzt schon zwei Jahre her, dass ich damit gearbeitet habe und es ging damals mit r-osgi bereits. Wenn Du die Endpunkte (also die Bundles bzw. Services) kennst und da nichts dynamisch läuft, dann ist es ohne Discovery-Protokolle eigentlich recht simpel.


----------



## Kai2 (30. Jun 2011)

Hallo, erstmal Danke für die schnelle Antwort!
Was bedeutet: "wenn da nichts dynamisch läuft"? Es soll schon möglich sein, dass man (wenn das Gesamtsysmtem schon läuft) noch an einem beliebeigen Rechner an einer Plattform einen Dienst anhängen kann, den danach natürlich alle nutzen sollen können. Das ist dann dynamisch, oder? Also so bräuchte ich das. Ginge das trotzdem mit r- bzw- d-OSGi? Wenn du damit gearbeitet hast: Kennst du gute Tutorials oder Literatur, wo das für einen "Neuling" einfach und verständlich beschrieben wird? Ich komm grad frisch von der Uni und hab leider noch sehr sehr wenig Programmiererfahrung, weshalb gute Literatur bzw. nen Tutorial echt hilfreich wäre. Hab lange gesucht, aber leider nichts brauchbares gefunden.

MfG Kai

Zusatzbemerkung:
Du meintest, dass du das vor über zwei Jahren benutzt hast: Gibt es heute schon elegantere Lösungen? (Meine Anwnedungen sind wie gesagt aus OSGi-Bundels aufgebaut - es müsste also etwas sein, was die OSGi-Architekur unterstützt).


----------



## muckelzwerg (30. Jun 2011)

Wenn Du keine fixen Adressen der Services hast, dann musst Du eine Art von "Binding" verwenden. Dafür gab es damals Discoveryprotokolle, um den Service zu finden, den man haben wollte. Das war "damals" etwas bröselig. Da war aber d-osgi auch noch ziemlicher Ramsch. Funktioniert hat es aber.

Ich kann Dir leider keine Tutorials nennen. Ich hab damals mit Apache Felix und R-OSGI gearbeitet und das Zeug auf Sensorknoten und Routern eingesetzt um dann wieder UPnP-Geräte anzusprechen. Da waren im Prinzip nur die Homepages und die Spezifikation von OSGI die Basis.
Heute gibts da bestimmt einiges mehr. Und mit OSGI selbst kennst Du Dich doch schon aus, da ist der Sprung nicht so groß. Bei R-OSGI werden Remote-Bundle erzeugt, die als Proxies für die Bundles auf dem anderen Rechner dienen. Das ist eigentlich nicht so viel Magic.


----------



## Kai2 (4. Jul 2011)

Hi, nochmal Danke für die Hilfe. Hab versucht eine r-OSGI Anwendung zu erstellen, bin aber leider gescheitert  
[dazu vlt später mehr, falls ich den Ansatz weiter verfolge]
Habe nun aber etwas von Riena gelesen. Gute Doku gibt es aber nirgends - sei es zu Riena, zu d-OSGi, zu r-OSGi, zu ECF... . 

Daher meine Frage: Kennt sich jemand damit aus und könnte mir sagen, welche Variante für meinen Anwendungsfall die günstigste wäre?

Also ich habe ein Verteiltes System, wobei einzelne Dienste als OSGi-Bundles angeboten werden. Befindet sich auf einem Rechner ein Dienst, so sollen alle anderen Rechner diese transparanent (per Fernzugriff?) nutzen können. 
Wichtig ist auch, dass ich Dienste während der Laufzeit an eine Platfform anmelden muss. Die andern Plattformen sollen dann auf den zur Laufzeit angemeldeten Dienst ebenso transparent zugreifen können. 
Erst wollte ich das über RMI machen, wie schon erwähnt. Mein Chef möchte aber, dass es generischer bleibt. Also wenn ich einen RMI-Ansatz wähle, sollte es dennoch möglich sein ohne viele Änderungen auf WebServices umzuschenken und umgedreht, da er meint, dass noch nicht bekannt ist, was für uns günstiger sein könnte.

Daher dachte ich an einer der oben genannten Varianten, da man dort ja das Kommunikationsprotokoll meist seperat einstellen kann, oder? Nur welche? 

Wenn mir jemand eine nennt die gut ist, würde mir das ungemein helfen, weil ich mich dann nur durch eine durchquälen muss und nicht 5 schlecht dokumentierte und mir bisher vollkommen unbekannte Ansätze vergleichen muss. ???:L

Schonmal vielen Dank!
MfG Kai


----------



## muckelzwerg (4. Jul 2011)

Hm, "ich hab es nicht hinbekommen, gibt es eine andere Möglichkeit?" ist eigentlich nicht unbedingt eine so weiterführende Frage oder?
Du hast bereits OSGi im Einsatz, also ist verteiltes OSGi doch ziemlich naheliegend. Und funktionieren tut es auch.
Was hast Du denn genau versucht, welche Anleitungen hast Du durchgespielt? Es gibt doch sogar fertige binaries dafür, mit vorinstallierten Bundles, oder nicht?


----------



## Kai2 (4. Jul 2011)

Hallo,
weshalb ich am Überlegen zum Umschwänken bin hat nichts damit zu tun, dass es beim ersten Versuch nicht geklappt hat, sondern vielmehr damit, dass mein Chef meinte, dass er aus Perfarmance und Firewallgründen in der Lage sein möchte die Kommunikationsart zu wechseln. Also z.B. zwischen "Kommunikation mit RMI" oder "Kommunikation mittels Webservices" switchen. 
Ich muss jetzt nicht beide Kommunikationsarten implementieren. Es reicht vollkommen, wenn ich nur eine mache, aber die Schnittstellen sollten so gewählt sein, dass man z.B. eine RMI-Kommunikationsimplementierung leicht durch eine Implementierung mittels Webservices austauschen könnte. 

r-OSGi nutzt doch als Protokoll Hessian, oder? Das ist ne Kommonikation über Webservices, oder? Da hat man doch dann den ganzen "XML-Umwandel und Verpack"-Aufwand, was bestimmt langsamer als RMI wäre. Daher könnte das in dem Sinne ne schlechte Wahl sein, wenn ichs nun so mache. Oder ist r-OSGi Performancetechnisch nicht erwähnenswert schlechter als RMI?
Rein mit RMI machen wäre aber auch wieder schlecht, weil der Chef meinte, später brauchen wirs vlt doch als Webservices und RMI könnte Probleme mit Firewalls machnen... . Daher wär ihm diese "switch"-Variante am liebsten, aber ich hab keine Ahnung, wie das gehen soll und hatte gehofft, das einer der obigen Ansätze das leistet. 

Aber da mir momentan nichts besseres einfällt, bleib ich vlt wirklich bei r-Osgi... . Ich würde nochmal gucken, was genau für Fehler kamen und mich nachher nochmal melden. 

Schonmal Danke


----------



## muckelzwerg (4. Jul 2011)

Puahhh, Theorie vs. Realität würde ich sagen. ^^
Sorry, das ist mir zu sehr Softwaretechnik, als dass ich da was wirklich Nützliches sagen kann.

r-OSGi war damals bei mir nicht sonderlich stressig. Wir hatten es mit den Infos von der Sourceforge-Seite relativ schnell zum Laufen gebracht. Auch mit remote UI.
Allerdings auf Felix. KA ob das mit z.B. Equinox anders läuft.


----------



## Kai2 (5. Jul 2011)

Hi,
ich habe mich nun dazu entschieden, r-OSGi zu versuchen! Habe ein einfaches Beispiel von hier versucht umzusetzen:
Stefan Diener - Software development: Tutorial: How to create a remote OSGi service

Leider erhalte ich ein null-Objekt zurück, wenn ich die RemoteServiceReference anfordere. Kann mir jemand sagen, was ich falsch mache?
Mein Code:
(ServerActivator)
[JAVA=42]package serverremote;

import java.util.Hashtable;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import serverremote.internal.Server;

import ch.ethz.iks.r_osgi.RemoteOSGiService;

public class Activator implements BundleActivator {

	private static BundleContext context;

	static BundleContext getContext() {
		return context;
	}

	/*
	 * (non-Javadoc)
	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext bundleContext) throws Exception {
		Activator.context = bundleContext;
		final Hashtable properties = new Hashtable();
	      properties.put(RemoteOSGiService.R_OSGi_REGISTRATION, Boolean.TRUE);
	      context.registerService(Server.class.getName(), new Server(), properties);
	      System.out.println("Service registered.");
	}

	/*
	 * (non-Javadoc)
	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext bundleContext) throws Exception {
		Activator.context = null;
	}

}[/code]

(ServerObject)
[JAVA=42]package serverremote.internal;

public class Server {

	private String s = "Du hast es geschafft!";

	public String getS(){
		return s;
	}

}[/code]

(ClientActivator)
[JAVA=42]package clientremote;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import serverremote.internal.Server;

import ch.ethz.iks.r_osgi.RemoteOSGiService;
import ch.ethz.iks.r_osgi.RemoteServiceReference;
import ch.ethz.iks.r_osgi.URI;

public class Activator implements BundleActivator {

	private static BundleContext context;

	static BundleContext getContext() {
		return context;
	}

	/*
	 * (non-Javadoc)
	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext bundleContext) throws Exception {
		Activator.context = bundleContext;
	    final ServiceReference serviceRef = context.getServiceReference(RemoteOSGiService.class.getName());
	    if (serviceRef == null) {
	          System.out.println("R-OSGi service not found!");
	    } else {
	          final RemoteOSGiService remote = (RemoteOSGiService) context.getService(serviceRef);
	          try {
	              remote.connect(new URI("r-osgi://localhost:9279"));

	              final RemoteServiceReference[] references = remote.getRemoteServiceReferences(
	                  new URI("r-osgi://localhost:9279"), Server.class.getName(), null);
	              if (references == null) {
	                  System.out.println("Service not found!");
	              } else {
	                  final Server server = (Server) remote.getRemoteService(references[0]);
	                  System.out.println(server.getS());
	              }
	        } finally {
	              context.ungetService(serviceRef);
	        }
	     }
	}


	/*
	 * (non-Javadoc)
	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext bundleContext) throws Exception {
		Activator.context = null;
	}

}[/code]

Wenn ich Server und Client ausführe, kommt folgende Ausgabe auf der Konsole:
osgi> WARNING: Port 9278 already in use. This instance of R-OSGi is running on p
ort 9279
Service registered.
Service not found!


Wie im Quellcode zu sehen ist, hab ich den Port statisch einfach mal auf 9279 gesetzt, da der immer den nimmt. Bei 9278 kam eine Exception, dass die Adresse nicht gefunden wird.
Da "Service not found" vom Cliet ausgegeben wird, heißt das ja, dass die RemoteServiceReference null ist, wenn man sich den Code anschaut. 

Aber warum? Was mach ich denn falsch?

Schonmal vielen Dank!
MfG Kai


----------



## Kai2 (6. Jul 2011)

Huhu,
mein Beispiel hat sich erstmal geklärt. Hab es nochmal gemacht (eigentlich identisch) und dann hats funktioniert! Dieser Thread hier ist also vorerst erledigt. Vielen Dank an muckelzwerg für die wirklich nette und gute Beratung/Unterstützung!

Viele Grüße,
Kai


----------

