Προγραμματισμός

Τι είναι το OSGi; Μια διαφορετική προσέγγιση για το Java modularity

Το OSGi διευκολύνει τη δημιουργία και τη διαχείριση αρθρωτών στοιχείων Java (ονομάζεται δέσμες) που μπορεί να αναπτυχθεί σε κοντέινερ. Ως προγραμματιστής, χρησιμοποιείτε τις προδιαγραφές OSGi και τα εργαλεία για να δημιουργήσετε ένα ή περισσότερα πακέτα. Το OSGi καθορίζει τον κύκλο ζωής για αυτά τα πακέτα. Τους φιλοξενεί και υποστηρίζει τις αλληλεπιδράσεις τους σε ένα κοντέινερ. Μπορείτε να θεωρήσετε ένα κοντέινερ OSGi ως περίπου ανάλογο με ένα JVM, με πρόσθετες δυνάμεις. Ομοίως, σκεφτείτε πακέτα ως εφαρμογές Java με μοναδικές δυνατότητες. Τα πακέτα εκτελούνται μέσα στο κοντέινερ OSGi ως στοιχεία πελάτη και διακομιστή.

Η συμμαχία OSGi

Το OSGi ξεκίνησε το 1999 και, σε αντίθεση με πολλές άλλες προδιαγραφές, το πρότυπο δεν διαχειρίζεται η Oracle, η Java Community Process ή το Eclipse Foundation. Αντιθέτως, το διαχειρίζεται η συμμαχία OSGi.

Πώς είναι διαφορετικό το OSGi

Η φιλοσοφία του OSGi διαφέρει από αυτήν των άλλων πλαισίων που βασίζονται σε Java, κυρίως το Spring. Στο OSGi, πολλές εφαρμογές μπορούν να υπάρχουν εντός του ίδιου κοντέινερ: το Περιβάλλον χρόνου εκτέλεσης πακέτων OSGi. Το δοχείο διασφαλίζει ότι κάθε στοιχείο είναι επαρκώς απομονωμένο και έχει επίσης πρόσβαση σε οποιεσδήποτε εξαρτήσεις απαιτεί. Το OSGi μπορεί να υποστηρίξει την έγχυση εξάρτησης, η οποία τυποποιείται από το έργο Aries Blueprint. Εκτός από την παροχή του κοντέινερ αντιστροφής ελέγχου (IoC) του OSGi, ο Aries υποστηρίζει τυπικά πλαίσια Java όπως το Java Persistence API (JPA).

Στο OSGi, τα πακέτα μπορούν να εκθέσουν υπηρεσίες που χρησιμοποιούν άλλα πακέτα. Ένα πακέτο μπορεί επίσης να δηλώσει μια έκδοση και μπορεί να καθορίσει από ποια άλλα πακέτα εξαρτάται. Στη συνέχεια, ο χρόνος εκτέλεσης φορτώνει αυτόματα όλες τις δέσμες του κατά σειρά εξάρτησης. Στο OSGi, πολλαπλές εκδόσεις του ίδιου πακέτου μπορούν να υπάρχουν δίπλα-δίπλα, αν αυτό απαιτείται από τις εξαρτήσεις της δέσμης.

OSGi στο Eclipse IDE και Equinox

Το OSGi υπάρχει σε κάποια μορφή εδώ και μερικές δεκαετίες. Χρησιμοποιείται για πολλές γνωστές εφαρμογές, από ενσωματωμένες φορητές συσκευές έως διακομιστές εφαρμογών και IDE.

