מבוא ל- OSGi

1. הקדמה

למספר יישומי קריטי משימות ו- Java של Java יש כמה דרישות טכנולוגיות קשות.

חלקם צריכים לתמוך בפריסה חמה, כדי לא לשבש את השירותים הפועלים - ואחרים צריכים להיות מסוגלים לעבוד עם גרסאות שונות של אותה חבילה לצורך תמיכה במערכות מורשת חיצוניות.

ה OSGi פלטפורמות מייצגות פתרון בר-קיימא לתמיכה בדרישות מסוג זה.

ה יוזמת שער שירות פתוח הוא מפרט המגדיר מערכת רכיבים מבוססת Java. כרגע הוא מנוהל על ידי ברית OSGi, והגרסה הראשונה שלה מתחילה בשנת 1999.

מאז, זה הוכיח שהוא סטנדרט נהדר עבור מערכות רכיבים, והוא נמצא בשימוש נרחב בימינו. ה ליקוי חמה, למשל, הוא OSGiיישום מבוסס.

במאמר זה נחקור כמה תכונות בסיסיות של OSGi מינוף היישום המסופק על ידי אפאצ'י.

2. יסודות OSGi

ב- OSGi, רכיב יחיד נקרא צרור.

באופן הגיוני, חבילה היא פיסת פונקציונליות שיש לה מחזור חיים עצמאי - מה שאומר שניתן להתחיל, לעצור ולהסיר אותו באופן עצמאי.

מבחינה טכנית, צרור הוא רק קובץ צנצנת עם MANIFEST.MF קובץ המכיל כמה כותרות ספציפיות ל- OSGi.

ה OSGi פלטפורמה מספקת דרך לקבל התראות על חבילות שהופכות לזמינות או כאשר הן מוסרות מהפלטפורמה. זה יאפשר ללקוח שתוכנן כראוי להמשיך לעבוד, אולי עם פונקציונליות מושפלת, גם כאשר שירות שהוא תלוי בו, אינו זמין לרגע.

מסיבה זו, צרור צריך להכריז במפורש לאילו חבילות הוא זקוק לגישה ו OSGi הפלטפורמה תפעיל אותה רק אם התלות זמינה בחבילה עצמה או בצרורות אחרים שכבר הותקנו בפלטפורמה.

3. קבלת הכלים

נתחיל את המסע שלנו פנימה OSGi על ידי הורדת הגרסה האחרונה של אפאצ'י קראף מהקישור הזה. אפאצ'י קראף היא פלטפורמה הפועלת OSGi-יישומים מבוססים; זה מבוסס על אפאצ'ייישום של OSGi מפרט שנקרא אפאצ'י פליקס.

קראף מציע כמה תכונות שימושיות בנוסף פליקס שיעזור לנו להכיר OSGi, למשל, ממשק שורת פקודה שיאפשר לנו אינטראקציה עם הפלטפורמה.

להתקין קראף, תוכלו לעקוב אחר הוראות ההתקנה מהתיעוד הרשמי.

4. נקודת כניסה צרורה

כדי לבצע יישום בסביבת OSGi, עלינו לארוז אותו כ- OSGi צרור והגדר את נקודת הכניסה ליישום, וזה לא הרגיל ראשי ריק סטטי ציבורי (מחרוזת [] טוענת) שיטה.

אז נתחיל בבניית OSGi- מבוסס יישום "שלום עולם".

אנו מתחילים להגדיר תלות פשוטה בליבה ממשק API של OSGi:

 org.osgi org.osgi.core 6.0.0 מסופק 

התלות מוכרזת כ בתנאי כי זה יהיה זמין ב OSGi זמן ריצה, והצרור לא צריך להטמיע אותו.

בוא עכשיו נכתוב את הפשט שלום עולם מעמד:

מחלקה ציבורית HelloWorld מיישמת את BundleActivator {התחלת הריק הציבורי (BundleContext ctx) {System.out.println ("שלום עולם."); } עצירה בטלנית ציבורית (BundleContext bundleContext) {System.out.println ("להתראות עולם."); }}

BundleActivator הוא ממשק המסופק על ידי OSGi כי יש ליישם על ידי שיעורים המהווים נקודות כניסה לחבילה.

ה הַתחָלָה() השיטה מופעלת על ידי OSGi פלטפורמה כאשר החבילה המכילה מחלקה זו מופעלת. מצד שני תפסיק() מופעל לפני רגע לפני עצירת הצרור.

בואו נזכור שכל חבילה יכולה לכלול לכל היותר אחת BundleActivator. ה BundleContext האובייקט המסופק לשתי השיטות מאפשר אינטראקציה עם OSGi זמן ריצה. נחזור לזה בקרוב.

