Programmering

Hva er OSGi? En annen tilnærming til Java-modularitet

OSGi muliggjør oppretting og administrering av modulære Java-komponenter (kalt bunter) som kan distribueres i en container. Som utvikler bruker du OSGi-spesifikasjonen og verktøyene til å lage en eller flere bunter. OSGi definerer livssyklusen for disse pakkene. Det er også vert for dem og støtter deres interaksjoner i en container. Du kan tenke på en OSGi-container som omtrent analog med en JVM, med ekstra krefter. Tenk også på bunter som Java-applikasjoner med unike evner. Pakker kjører inne i OSGi-beholderen som klient- og serverkomponenter.

OSGi-alliansen

OSGi startet i 1999, og i motsetning til mange andre spesifikasjoner styres standarden ikke av Oracle, Java Community Process eller Eclipse Foundation. I stedet styres det av OSGi-alliansen.

Hvordan OSGi er annerledes

OSGis filosofi skiller seg fra andre Java-baserte rammer, særlig våren. I OSGi kan det eksistere flere applikasjoner i samme container: OSGi pakke kjøretidsmiljø. Beholderen sørger for at hver komponent er tilstrekkelig isolert, og har også tilgang til alle avhengigheter den krever. OSGi kan støtte avhengighetsinjeksjon, som er standardisert av Aries Blueprint-prosjektet. I tillegg til å tilby OSGi’s inversion of control (IoC) container, støtter Aries standard Java-rammer som Java Persistence API (JPA).

I OSGi kan bunter avsløre tjenester som andre bunter bruker. En pakke kan også erklære en versjon, og kan definere hvilke andre pakker den avhenger av. Kjøretiden laster deretter automatisk alle pakkene i rekkefølge etter avhengighet. I OSGi kan flere versjoner av samme pakke eksistere side om side, hvis det kreves av pakkeavhengigheter.

OSGi i formørkelse IDE og jevndøgn

OSGi har eksistert i noen form i et par tiår. Den brukes til mange kjente applikasjoner, fra innebygde mobile enheter til applikasjonsservere og IDEer.

Den populære Eclipse IDE er bygget på toppen av OSGi. Eclipse implementering av OSGi-containeren kalles Equinox. Det er et godt eksempel for å forstå OSGi. Å være basert på OSGi betyr at Equinox er en modulær plattform. Det er vert for en rekke tjenester som utviklere kan legge til etter eget ønske. Hver av disse tilbyr en evne som en utvikler kan trenge i IDE-en. Du kan legge til redaktører for Java og JavaScript, en app-server og en databasekontakt. Hver av disse er implementert som en OSGi-pakke som legges til containeren og kan samhandle med andre tjenester i containeren.

Nylig har det vært en interesse for å bruke OSGi for Internet of Things (IoT). OSGi passer naturlig for denne typen utvikling, som har en rekke programvarekomponenter som kjører side om side på enheter, uten nødvendigvis å vite om hverandre. En OSGi-container gir en enkel og standardisert måte å være vert for disse dynamiske programvarekomponentene på.

Bruke OSGi i et Java-prosjekt: Knoplerfish OSGi

Vi arbeider gjennom et eksempel på et program som vil gjøre OSGi-konsepter mer konkrete. Eksemplet vårt er basert på Knoplerfish OSGi kjøretid, som brukes i mange produksjonsutrullinger. Knoplerfish inkluderer et GUI og kommandolinjegrensesnitt (CLI) for å administrere OSGi-containeren og dens bunter.

Det første du vil gjøre er å laste ned Knoplerfish. Den nåværende versjonen på dette tidspunktet er Knoplerfish OSGi 6.1.3. Du kan erstatte den versjonen med det som er mest oppdatert når du leser denne artikkelen.

Etter at du har lastet ned og installert Knoplerfish, bruk CLI til å gå inn i katalogen der du lastet ned JAR-filen, og skriv inn: java -jar framework.jar. Det kjører den kjørbare JAR, og du skal bli møtt med et GUI-vindu.

Knoplerfish OSGi GUI

Knoplerfish OSGis GUI kan virke overveldende i begynnelsen, men det grunnleggende er enkelt:

  • Øverst på skjermen er menyen.
  • Til venstre er settet med bunter som er lastet inn i kjøretiden.
  • Til høyre er et informasjonsvindu.
  • Nederst er det en konsoll for tekstutgang.
  • Helt nederst er det en inngangskonsoll.