Το δημοφιλές Eclipse IDE είναι χτισμένο πάνω από OSGi. Η εφαρμογή του κοντέινερ OSGi από την Eclipse ονομάζεται Equinox. Είναι ένα εξαιρετικό παράδειγμα για την κατανόηση του OSGi. Το να βασίζεσαι στο OSGi σημαίνει ότι το Equinox είναι μια αρθρωτή πλατφόρμα. Φιλοξενεί μια ποικιλία υπηρεσιών που οι προγραμματιστές μπορούν να προσθέσουν κατά βούληση. Καθένα από αυτά προσφέρει μια δυνατότητα που μπορεί να χρειαστεί ένας προγραμματιστής στο IDE του. Μπορείτε να προσθέσετε προγράμματα επεξεργασίας για Java και JavaScript, διακομιστή εφαρμογών και εφαρμογή σύνδεσης βάσης δεδομένων. Κάθε ένα από αυτά εφαρμόζεται ως δέσμη OSGi που προστίθεται στο κοντέινερ και μπορεί να αλληλεπιδράσει με άλλες υπηρεσίες στο κοντέινερ.

Πρόσφατα, υπήρξε μια αύξηση ενδιαφέροντος για τη χρήση του OSGi για το Διαδίκτυο των πραγμάτων (IoT). Το OSGi είναι μια φυσική εφαρμογή για αυτόν τον τύπο ανάπτυξης, ο οποίος διαθέτει μια ποικιλία στοιχείων λογισμικού που εκτελούνται δίπλα-δίπλα σε συσκευές, χωρίς απαραίτητα να γνωρίζουν ο ένας τον άλλον. Ένα κοντέινερ OSGi παρέχει έναν απλό και τυποποιημένο τρόπο φιλοξενίας αυτών των δυναμικών στοιχείων λογισμικού.

Χρήση OSGi σε έργο Java: Knoplerfish OSGi

Θα επεξεργαστούμε ένα παράδειγμα εφαρμογής που θα κάνει τις έννοιες OSGi πιο συγκεκριμένες. Το παράδειγμά μας βασίζεται στον χρόνο εκτέλεσης Knoplerfish OSGi, ο οποίος χρησιμοποιείται σε πολλές εφαρμογές παραγωγής. Το Knoplerfish περιλαμβάνει μια διεπαφή GUI και γραμμής εντολών (CLI) για τη διαχείριση του κοντέινερ OSGi και των πακέτων του.

Το πρώτο πράγμα που θα κάνετε είναι να κατεβάσετε το Knoplerfish. Η τρέχουσα έκδοση κατά τη στιγμή αυτής της γραφής είναι το Knoplerfish OSGi 6.1.3. Μπορείτε να αντικαταστήσετε αυτήν την έκδοση με ό, τι είναι πιο πρόσφατο όταν διαβάζετε αυτό το άρθρο.

Αφού κατεβάσετε και εγκαταστήσετε το Knoplerfish, χρησιμοποιήστε το CLI για να μεταβείτε στον κατάλογο στον οποίο πραγματοποιήσατε λήψη του αρχείου JAR και εισαγάγετε: java -jar framework.jar. Αυτό θα τρέξει το εκτελέσιμο JAR και θα πρέπει να σας υποδεχτεί με ένα παράθυρο GUI.

Το Knoplerfish OSGi GUI

Το GUI του Knoplerfish OSGi μπορεί να φαίνεται αρχικά συντριπτικό, αλλά τα βασικά είναι απλά:

  • Στο επάνω μέρος της οθόνης βρίσκεται το μενού.
  • Στα αριστερά βρίσκεται το σύνολο των πακέτων που έχουν φορτωθεί στο χρόνο εκτέλεσης.
  • Στα δεξιά βρίσκεται ένα παράθυρο πληροφοριών.
  • Στο κάτω μέρος υπάρχει μια κονσόλα εξόδου κειμένου.
  • Στο κάτω μέρος υπάρχει μια κονσόλα εισόδου.
Μάθιου Τάισον

Τύπος βοήθεια στην κονσόλα εισόδου εάν θέλετε να δείτε τις επιλογές βοήθειας.

Πριν προχωρήσουμε στο παράδειγμα, ρίξτε μια ματιά στο σύνολο των πακέτων που εκτελούνται. Θα δείτε ένα πακέτο που ονομάζεται Διακομιστής HTTP, που σημαίνει ότι έχει ολοκληρωθεί μια δέσμη με διακομιστή HTTP. Μεταβείτε στο πρόγραμμα περιήγησής σας και δείτε το // localhost: 8080. Σίγουρα, θα δείτε μια ιστοσελίδα Knoplerfish.