5. בניית צרור

בואו לשנות את pom.xml ולהפוך אותו לחבילת OSGi בפועל.

קודם כל, עלינו לציין במפורש שאנחנו הולכים לבנות צרור, ולא צנצנת:

חבילה

ואז אנו ממנפים את תוסף maven-bundle, באדיבות ה- אפאצ'י פליקס קהילה, לארוז את שלום עולם כיתה כ OSGi חבילה:

 org.apache.felix תוסף maven-bundle 3.3.0 נכון $ {pom.groupId}. $ {pom.artifactId} $ {pom.name} $ {pom.version} com.baeldung.osgi.sample.activator.HelloWorld com.baeldung.osgi.sample.activator 

בסעיף ההוראות אנו מציינים את ערכי ה- OSGi כותרות שאנחנו רוצים לכלול בקובץ MANIFEST של החבילה.

Bundle-Activator הוא השם המלא של ה- BundleActivator יישום שישמש להפעלה ולעצירת החבילה, והוא מתייחס לשיעור שכתבנו זה עתה.

חבילה פרטית אינו כותרת של OSGi, אך הוא משמש להגדרת התוסף לכלול את החבילה בצרור אך לא להפוך אותה לזמינה עבור אחרים. כעת נוכל לבנות את החבילה עם הפקודה הרגילה mvn נקי להתקין.

6. התקנה והפעלת החבילה

בואו נתחיל קראף על ידי ביצוע הפקודה:

/ bin / karaf start

איפה היא התיקיה שבה קראף מותקן. כאשר הפקודה של קראף המסוף מופיע שנוכל לבצע את הפקודה הבאה להתקנת החבילה:

> צרור: התקן mvn: com.baeldung / osgi-intro-sample-activator / 1.0-SNAPSHOT מזהה חבילה: 63

זה מורה לכארף לטעון את החבילה ממאגר Maven המקומי.

בתמורה מדפיס קאראף את המזהה המספרי שהוקצה לחבילה, תלוי במספר החבילות שכבר הותקנו ועשוי להשתנות. החבילה מותקנת כעת, כעת אנו יכולים להפעיל אותה עם הפקודה הבאה:

> צרור: התחל 63 שלום עולם

"שלום עולם" מופיע מיד ברגע שהחבילה מתחילה. כעת אנו יכולים לעצור ולהסיר את ההתקנה עם:

> צרור: עצור 63> צרור: הסר 63

"להתראות עולם" מופיע בקונסולה, בהתאם לקוד שב- תפסיק() שיטה.

7. שירות OSGi

בואו נמשיך לכתוב פשוט OSGi שירות, ממשק החושף שיטה לברך אנשים:

חבילה com.baeldung.osgi.sample.service.definition; ממשק ציבורי גרטר {מחרוזת ציבורית sayHiTo (שם מחרוזת); }

בוא נכתוב יישום של זה שהוא BundleActivator גם כך נוכל ליצור את השירות מיידי ולרשום אותו בפלטפורמה עם תחילת החבילה:

חבילה com.baeldung.osgi.sample.service.implementation; הכיתה הציבורית GreeterImpl מיישמת את Greeter, BundleActivator {סימוכין של שירות פרק שירות; רישום שירות רישום פרטי; @ מעקף ציבורי ציבורי sayHiTo (שם מחרוזת) {להחזיר "שלום" + שם; } התחלה בטלנית ציבורית של @Override (הקשר BundleContext) זורקת חריג {System.out.println ("שירות רישום."); רישום = context.registerService (Greeter.class, GreeterImpl חדש (), Hashtable חדש ()); הפניה = רישום .getReference (); } @Override עצירה בטלנית ציבורית (הקשר BundleContext) זורקת חריגה {System.out.println ("שירות ביטול רישום."); registration.unregister (); }}

אנו משתמשים ב- BundleContext כאמצעי לבקש את OSGi פלטפורמה לרישום מופע חדש של השירות.

