Uvod u OSGi

1. Uvod

Nekoliko Java-kritičnih aplikacija i međuprogramskog softvera ima neke tvrde tehnološke zahtjeve.

Neki moraju podržavati vruću implementaciju kako ne bi ometali pokrenute usluge - a drugi moraju biti u mogućnosti raditi s različitim verzijama istog paketa radi podrške vanjskim naslijeđenim sustavima.

The OSGi platforme predstavljaju održivo rješenje za podržavanje ove vrste zahtjeva.

The Open Service Gateway Initiative je specifikacija koja definira sustav komponenata zasnovan na Javi. Trenutno njime upravlja OSGi savez, a njegova prva verzija datira iz 1999.

Od tada se pokazao kao izvrstan standard za komponentne sustave i danas se široko koristi. The Eclipse IDE, na primjer, je OSGiaplikacija na temelju.

U ovom ćemo članku istražiti neke osnovne značajke OSGi iskorištavajući provedbu koju pruža Apači.

2. OSGi osnove

U OSGi-u, jedna se komponenta naziva paket.

Logički, paket je dio funkcionalnosti koji ima neovisan životni ciklus - što znači da se može samostalno pokrenuti, zaustaviti i ukloniti.

Tehnički gledano, paket je samo jar datoteka s datotekom NAJVIŠE.MF datoteka koja sadrži neka zaglavlja specifična za OSGi.

The OSGi platforma pruža način primanja obavijesti o paketima koji postaju dostupni ili kada su uklonjeni s platforme. To će omogućiti pravilno dizajniranom klijentu da nastavi raditi, možda s pogoršanom funkcionalnošću, čak i kad je usluga o kojoj ovisi trenutno nedostupna.

Zbog toga paket mora izričito deklarirati kojim paketima treba imati pristup i OSGi platforma će ga pokrenuti samo ako su ovisnosti dostupne u samom paketu ili u drugim paketima koji su već instalirani na platformi.

3. Dobivanje alata

Započet ćemo putovanje OSGi preuzimanjem najnovije verzije Apač Karaf s ove poveznice. Apač Karaf je platforma koja radi OSGi-temeljene aplikacije; temelji se na Apači'S provedba OSGi specifikacija nazvana Apache Felix.

Karaf nudi neke korisne značajke povrh Felix to će nam pomoći pri upoznavanju OSGi, na primjer, sučelje naredbenog retka koje će nam omogućiti interakciju s platformom.

Instalirati Karaf, možete slijediti upute za instalaciju iz službene dokumentacije.

4. Točka unosa snopa

Da bismo izvršili aplikaciju u OSGi okruženju, moramo je spakirati kao OSGi grupirajte i definirajte ulaznu točku aplikacije, a to nije uobičajeno javna statička void glavna (String [] args) metoda.

Pa, krenimo s izgradnjom OSGi- zasnovan na "Hello World" aplikaciji.

Počinjemo postavljati jednostavnu ovisnost o jezgri OSGi API:

 org.osgi org.osgi.core 6.0.0 pod uvjetom 

Ovisnost se deklarira kao pod uvjetom jer će biti dostupan u OSGi vrijeme izvođenja, a paket ga ne treba ugrađivati.

Napišimo sada jednostavno Pozdrav svijete razred:

javna klasa HelloWorld implementira BundleActivator {javni void start (BundleContext ctx) {System.out.println ("Hello world."); } javno prazno zaustavljanje (BundleContext bundleContext) {System.out.println ("Zbogom svijet."); }}

BundleActivator je sučelje koje pruža OSGi to moraju implementirati klase koje su ulazne točke za paket.

The početak() metoda poziva se OSGi platformi kada se pokreće paket koji sadrži ovu klasu. S druge strane Stop() poziva se prije nego što je snop zaustavljen.

Imajmo na umu da svaki snop može sadržavati najviše jedan BundleActivator. The BundleContext objekt koji se pruža objema metodama omogućuje interakciju s OSGi vrijeme izvođenja. Uskoro ćemo se vratiti na to.

5. Izrada snopa

Izmijenimo pom.xml i učinite to stvarnim OSGi paketom.