Το πακέτο «Hello JavaWorld»

Ας χρησιμοποιήσουμε το χρόνο εκτέλεσης OSGi για να δημιουργήσουμε ένα απλό πακέτο, το οποίο θα καλέσω Γεια σας JavaWorld. Αυτό το πακέτο εξάγει ένα μήνυμα στην κονσόλα.

Στην Λίστα 1, χρησιμοποιούμε το Maven για να δημιουργήσουμε το πακέτο. Έχει μόνο μία εξάρτηση, η οποία παρέχεται από τη συμμαχία OSGi.

Λίστα 1. Εξάρτηση OSGi στο Maven POM

   org.osgi org.osgi.core 

Τώρα, θα χρησιμοποιήσουμε επίσης ένα πρόσθετο, με ευγένεια του έργου Apache Felix. Αυτή η προσθήκη φροντίζει για τη συσκευασία της εφαρμογής ως δέσμη OSGi για χρήση. Η λίστα 2 δείχνει τη διαμόρφωση που θα χρησιμοποιήσουμε.

Λίστα 2. Πρόσθετο OSGi Felix στο Maven POM

   org.apache.felix maven-bundle-plugin true org.javaworld.osgi org.javaworld.osgi.Γεια σας 

Τώρα μπορούμε να ρίξουμε μια ματιά στην απλή τάξη που θα παράγει ένα "Γεια".

Λίστα 3. Γεια σας JavaWorld OSGi πακέτο

 πακέτο com.javaworld.osgi; εισαγωγή org.osgi.framework.BundleActivator; εισαγωγή org.osgi.framework.BundleContext; δημόσια τάξη HelloJavaWorld εφαρμόζει το BundleActivator {public void start (BundleContext ctx) {System.out.println ("Hello JavaWorld."); } δημόσια στάση κενού (BundleContext bundleContext) {}} 

Δημιουργήστε το πακέτο μεταβαίνοντας στη γραμμή εντολών και πληκτρολογώντας καθαρή εγκατάσταση mvn. Αυτό θα εξάγει ένα αρχείο JAR που περιέχει το πακέτο. Τώρα, πηγαίνετε στο Αρχείο μενού στο Knoplerfish GUI και επιλέξτε Προσθήκη πακέτου. Αυτό θα παρέχει ένα πρόγραμμα περιήγησης αρχείων. Βρείτε το JAR που μόλις δημιουργήσαμε και επιλέξτε το.

Διαχείριση πακέτων OSGi στο κοντέινερ

Στο παράθυρο εξόδου του Knoplerfish UI, θα δείτε το μήνυμα "Γεια σας, JavaWorld". Κάντε κλικ στο πακέτο στο Knoplerfish GUI και μπορείτε να δείτε το αναγνωριστικό που του έχει ανατεθεί το κοντέινερ. Όταν είστε έτοιμοι να σταματήσετε το πακέτο, μπορείτε να κάνετε κλικ στο στοιχείο Διακοπή μενού. Ένας άλλος τρόπος είναι να μπείτε διακοπή [αριθμός δέσμης] στη γραμμή εντολών. Μπορείτε να διαχειριστείτε πακέτα στο κοντέινερ χρησιμοποιώντας είτε το GUI είτε τη γραμμή εντολών.

Τώρα έχετε μια ιδέα για το πώς λειτουργεί ένα απλό πακέτο στο κοντέινερ OSGi. Οπουδήποτε υπάρχει κοντέινερ OSGi, θα βρείτε την ίδια απλότητα στην εκκίνηση και τη διακοπή πακέτων. Το OSGi δημιουργεί ένα περιβάλλον και κύκλο ζωής για το πακέτο.

Αλληλεπιδράσεις πακέτων: Υπηρεσίες και πελάτες

Στη συνέχεια, θα δούμε πώς επικοινωνούν τα πακέτα μεταξύ τους.

