סקירת JNDI, חלק 3: JNDI מתקדם

אני צריך לכסות הרבה אדמות החודש, אז אני אשאיר את המוך ואחתוך ממש לנקודות הכדור. ראשית, ממשק ה- Java Naming and Directory ממלא תפקיד חשוב בכמה טכנולוגיות Java. אנו נסתכל על תפקיד זה כדי להבין טוב יותר את מעמדה האסטרטגי של JNDI בתמונת ה- Java הכוללת. בשלב הבא, מתוך הכרה בצורך שלך בשירות JNDI עובד לעבוד איתו, אציג בפניך יישום LDAP נייד זמין בחינם, ואלמד אותך כיצד להתחבר לספק שירותי JNDI ולהשתמש בו. לסיום, אקח אותך לבדיקה מקרוב של אובייקטים מחייבים לערכים ב- JNDI.

תיבת טקסט:

TEXTBOX_HEAD: סקירה על JNDI: קרא את כל הסדרה!

  • חלק 1. מבוא לשירותי שמות

  • חלק 2. השתמש בשירותי ספריית JNDI כדי לנהל טוב יותר את היישומים המופצים שלך

  • חלק 3. השתמש ב- JNDI לאחסון אובייקטים של היישום המבוזר שלך

  • חלק 4. משוך יחד את מה שלמדת עם יישום התומך ב- JNDI

: END_TEXTBOX

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

נתחיל במבט על האופן שבו JNDI מופיע בטכנולוגיות Java אחרות.

JNDI בכל מקום

JNDI ממלא תפקיד במספר טכנולוגיות Java. בואו ניקח בחשבון שלוש מהן: JDBC (חבילת קישוריות Java Database), JMS (Java Messaging Service) ו- EJB (Enterprise JavaBeans).

JDBC היא טכנולוגיית Java לבסיסי נתונים יחסיים. JNDI הופיע לראשונה בחבילה האופציונלית של JDBC 2.0 (ראה משאבים) יחד עם DataSourceהממשק. DataSourceלמשל, כפי ששמו מרמז, מהווה מקור הנתונים - לעתים קרובות ממסד נתונים אך לא תמיד. DataSourceמאחסן מידע למשל על מקור הנתונים - כגון שמו, לנהג עומס ושימוש, ומיקומו - ומאפשר בקשה למתן חיבור למקור נתונים מבלי להתייחס הפרטים הבסיסיים. מפרט JDBC ממליץ להשתמש ב- JNDI לאחסון DataSourceאובייקטים.

JMS היא טכנולוגיית Java להעברת הודעות. מפרט JMS מתאר אובייקטים מנוהלים - אובייקטים המכילים מידע על תצורת JMS ומשמשים את לקוחות JMS לאיתור תורי ונושאים ספציפיים. כמו במקרה של JDBC, המפרט ממליץ לאתר אובייקטים מנוהלים על ידי JMS באמצעות JNDI.

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

מה מביא JNDI לשולחן שגורם לו להיות כל כך מוערך?

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

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

הנקודה של הספק

כדי להשתמש ב- JNDI, אתה זקוק לשירות שמות וספריות וספק שירותי JNDI. Sun מספקת מספר ספקים של שירותי שמות וספריות נפוצים (שמות COS, NIS, הרישום של RMI, LDAP ועוד). התמקמתי ב- LDAP.

ל- LDAP (Lightweight Directory Access Protocol) יש את היתרונות הכפולים של הטמעה נרחבת (הן בצורות מסחריות והן בחינמיות) וקל לשימוש סביר. התכונות שלו נתמכות היטב גם על ידי ספק שירותי ה- LDAP של Sun ו- JNDI.

מכיוון שהשגה ותצורה של שרת LDAP אינו ממש נושא ג'אווה, אני רק אביא אותך לכיוון הנכון ואספק לך הפניות למשאבי אינטרנט.

קיימות יישומי LDAP רבים. רבים מהם הם מוצרים מסחריים כגון שרת המדריך Netscape וספריה Secure Way של יבמ. חלקם ארוזים כחלק מהיצע גדול יותר (Active Directory של מיקרוסופט הוא חלק מ- Windows 2000). אם יש לך גישה ליישום כזה, תוכל לדלג על רוב החלק הזה. אחרת, אני מתאר את OpenLDAP - יישום זמין באופן חופשי של LDAP המבוסס על יישום הייחוס של אוניברסיטת מישיגן - כמו גם את ההתקנה והתצורה שלו.

OpenLDAP זמין מקרן OpenLDAP (ראה משאבים). הרישיון שלה מבוסס על "הרישיון האמנותי" של פרל, כלומר OpenLDAP היא תוכנה חינמית (או קוד פתוח). קבצים בינאריים ארוזים מראש זמינים לטעמים שונים של לינוקס (דביאן, רד האט) וכן BSD יוניקס. העבודות מתבצעות ביציאה ל- Windows NT.

אם אתה מתכנן להתקין את OpenLDAP, עליך לקרוא את המדריך למנהל SLAPD ו- SLURPD (slapd הוא שמו של ההפעלה של שרת LDAP ו- slurpd הוא שמו של שרת שכפול LDAP; ראה משאבים למיקום).

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

התחברות להקשר JNDI

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

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