Matthew Tyson

Type hjelp inn i inngangskonsollen hvis du vil se hjelpealternativene.

Før vi går inn i eksemplet, ta en titt på settet med kjørende bunter. Du ser en pakke kalt HTTP-server, som betyr at en pakke som kjører en HTTP-server er oppe. Gå til nettleseren din, og sjekk ut // localhost: 8080. Visst nok vil du se en Knoplerfish-webside.

“Hello JavaWorld” -pakken

La oss bruke OSGi-kjøretiden til å bygge en enkel pakke, som jeg vil kalle Hei JavaWorld. Denne pakken sender ut en melding til konsollen.

I oppføring 1 bruker vi Maven til å bygge pakken. Den har bare en avhengighet, som leveres av OSGi-alliansen.

Oppføring 1. OSGi-avhengighet i Maven POM

   org.osgi org.osgi.core 

Nå skal vi også bruke en plug-in, takket være Apache Felix-prosjektet. Denne plugin-modulen tar seg av pakking av appen som en OSGi-pakke for bruk. Oppføring 2 viser konfigurasjonen vi vil bruke.

Oppføring 2. OSGi Felix plug-in i Maven POM

   org.apache.felix maven-bundle-plugin true org.javaworld.osgi org.javaworld.osgi.Hello 

Nå kan vi ta en titt på den enkle klassen som vil gi et "Hei".

Oppføring 3. Hei JavaWorld OSGi-pakke

 pakke com.javaworld.osgi; importer org.osgi.framework.BundleActivator; importer org.osgi.framework.BundleContext; offentlig klasse HelloJavaWorld implementerer BundleActivator {public void start (BundleContext ctx) {System.out.println ("Hello JavaWorld."); } offentlig ugyldig stopp (BundleContext bundleContext) {}} 

Bygg pakken ved å gå til kommandolinjen og skrive mvn ren installasjon. Dette vil sende en JAR-fil som inneholder pakken. Nå, gå til Fil menyen i Knoplerfish GUI, og velg Legg til pakke. Dette vil gi en filleser. Finn JAR vi nettopp har laget, og velg den.

Administrere OSGi-bunter i containeren

I utgangsvinduet til Knoplerfish UI vil du se "Hello, JavaWorld" -meldingen vises. Klikk på pakken i Knoplerfish GUI, og du kan se ID-en som beholderen har tildelt den. Når du er klar til å stoppe pakken, kan du klikke på stopp-menyelementet. En annen måte er å komme inn stopp [pakke nummer] på kommandolinjen. Du kan administrere bunter i containeren ved hjelp av enten GUI eller kommandolinjen.

Nå har du en følelse av hvordan en enkel pakke fungerer i OSGi-containeren. Uansett hvor en OSGi-container eksisterer, vil du finne den samme enkelheten i å starte og stoppe bunter. OSGi skaper et miljø og en livssyklus for pakken.

Bundle Interactions: Services and clients

Deretter vil vi se på hvordan bunter kommuniserer med hverandre.

Det første vi skal gjøre er å lage en servicepakke. En servicepakke er analog med en EJB-øktbønne: Den gir en komponent som er tilgjengelig for andre pakker via et eksternt grensesnitt. For å lage en tjenestepakke, må vi gi både et grensesnitt og en implementeringsklasse.

Oppføring 4. Servicepakkegrensesnittet

 pakke com.javaworld.osgi.service; offentlig grensesnitt WhatIsOsgi {public Integer addNum (Integer x, Integer y); } 

Listing 4 er et enkelt grensesnitt. Den eneste metoden er en addNum () metode som vil gjøre det den innebærer: returner tillegget av to tall. Implementeringen vist i Listing 5 er like enkel, men legger til et par OSGi-spesifikke metoder.

Oppføring 5. Servicepakkeimplementeringen

 pakke com.javaworld.osgi.service; offentlig klasse WhatIsOsgiImpl implementerer WhatIsOsgi, BundleActivator {private ServiceReference ref; privat ServiceRegistration reg; @Override public Integer addNum (Integer x, Integer y) {return x + y; } @Override public void start (BundleContext context) kaster unntak {reg = context.registerService (WhatIsOsgi.class, new WhatIsOsgiImpl (), new Hashtable ()); ref = reg.getReference (); } @ Override public void stop (BundleContext context) kaster Unntak {reg.unregister (); }} 