Το πρώτο πράγμα που θα κάνουμε είναι να δημιουργήσουμε ένα δέσμη υπηρεσιών. Ένα πακέτο υπηρεσιών είναι ανάλογο με ένα φασόλι συνεδρίας EJB: Παρέχει ένα στοιχείο που μπορεί να προσεγγιστεί από άλλα πακέτα μέσω απομακρυσμένης διεπαφής. Για να δημιουργήσουμε ένα πακέτο υπηρεσιών, πρέπει να παρέχουμε μια διεπαφή και μια κλάση υλοποίησης.

Λίστα 4. Η διεπαφή δέσμης υπηρεσιών

 πακέτο com.javaworld.osgi.service; δημόσια διεπαφή WhatIsOsgi {public Integer addNum (Integer x, Integer y); } 

Η λίστα 4 είναι μια απλή διεπαφή. Η μόνη μέθοδος είναι ένα addNum () μέθοδος που θα κάνει αυτό που συνεπάγεται: επιστρέψτε την προσθήκη δύο αριθμών. Η εφαρμογή που εμφανίζεται στην καταχώριση 5 είναι εξίσου απλή, αλλά προσθέτει μερικές μεθόδους ειδικές για OSGi.

Λίστα 5. Η υλοποίηση του πακέτου υπηρεσιών

 πακέτο com.javaworld.osgi.service; δημόσια τάξη WhatIsOsgiImpl εφαρμόζει WhatIsOsgi, BundleActivator {private ServiceReference ref; ιδιωτική υπηρεσία Εγγραφή εγγραφής; @ Override public Integer addNum (Integer x, Integer y) {return x + y; } @Override public void start (πλαίσιο BundleContext) ρίχνει την Εξαίρεση {reg = konteks.registerService (WhatIsOsgi.class, νέο WhatIsOsgiImpl (), νέο Hashtable ()); ref = reg.getReference (); } @Override public void stop (πλαίσιο BundleContext) ρίχνει την Εξαίρεση {reg.unregister (); }} 

Ας δούμε πιο κοντά τι συμβαίνει στην Καταχώριση 5:

  1. δημόσια τάξη WhatIsOsgiImpl εφαρμόζει το WhatIsOsgi, BundleActivator: Εδώ εφαρμόζουμε τη διεπαφή που δημιουργήσαμε. Σημειώστε ότι εφαρμόζουμε επίσης το BundleActivator διεπαφή, όπως κάναμε με το Γεια σου JavaWorld παράδειγμα. Το τελευταίο είναι επειδή αυτό το πακέτο θα ενεργοποιηθεί.
  2. ιδιωτική υπηρεσία ServiceReference ref; ιδιωτικό ServiceRegistration reg;: Αυτές είναι μεταβλητές για την υπηρεσία εγγραφής OSGi και την αναφορά δέσμης για αυτήν την υπηρεσία, αντίστοιχα.
  3. public Integer addNum (Integer x, Integer y): Αυτή είναι η απλή εφαρμογή της μεθόδου προσθήκης.
  4. δημόσια άκυρη εκκίνηση (πλαίσιο BundleContext): Αυτή η μέθοδος εκκίνησης είναι μέρος του BundleActivator διεπαφή και εκτελείται από το κοντέινερ. Σε αυτό το παράδειγμα, λαμβάνουμε μια αναφορά στην υπηρεσία εγγραφής OSGi και την εφαρμόζουμε στο δικό μας WhatIsOsgi διεπαφή και εφαρμογή. Το άδειο Hashtable είναι για παραμέτρους ρυθμίσεων, τις οποίες δεν χρησιμοποιούμε εδώ. Παίρνουμε επίσης μια αναφορά στην υπηρεσία που μόλις δημιουργήσαμε.
  5. δημόσια κενή στάση (πλαίσιο BundleContext): Εδώ, καταργούμε απλώς την υπηρεσία. Αυτή η απλή υπηρεσία διαχειρίζεται μόνο τα λιγότερα στοιχεία του κύκλου ζωής της. Ο κύριος σκοπός του είναι να εκθέσει το addNum μέθοδο στο κοντέινερ OSGi.

Ο πελάτης OSGi