השגת הקשר הראשוני דורשת שלושה שלבים:

  1. ראשית בחר ספק שירות. אם אתה מתכוון להשתמש ב- OpenLDAP או ביישום LDAP אחר, Sun מספקת לספק שירותי LDAP ייחוס (ראה משאבים). הוסף את שם ספק השירות לקבוצת מאפייני הסביבה (המאוחסנים Hashtableבמקרה):

    Hashtable hashtableEnvironment = חדש Hashtable (); hashtableEnvironment.put (Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
  2. הוסף מידע נוסף שספק השירות דורש. עבור LDAP, זה כולל את כתובת ה- URL שמזהה את השירות, את הקשר הבסיס ואת השם והסיסמה שאליהם אתה צריך להתחבר:

    // השירות: ldap: // localhost: 389 / // הקשר השורש: dc = etcee, dc = com hashtableEnvironment.put (Context.PROVIDER_URL, "ldap: // localhost: 389 / dc = etcee, dc = com "); hashtableEnvironment.put (Context.SECURITY_PRINCIPAL, "שם"); hashtableEnvironment.put (Context.SECURITY_CREDENTIALS, "סיסמה");
  3. לבסוף, קבל את ההקשר הראשוני. אם אתה רק מתכוון לבצע פעולות שמות, תזדקק רק Contextלמופע. אם בכוונתך לבצע גם פעולת ספריה, תזדקק DirContextלמופע במקום. לא כל הספקים מספקים את שניהם:

     הקשר הקשר = InitialContext חדש (hashtableEnvironment); 

    אוֹ:

     DirContext dircontext = חדש InitialDirContext (hashtableEnvironment); 

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

לעבוד עם חפצים

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

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

 context.bind ("שם", אובייקט) 

The bind() operation binds a name to a Java object. The syntax of the command is reminiscent of RMI, but the semantics are not as clearly defined. It's permissible for the bind() operation to store either a snapshot of the object or a reference to a "live" object, for example.

Be aware that the bind() operation throws a NamingException if an exception occurs during the execution of the operation.

Now let's take a look at the bind() operation's complement -- lookup():

 Object object = context.lookup("name") 

The lookup() operation retrieves the object bound to the specified name. Once again, the syntax is reminiscent of RMI, but the method's semantics are not as clearly defined.

Just as with bind(), the lookup() operation throws a NamingException if an exception occurs during the execution of the operation.

Object storage

What does it mean to store an object in a JNDI naming and directory service? We've already mentioned that the exact semantics of the bind() and lookup() operations aren't tightly defined; it's up to the JNDI service provider to define their semantics.

According to the JNDI specification, service providers are encouraged (but not required) to support object storage in one of the following formats:

  • Serialized data
  • Reference
  • Attributes in a directory context

If all JNDI service providers support these standard mechanisms, Java programmers are free to develop generic solutions that work even when the underlying service provider layer changes.

Each of the methods above has advantages and disadvantages. The best method will depend on the requirements of the application under development.

Let's consider each in turn.

As serialized data

The most obvious approach to storing an object in a directory is to store the serialized representation of an object. The only requirement is that the object's class implement the Serializable interface.

When an object is serialized, its state becomes transformed into a stream of bytes. The service provider takes the stream of bytes and stores it in the directory. When a client looks up the object, the service provider reconstructs it from the stored data.

The following code demonstrates how to bind a LinkedList to an entry in an JNDI service:

 // create linked list LinkedList linkedlist = new LinkedList(); . . . // bind context.bind("cn=foo", linkedlist); . . . // lookup linkedlist = (LinkedList)context.lookup("cn=foo"); 

It's that easy!

Unfortunately, the other two methods are more complicated. I will describe them briefly but reserve a detailed discussion for a later date.

As a reference

Sometimes it's not appropriate (or possible) to serialize an object. If the object provides a service on a network, for example, it doesn't make sense to store the state of the object itself. We're interested in the information necessary to find and communicate with the object.

An example is a connection to an external resource (one outside the scope of the Java Virtual Machine) such as a database or file. It clearly doesn't make sense to try to store the database or the file itself in the JNDI service. Instead, we want to store the information necessary to reconstruct the connection.

In this case the programmer should either bind a Reference instance that corresponds to the object or have the object's class implement the Referenceable interface (in which the object generates and provides a Reference instance when requested by the service provider).

The Reference instance contains enough information to recreate the reference. If a reference to a file was stored, the reference contains enough information to create a File object that points to the correct file.

As attributes

If you're using a service provider that provides directory functionality instead of only naming functionality, you can also store an object as a collection of attributes on a DirContext object (a DirContext instance differs from a Context instance in that it may have attributes).

To use this method, you must create objects that implement the DirContext interface and contain the code necessary to write their internal state as an Attributes object. You must also create an object factory to reconstitute the object.

This approach is useful when the object must be accessible by non-Java applications.

Conclusion

If you've read the series, you should understand and appreciate the power and importance of JNDI -- you don't hear much about it, but it's there under the covers.

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

למידע נוסף על נושא זה

  • החבילה האופציונלית של JDBC 2.0

    //java.sun.com/products/jdbc/articles/package2.html

  • עבור אל קרן OpenLDAP להורדת OpenLDAP

    //www.openldap.org/

  • להורדת מדריך מנהל SLAPD ו- SLURPD , עבור אל

    //www.umich.edu/~dirsvcs/ldap/doc/guides/

  • מידע על JNDI, נותני שירותים וכן הלאה

    //java.sun.com/products/jndi/

סיפור זה, "סקירת JNDI, חלק 3: JNDI מתקדם" פורסם במקור על ידי JavaWorld.