La oss se nærmere på hva som skjer i Listing 5:

  1. offentlig klasse WhatIsOsgiImpl implementerer WhatIsOsgi, BundleActivator: Her implementerer vi grensesnittet vi opprettet. Merk at vi også implementerer BundleActivator grensesnitt, som vi gjorde med HeiJavaWorld eksempel. Sistnevnte er fordi denne pakken vil aktivere seg selv.
  2. privat ServiceReferanse ref; privat ServiceRegistration reg;: Dette er variabler for henholdsvis OSGi-registreringstjenesten og buntreferansen for denne tjenesten.
  3. public Integer addNum (Integer x, Integer y): Dette er den enkle implementeringen av add-metoden.
  4. offentlig ugyldig start (BundleContext context): Denne startmetoden er en del av BundleActivator grensesnitt, og utføres av containeren. I dette eksemplet får vi en referanse til OSGi-registreringstjenesten og bruker den på vår WhatIsOsgi grensesnitt og implementering. Det tomme Hashtable er for konfigurasjonsparametre, som vi ikke bruker her. Vi får også en referanse til tjenesten vi nettopp har opprettet.
  5. public void stop (BundleContext context): Her avregistrerer vi bare tjenesten. Denne enkle tjenesten klarer bare de bareste elementene i livssyklusen. Hovedformålet er å avsløre addNum metoden til OSGi-containeren.

OSGi-klienten

Neste gang, la oss skrive en klient som kan bruke tjenesten. Denne klienten vil igjen bruke BundleActivator grensesnitt. Det vil også legge til ServiceListener grensesnitt, som vist i liste 6.

Oppføring 6. OSGi-tjenesteklientpakken

 offentlig klasse OsgiClient implementerer BundleActivator, ServiceListener {private BundleContext ctx; privat ServiceReference-tjeneste; offentlig ugyldig start (BundleContext ctx) {this.ctx = ctx; prøv {ctx.addServiceListener (dette, "(objectclass =" + WhatIsOsgi.class.getName () + ")"); } catch (InvalidSyntaxException ise) {ise.printStackTrace (); }}} 

Oppføring 6 har en startmetode som vil legge til en tjenestelytter. Denne lytteren blir filtrert etter klassenavnet på tjenesten vi opprettet i Oppføring 5. Når tjenesten er oppdatert, vil den ringe serviceChanged () metode, som vist i liste 7.

Oppføring 7. serviceChanged method

 public void serviceChanged (ServiceEvent event) {int type = event.getType (); switch (type) {case (ServiceEvent.REGISTERED): serviceReference = event.getServiceReference (); Greeter-tjeneste = (Greeter) (ctx.getService (service)); System.out.println ("Legger til 10 og 100:" + service.addNum (10, 100)); gå i stykker; sak (ServiceEvent.UNREGISTERING): System.out.println ("Tjeneste uregistrert."); ctx.ungetService (event.getServiceReference ()); // Utgir referanse til service slik at det kan være GC'd break; standard: pause; }} 

Merk at serviceChanged metoden brukes til å bestemme hvilken hendelse som har skjedd for en tjeneste vi er interessert i. Tjenesten vil da svare som spesifisert. I dette tilfellet, når REGISTRERT hendelsen dukker opp, bruker vi addNum () metode.

OSGi-alternativet

Dette har vært en rask introduksjon til OSGi, Open Services Gateway Initiative. Som du har sett gjennom Knoplerfish-eksemplet, gir OSGi et kjøretidsmiljø der du kan definere modulære Java-komponenter (bunter). Det gir en definert livssyklus for hosting av pakker i klienten, og den støtter pakker som interagerer som klienter og tjenester i containeren. Alle disse funksjonene samlet gir et interessant alternativ til standard Java-driftstider og rammer, spesielt for mobil- og IoT-applikasjoner.

Til slutt, merk at den forrige artikkelen i “Hva er: Java” -serien introduserte Java Platform Module System, som tilbyr en annen tilnærming til den samme utfordringen med Java-modularitet.

Denne historien, "Hva er OSGi? En annen tilnærming til Java-modularitet" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found