Prije svega, moramo izričito navesti da ćemo izgraditi snop, a ne jar:

paket

Tada koristimo dodatak maven-bundle, ljubaznošću Apache Felix zajednicu, za spakiranje Pozdrav svijete razred kao an OSGi paket:

 org.apache.felix maven-bundle-plugin 3.3.0 true $ {pom.groupId}. $ {pom.artifactId} $ {pom.name} $ {pom.version} com.baeldung.osgi.sample.activator.HelloWorld com.baeldung.osgi.sample.activator 

U odjeljku s uputama navodimo vrijednosti OSGi zaglavlja koja želimo uključiti u datoteku MANIFEST paketa.

Paket-aktivator je potpuno kvalificirano ime BundleActivator implementacija koja će se koristiti za pokretanje i zaustavljanje snopa, a odnosi se na klasu koju smo upravo napisali.

Privatni paket nije OSGi zaglavlje, ali se koristi da dodatak kaže da paket uključuje u paket, ali da ga ne učini dostupnim drugim. Sad možemo graditi snop uobičajenom naredbom mvn čista instalacija.

6. Instaliranje i pokretanje paketa

Počnimo Karaf izvršavanjem naredbe:

/ bin / karaf start

gdje je mapa u kojoj Karaf je instaliran. Kada se odzivnik Karaf konzola se može izvršiti sljedeću naredbu za instalaciju snopa:

> paket: instalirajte mvn: com.baeldung / osgi-intro-sample-activator / 1.0-SNAPSHOT ID paketa: 63

Ovo upućuje Karafa da učita paket iz lokalnog spremišta Maven.

Zauzvrat, Karaf ispisuje numerički ID dodijeljen snopu koji ovisi o broju već instaliranih snopova i može varirati. Paket je sada tek instaliran, sada ga možemo pokrenuti sljedećom naredbom:

> paket: početak 63 Hello World

"Hello World" odmah se pojavljuje čim se paket pokrene. Sada možemo zaustaviti i deinstalirati paket sa:

> bundle: stop 63> bundle: deinstaliraj 63

"Goodbye World" pojavljuje se na konzoli, u skladu s kodom u Stop() metoda.

7. OSGi usluga

Idemo dalje pisati jednostavan OSGi usluga, sučelje koje izlaže metodu pozdravljanja ljudi:

paket com.baeldung.osgi.sample.service.definition; javno sučelje Greeter {javni String sayHiTo (naziv niza); }

Napišimo njegovu implementaciju koja je a BundleActivator također, tako da ćemo moći pokrenuti uslugu i registrirati je na platformi kad se paket pokrene:

paket com.baeldung.osgi.sample.service.implementation; javna klasa GreeterImpl implementira Greeter, BundleActivator {private ServiceReference reference; privatna registracija ServiceRegistration; @Override public String sayHiTo (naziv niza) {return "Hello" + name; } @Override public void start (kontekst BundleContext) baca iznimku {System.out.println ("Usluga registracije."); registracija = context.registerService (Greeter.class, novi GreeterImpl (), novi Hashtable ()); referenca = registracija .getReference (); } @Override public void stop (kontekst BundleContext) baca iznimku {System.out.println ("Poništavanje registracije usluge."); registration.unregister (); }}

Koristimo BundleContext kao sredstvo zahtjeva za OSGi platforma za registraciju nove instance usluge.

Također bismo trebali pružiti vrstu usluge i mapu mogućih konfiguracijskih parametara koji nisu potrebni u našem jednostavnom scenariju. Krenimo sada s konfiguracijom maven-bundle-plugin:

 org.apache.felix maven-bundle-plugin true $ {project.groupId}. $ {project.artifactId} $ {project.artifactId} $ {project.version} com.baeldung.osgi.sample.service.implementation.GreeterImpl com .baeldung.osgi.sample.service.implementation com.baeldung.osgi.sample.service.definition 

Vrijedno je napomenuti da samo com.baeldung.osgi.sample.service.definition paket je ovaj put izvezen kroz Izvozni paket Zaglavlje.