עלינו לספק גם את סוג השירות ומפה של פרמטרי התצורה האפשריים, שאינם נחוצים בתרחיש הפשוט שלנו. בואו נמשיך עכשיו עם התצורה של ה- תוסף maven-bundle:

 org.apache.felix maven-bundle-plugin נכון $ {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 

ראוי לציין שרק את com.baeldung.osgi.sample.service.definition החבילה יוצאה הפעם דרך חבילת ייצוא כּוֹתֶרֶת.

תודה על זה, OSGi יאפשר לחבילות אחרות להפעיל רק את השיטות שצוינו בממשק השירות. חֲבִילָה com.baeldung.osgi.sample.service.implementation מסומן כפרטי, כך שאף חבילה אחרת לא תוכל לגשת ישירות לחברי היישום.

8. לקוח OSGi

בואו עכשיו נכתוב את הלקוח. זה פשוט מחפש את השירות בעת ההפעלה ומפעיל אותו:

לקוח בכיתה ציבורית מיישם את BundleActivator, ServiceListener {}

בואו ליישם את התחלת BundleActivator () שיטה:

BundleContext ctx פרטי; שירות פרטי הפניה שירות הפניה; התחלה בטלנית ציבורית (BundleContext ctx) {this.ctx = ctx; נסה את {ctx.addServiceListener (זה, "(objectclass =" + Greeter.class.getName () + ")"); } לתפוס (InvalidSyntaxException האי) {ise.printStackTrace (); }}

ה addServiceListener () השיטה מאפשרת ללקוח לבקש מהפלטפורמה לשלוח התראות על השירות התואם את הביטוי שסופק.

הביטוי משתמש בתחביר הדומה לזה של ה- LDAP, ובמקרה שלנו אנו מבקשים התראות על א גרטר שֵׁרוּת.

בואו נמשיך לשיטת החזרה להתקשרות:

public void serviceChanged (ServiceEvent serviceEvent) {int type = serviceEvent.getType (); switch (type) {case (ServiceEvent.REGISTERED): System.out.println ("הודעה על שירות רשום."); serviceReference = serviceEvent .getServiceReference (); שירות Greeter = (Greeter) (ctx.getService (serviceReference)); System.out.println (service.sayHiTo ("ג'ון")); לשבור; מקרה (ServiceEvent.UNREGISTERING): System.out.println ("הודעת השירות לא רשומה."); ctx.ungetService (serviceEvent.getServiceReference ()); לשבור; ברירת מחדל: הפסקה; }}

כאשר שינוי כלשהו הכרוך ב- גרטר השירות מתרחש, מקבלים הודעה על השיטה.

כאשר השירות רשום לפלטפורמה, אנו מקבלים התייחסות אליו, אנו מאחסנים אותו באופן מקומי ואז משתמשים בו בכדי לרכוש את אובייקט השירות ולהפעיל אותו.

כאשר השרת אינו מאוחר יותר רשום, אנו משתמשים בהתייחסות המאוחסנת בעבר כדי לבטל אותו, כלומר אנו אומרים לפלטפורמה שאנחנו לא מתכוונים להשתמש בה יותר.

עכשיו אנחנו רק צריכים לכתוב את תפסיק() שיטה:

עצירה בטלנית ציבורית (BundleContext bundleContext) {if (serviceReference! = null) {ctx.ungetService (serviceReference); }}

שוב, אנו מבטלים את השירות בכדי לכסות את המקרה בו הלקוח נעצר לפני הפסקת השירות. בואו נסתכל סופית על התלות במערכת pom.xml:

 com.baeldung osgi-intro-sample-service 1.0-SNAPSHOT סיפק org.osgi org.osgi.core 6.0.0 

9. לקוח ושירות

בואו נתקין כעת את חבילות הלקוחות והשירותים בכרף על ידי ביצוע:

> התקן mvn: com.baeldung / osgi-intro-sample-service / 1.0-SNAPSHOT Bundle ID: 64> להתקין mvn: com.baeldung / osgi-intro-sample-client / 1.0-SNAPSHOT Bundle ID: 65

זכור תמיד שמספרי המזהים המוקצים לכל חבילה עשויים להשתנות.

נתחיל כעת עם חבילת הלקוחות:

> התחל 65

לכן שום דבר לא קורה מכיוון שהלקוח פעיל והוא ממתין לשירות שנוכל להתחיל עם:

> התחל 64 רישום שירות. שירות רשום. שלום ג'ון

מה שקורה הוא שברגע שמתחיל BundleActivator של השירות, השירות נרשם לפלטפורמה. זה, בתורו, מודיע ללקוח שהשירות שהוא חיכה לו זמין.

לאחר מכן הלקוח מקבל התייחסות לשירות ומשתמש בו כדי להפעיל את היישום שמועבר באמצעות חבילת השירות.

10. מסקנה

במאמר זה בחנו את התכונות החיוניות של OSGi בדוגמה פשוטה לכך שמספיק כדי להבין את הפוטנציאל של OSGi.

לסיכום, בכל פעם שעלינו להבטיח כי יש לעדכן יישום בודד ללא כל שירות, OSGi יכול להיות פיתרון בר-קיימא.

את הקוד לפוסט זה ניתן למצוא ב- GitHub.