Στη συνέχεια, ας γράψουμε έναν πελάτη που μπορεί να χρησιμοποιήσει την υπηρεσία. Αυτός ο πελάτης θα κάνει ξανά χρήση του BundleActivator διεπαφή. Θα προσθέσει επίσης το ServiceListener διεπαφή, όπως φαίνεται στην καταχώριση 6.

Λίστα 6. Το πακέτο πελατών της υπηρεσίας OSGi

 δημόσια τάξη OsgiClient εφαρμόζει το BundleActivator, ServiceListener {private BundleContext ctx; ιδιωτική υπηρεσία δημόσια άκυρη εκκίνηση (BundleContext ctx) {this.ctx = ctx; δοκιμάστε το {ctx.addServiceListener (this, "(objectclass =" + WhatIsOsgi.class.getName () + ")"); } catch (InvalidSyntaxException ise) {ise.printStackTrace (); }}} 

Η λίστα 6 έχει μια μέθοδο εκκίνησης που θα προσθέσει έναν ακροατή υπηρεσιών. Αυτός ο ακροατής φιλτράρεται από το όνομα κλάσης της υπηρεσίας που δημιουργήσαμε στην Λίστα 5. Όταν η υπηρεσία ενημερωθεί, θα καλέσει το υπηρεσίαΑλλαγή () μέθοδο, όπως φαίνεται στην καταχώριση 7.

Λίστα 7. Μέθοδος serviceChanged

 public void serviceChanged (ServiceEvent event) {int type = event.getType (); διακόπτης (τύπος) {case (ServiceEvent.REGISTERED): serviceReference = event.getServiceReference (); Υπηρεσία Greeter = (Greeter) (ctx.getService (service)); System.out.println ("Προσθήκη 10 και 100:" + service.addNum (10, 100)); Διακοπή; υπόθεση (ServiceEvent.UNREGISTERING): System.out.println ("Μη καταχωρισμένη υπηρεσία."); ctx.ungetService (event.getServiceReference ()); // Απελευθερώνει αναφορά στην υπηρεσία, ώστε να μπορεί να σπάσει το GC. προεπιλογή: break; }} 

Σημειώστε ότι το υπηρεσίαΑλλαγή χρησιμοποιείται μέθοδος για τον προσδιορισμό του συμβάντος για μια υπηρεσία που μας ενδιαφέρει. Στη συνέχεια, η υπηρεσία θα ανταποκριθεί όπως ορίζεται. Σε αυτήν την περίπτωση, όταν το ΕΓΓΕΓΡΑΜΜΕΝΟΣ εμφανίζεται το συμβάν, χρησιμοποιούμε το addNum () μέθοδος.

Η εναλλακτική λύση OSGi

Αυτή ήταν μια γρήγορη εισαγωγή στο OSGi, το Open Services Gateway Initiative. Όπως έχετε δει στο παράδειγμα Knoplerfish, το OSGi παρέχει ένα περιβάλλον χρόνου εκτέλεσης όπου μπορείτε να ορίσετε αρθρωτά στοιχεία Java (πακέτα). Παρέχει έναν καθορισμένο κύκλο ζωής για τη φιλοξενία πακέτων στον πελάτη και υποστηρίζει πακέτα που αλληλεπιδρούν ως πελάτες και υπηρεσίες εντός του κοντέινερ. Όλες αυτές οι δυνατότητες από κοινού παρέχουν μια ενδιαφέρουσα εναλλακτική λύση για τους τυπικούς χρόνους εκτέλεσης και τα πλαίσια Java, ειδικά για εφαρμογές για κινητά και IoT.

Τέλος, σημειώστε ότι το προηγούμενο άρθρο στη σειρά «Τι είναι: Java» εισήγαγε το Java Platform Module System, το οποίο προσφέρει μια διαφορετική προσέγγιση στην ίδια πρόκληση της Java modularity.

Αυτή η ιστορία, "Τι είναι το OSGi; Μια διαφορετική προσέγγιση για το Java modularity" δημοσιεύθηκε αρχικά από το JavaWorld.