Zahvaljujući tome, OSGi omogućit će ostalim snopovima pozivanje samo metoda navedenih u sučelju usluge. Paket com.baeldung.osgi.sample.service.implementation označena je kao privatna, tako da niti jedan drugi paket neće moći izravno pristupiti članovima implementacije.

8. OSGi klijent

Napišimo sada klijenta. Jednostavno traži uslugu prilikom pokretanja i poziva je:

klijent javne klase implementira BundleActivator, ServiceListener {}

Provedimo BundleActivator start () metoda:

privatni BundleContext ctx; private ServiceReference serviceReference; javni void start (BundleContext ctx) {this.ctx = ctx; isprobajte {ctx.addServiceListener (this, "(objectclass =" + Greeter.class.getName () + ")"); } catch (InvalidSyntaxException ise) {ise.printStackTrace (); }}

The addServiceListener () metoda omogućuje klijentu da od platforme zatraži slanje obavijesti o usluzi koja je u skladu s navedenim izrazom.

Izraz koristi sintaksu sličnu LDAP-ovoj, a u našem slučaju tražimo obavijesti o a Pozdrav servis.

Krenimo na metodu povratnog poziva:

public void serviceChanged (ServiceEvent serviceEvent) {int type = serviceEvent.getType (); prekidač (tip) {case (ServiceEvent.REGISTERED): System.out.println ("Obavijest o usluzi registrirana."); serviceReference = serviceEvent .getServiceReference (); Pozdravljanje usluge = (Pozdravljanje) (ctx.getService (serviceReference)); System.out.println (service.sayHiTo ("John")); pauza; slučaj (ServiceEvent.UNREGISTERING): System.out.println ("Obavijest o usluzi neregistrirana."); ctx.ungetService (serviceEvent.getServiceReference ()); pauza; zadano: prekid; }}

Kad se neka preinaka koja uključuje Pozdrav dogodi se usluga, obavijesti se o metodi.

Kada je usluga registrirana na platformi, dobivamo referencu na nju, pohranjujemo je lokalno i zatim koristimo za dobivanje objekta usluge i pozivanje na nju.

Kad se poslužitelj kasnije neregistrira, koristimo prethodno pohranjenu referencu da ga poništimo, što znači da kažemo platformi da ga više nećemo koristiti.

Sada samo trebamo napisati Stop() metoda:

javno prazno zaustavljanje (BundleContext bundleContext) {if (serviceReference! = null) {ctx.ungetService (serviceReference); }}

Ovdje opet uklanjamo uslugu kako bismo pokrili slučaj u kojem je klijent zaustavljen prije zaustavljanja usluge. Dajmo konačni pogled na ovisnosti u pom.xml:

 com.baeldung osgi-intro-sample-service 1.0-SNAPSHOT pod uvjetom org.osgi org.osgi.core 6.0.0 

9. Klijent i usluga

Instalirajmo sada klijentske i servisne pakete u Karaf tako što ćemo učiniti:

> instalirajte mvn: com.baeldung / osgi-intro-sample-service / 1.0-SNAPSHOT ID snopa: 64> instalirajte mvn: com.baeldung / osgi-intro-sample-client / 1.0-SNAPSHOT ID snopa: 65

Uvijek imajte na umu da se identifikacijski brojevi dodijeljeni svakom paketu mogu razlikovati.

Počnimo sada snop klijenata:

> start 65

Stoga se ništa ne događa jer je klijent aktivan i čeka uslugu, a mi možemo započeti s:

> start 64 Usluga registracije. Usluga registrirana. Pozdrav John

Ono što se događa je da čim se BundleActivator usluge pokrene, usluga se registrira na platformi. To, pak, obavještava klijenta da je usluga koju je čekao dostupna.

Klijent tada dobiva referencu na uslugu i koristi je za pozivanje implementacije isporučene kroz paket usluga.

10. Zaključak

U ovom smo članku istražili bitne značajke OSGi-a s direktnim primjerom da je to dovoljno za razumijevanje potencijala OSGi-a.

Zaključno, kad god moramo jamčiti da se pojedinačna aplikacija mora ažurirati bez ikakvih loših usluga, OSGi može biti održivo rješenje.

Kôd za ovaj post možete pronaći na GitHubu.