11-08.doc

(219 KB) Pobierz
Wstęp

Rzeczywistość              297

 

11

 

XML
na potrzeby konfiguracji

 

 

 

 

Niniejszy rozdział zawiera informacje dotyczące sposobów zastosowania języka XML w danych służących do konfiguracji. W poprzednich rozdziałach Czytelnik poznawał sposoby zastosowania tego języka do przesyłania danych pomiędzy aplikacjami i do tworzenia warstwy prezentacyjnej — w tym rozdziale zostaną omówione sposoby wykorzystania XML-a do przechowywania da­nych. Aby zrozumieć przesłanki przemawiające za użyciem XML-a na potrzeby konfiguracji, wy­star­czy napisać aplikację korzystającą z obszernych plików właściwości albo serwer konfigu­ro­wa­ny na podstawie plików, a nie argumentów wiersza poleceń. W obu tych przypadkach format plików dostarczających informacje do aplikacji jest umowny i zazwyczaj odpowiada tylko okreś­lo­nej aplikacji. Programista ustala format pliku, buduje moduł odczytujący taki plik i aplikacja zostaje związana ze swoim plikiem konfiguracyjnym na zawsze. Oczywiście, takie postępowanie nie uwzględnia dalekowzrocznych planów związanych z rozwijaniem tej aplikacji.

Programiści i inżynierowie systemów zdali sobie sprawę z kłopotów z pielęgnacją tak napisanego oprogramowania (zapominanie o przecinkach, niepewność dotycząca znaków wskazujących po­czą­­tek komentarza itd.). Jasne stało się, że potrzebny jest standard reprezentacji tego typu danych niezwiązany z konkretną aplikacją. Jednym z takich standardów, wciąż wykorzystywanym, ale poz­­ba­wionym wielu użytecznych cech, jest klasa java.util.Properties i odpowiednie pliki właściwości. Konstrukcje te, wprowadzone w pakiecie Java Development Kit (JDK) 1.0, umoż­liwiają wygodne z punktu widzenia Javy przechowywanie informacji konfiguracyjnych, jednakże nie udostępniają żadnego sposobu grupowania lub budowania hierarchii. Aplikacja klienta ma taki dostęp do informacji serwera, jak serwer do informacji klienta i programista nie jest w stanie prze­pro­wadzić żadnego logicznego grupowania wewnątrz takiego pliku. Co więcej, kiedy hierarchi­czne parametry konfiguracyjne zyskały na popularności, takie zagnieżdżanie było trudne do osią­gnięcia za pomocą innych rozwiązań bez wprowadzania jeszcze bardziej złożonych (a wciąż współ­pracujących tylko z daną aplikacją) formatów plików. XML przyniósł rozwiązanie wszyst­kich tych problemów — oferował standardowy, prosty sposób reprezentacji informacji konfiguracyjnych.

Format XML nadaje się do szerokich zastosowań administracyjnych. Możliwe jest zbudowanie ogól­nej aplikacji ładującej definicję DTD lub schemat, a następnie plik konfiguracyjny i umoż­li­wia­jącej dodawanie, aktualizację, usuwanie i modyfikację informacji konfiguracyjnych. Jedna apli­kacja, wykorzystująca jeden lub wiele plików konfiguracyjnych XML, mogłaby służyć jako jeden interfejs administracyjny. Jeśli porównamy to z całą mnogością plików haseł, plików sha­dow, użytkowników, grup i skryptów inicjalizacyjnych, to na pewno takie rozwiązanie jest przej­rzystsze i prostsze w obsłudze.

Ponieważ XML jest już wykorzystywany w wielu aplikacjach, dodanie rozszerzenia do prze­twa­rzania i obsługi plików konfiguracyjnych było tylko kwestią czasu. Aplikacje nie wykorzystujące jeszcze XML-a mogą wprowadzać pliki konfiguracyjne oparte na tym języku; jest to o wiele prostsze niż dodanie obsługi przesyłania danych XML lub przekształcania XML-a do innych formatów. Tak czy inaczej, konfiguracja za pomocą XML-a okazała się dobrym rozwiązaniem w wielu sytuacjach. Od kiedy przedstawiono specyfikację Enterprise JavaBeans(EJB) 1.1, wyma­ga­jącą deskryptorów wdrożeniowych EJB w formacie XML, wykorzystanie tego języka w kon­fi­guracji stało się bardzo popularne. Wielu programistów obawiających się obciążenia wynikającego z uruchomienia parsera XML lub wątpiących w perspektywy standardu XML nagle musiało wy­ko­rzystać ten język do wdrożenia obiektów biznesowych w serwerach EJB. Spowodowało to lo­gicz­ną migrację wszystkich danych konfiguracyjnych do tego formatu i przyczyniło się nawet do zmniejszenia złożoności niejednej aplikacji. W niniejszym rozdziale zostaną przedstawione spo­soby wykorzystania XML-a do konfigurowania własnej aplikacji.

Najpierw zostaną omówione używane obecnie sposoby korzystania z XML-a na potrzeby kon­fi­gu­ra­cji. Przedstawione zostaną deskryptory wdrożeniowe EJB pod kątem decyzji projektowych, ja­kie podjęto przy tworzeniu specyfikacji tego rodzaju plików. To stanowić będzie przygotowanie do stworzenia własnych plików konfiguracyjnych XML. Zaczniemy od zbudowania pliku kon­fi­guracyjnego dla serwera, który stworzyliśmy w poprzednim rozdziale. Następnie napiszemy klasy narzędziowe przetwarzające i ładujące te informacje do naszych klas XML-RPC — to znacznie zwięk­szy elastyczność omawianego serwera i jego klientów. Informacje o konfiguracji w prosty spo­sób załadujemy za pomocą interfejsów JDOM. W zakończeniu rozdziału zostaną porównane możliwości XML-a i innych mechanizmów składowania danych — baz danych i serwerów usług katalogowych. Dzięki temu Czytelnik będzie mógł wyrobić sobie opinię na temat praktycznych za­stosowań XML-a.

Deskryptory wdrożeniowe EJB

Zanim zbudujemy własne pliki konfiguracyjne oraz oprogramowanie pozwalające z nich korzys­tać, przyjrzymy się istniejącym formatom i szablonom. Tematem niniejszej książki nie jest spe­cy­fikacja EJB, ale krótki opis deskryptorów wdrożeniowych EJB potrzebny jest do zrozumienia zasady działania plików konfiguracyjnych XML; opis ten podpowie również, jak zaprojektować włas­ny for­mat danych konfiguracyjnych. W niniejszym podrozdziale zostaną także omówione naj­ważniejsze decyzje projektowe leżące u podstaw plików konfiguracyjnych deskryptorów.

Jednak przed omówieniem deskryptorów wdrożeniowych warto zastanowić się, dlaczego w ogóle programiści EJB „przeszli” na XML. Specyfikacja EJB 1.0 wymagała stosowania uszeregowanych deskryptorów wdrożeniowych; niestety, to była jedyna wskazówka oferowana przez autorów spe­cyfikacji. Każdy producent EJB wymagał więc własnego formatu deskryptorów wdrożeniowych dla swojego serwera i zmuszał programistę do uruchamiania narzędzia (a nawet pisania własnych narzędzi) szeregujących deskryptor. Specyfikacja EJB (a także ogólnie język Java) utraciła prawo do miana WORA (Write Once Run Anywhere — aplikacja raz napisana może zostać uru­cho­mio­na gdziekolwiek). XML udostępniał standardowy sposób obsługi deskryptorów wdrożeniowych, a także zniwelował potrzebę korzystania z własnych narzędzi szeregujących. Co więcej, firma Sun
udostępniła definicję DTD EJB, dzięki której deskryptory wdrożeniowe dowolnego producenta zgo­dne są z jedną specyfikacją; system EJB został w dużym stopniu uniezależniony od platformy i produktów określonego producenta.

Podstawy

Podobnie jak w przypadku dowolnego dokumentu XML, deskryptor wdrożeniowy EJB posiada definicję DTD, z którą utrzymuje zgodność. Jak już wcześniej wspomniano, w przyszłych wer­sjach specyfikacji definicja ta zostanie prawdopodobnie zastąpiona schematem. Tak czy inaczej, dokumenty XML używane w konfiguracji muszą tutaj (nawet bardziej niż gdzie indziej) prze­strzegać narzuconych na nie reguł. Bez zawężeń informacje w nich zamieszczone mogłyby okazać się niepoprawne lub bezużyteczne, a na tym cierpiałaby cała aplikacja. Po określeniu zawężeń deskryptor wdrożeniowy rozpoczyna się od elementu głównego ejb-jar. Niniejsza uwaga może wydawać się banalna, ale nazwanie elementu głównego stanowi istotny element budowania do­wol­nego dokumentu XML. Na elemencie tym spoczywa ciężar odpowiedzialności za reprezen­ta­cję wszystkich informacji zawartych w danym dokumencie XML. Szczególnie w przypadku, kiedy inne osoby będą musiały zarządzać naszymi dokumentami, właściwe ich nazwanie może oszczę­dzić im wiele kłopotów. Poniżej pokazano istotne fragmenty deskryptora wdrożeniowego XML zgodnego ze specyfikacją EJB:

<?xml version="1.0"?>

 

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise

JavaBeans 1.1//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd">

 

<ejb-jar>

  <description>

  Ten plik ejb-jar zawiera obiekty enterprise beans będące

  częścią aplikacji samoobsługowej dla pracowników.

  </description>

 

...

</ejb-jar>

Zastosowanie przestrzeni nazw (które w czasie tworzenia specyfikacji EJB 1.1 były jeszcze w po­wijakach) powoduje, że nazewnictwo elementu głównego i pozostałych jest bardziej przejrzyste. To zaś upraszcza określenie celu dokumentu; należy zauważyć, jak wiele dwuznaczności unik­nięto poprzez zastosowanie w deskryptorze wdrożeniowym przestrzeni nazwy takiej jak Dep­loy­mentDescriptor lub nawet EJB-DD. Wystarczy spojrzeć na przedrostek elementu, a wszystkie wątpliwości znikają.

Organizacja

Podobnie jak nazwy są istotne dla przejrzystości dokumentu, jego organizacja ma zasadnicze zna­czenie dla użyteczności danych jako źródła konfiguracji. Sposób organizacji i zagnieżdżania ele­men­tów i atrybutów nie tylko pomaga w zrozumieniu przeznaczenia dokumentu, ale gwarantuje również, że zawarte w nim informacje konfiguracyjne będą mogły być wykorzystane w różnych aplikacjach. Równie ważna jest umiejętność ustalenia, kiedy nie składować informacji tak, by była ona współużytkowana. Szczególnie istotny jest tutaj przypadek deskryptora wdrożeniowego; każ­dy obiekt EJB ma działać niezależnie od innych i posiadać tylko te informacje, które uzyskał z od­po­­wiadającego mu pojemnika (ang. containter). Może to stanowić problem, jeśli obiekty bean współdziałają ze sobą poza ścisłymi zasadami narzucanymi przez programistę — istnieje wtedy możliwość zburzenia logiki biznesowej i obniżenia wydajności. Dlatego właśnie każdy wpis EJB jest niezależny od pozostałych.

W poniższym przykładzie za pomocą dokumentu XML opisano obiekt bean sesji:

<enterprise-beans>

  <session>

    <description>

      Obiekt bean EmployeeServiceAdmin stanowi implementację sesji

      wykorzystywanej przez administratora aplikacji.

    </description>

 

    <ejb-name>EmployeeServiceAdmin</ejb-name>

    <home>com.wombat.empl.EmployeeServiceAdminHome</home>

    <remote>com.wombat.empl.EmployeeServiceAdmin</remote>

    <ejb-class>com.wombat.empl.EmployeeServiceAdmin-Bean</ejb-class>

    <session-type>Stateful</session-type>

    <transaction-type>Bean</transaction-type>

 

    <resource-ref>

      <description>

        Referencja do bazy JDBC.

        EmployeeService zawiera dziennik wszystkich transakcji

        dokonywanych poprzez bean EmployeeService na potrzeby

        audytu.

      </description>

      <res-ref-name>jdbc/EmployeeAppDB</res-ref-name>

      <res-type>javax.sql.DataSource</res-type>

     <res-auth>Containter</res-auth>

    </resource-ref>

 

  </session>

</enterprise-bean>

Elementy nie tylko izolują ten obiekt bean od wszelkich innych, ale również umożliwiają logiczne grupowanie danych. Element resource-ref zawiera informacje odpowiadające określonemu wpi­­sowi związanemu ze środowiskiem. W ten sposób aplikacja przetwarzająca i wykorzystująca dane, a także programiści i administratorzy systemu zarządzający aplikacją mogą w prosty sposób zlokalizować i zaktualizować informacje o obiekcie bean lub serwerze EJB.

Większą grupą — i nie tak łatwo rozpoznawalną — jest element enterprise-beans. Dzięki nie­mu możliwe jest zamieszczenie informacji specyficznych dla danego pojemnika, a nie ma­jących zastosowania do obiektów bean; informacje te nie zostaną wymieszane z tymi specy­fi­cz­nymi dla EJB. Jest to ważne rozgraniczenie; za jego pomocą w dalszej części rozdziału oddzielimy informacje konfiguracji serwera i klientów XML-RPC. Wreszcie — do tego elementu macie­rzys­te­go można dodać dowolną liczbę obiektów bean; tutaj zamieszczony jest przykład tylko jednego obiektu sesji bean, ale można ich wstawić dowolnie wiele, tak by odpowiadały wielu obiektom bean w tworzonym pliku jar.

Choć pokazany plik XML został opisany pobieżnie, Czytelnik może już domyślać się, jak na­zy­wać i organizować pliki XML tego rodzaju we własnych aplikacjach oraz w opisywanym przy­kładzie XML-RPC. Niemal każda aplikacja ma odmienne potrzeby, co pociąga za sobą odmienną organizację dokumentu XML oraz inny zestaw zawężeń. Skoro przyjrzeliśmy się już przykładowi konfigurowania serwera aplikacji za pomocą języka XML i zaczęliśmy zastanawiać się nad stwo­rzeniem własnego pliku konfiguracyjnego, spróbujmy podejść do tematu praktycznie i zbudować właśnie taki plik dla naszych klas XML-RPC.

Tworzenie pliku konfiguracyjnego XML

Aby zastosować naszą wiedzę w praktyce, zbudujemy plik konfiguracyjny XML dla klas XML-RPC, które napisaliśmy w poprzednim rozdziale. Posłuży nam to jako doskonały przykład za­sto­so­wania informacji konfiguracyjnych w formacie XML; mamy już dostępny parser XML (wy­korzystany w serwerze XML-RPC) i możliwe jest użycie tego samego pliku konfiguracyjnego dla klientów i serwera. Co więcej, plik konfiguracyjny mógłby być edytowany za pomocą interfejsu IDE XML, a nie za pomocą własnego interfejsu do edycji pliku we własnym formacie. To wszy­stko przyczynia się do zmniejszenia ilości kodu koniecznego do budowania złożonych aplikacji.

Zanim zaczniemy pisać plik konfiguracyjny, musimy określić, jakie informacje będzie można z nie­go odczytać:

·       port, na którym ma być uruchomiony serwer XML-RPC,

·       klasa parsera, którą serwer wykorzysta jako sterownik SAX,

·       procedury obsługi dla serwera XML-RPC,

·       identyfikator klasy,

·       nazwa klasy,

·       nazwa hosta, z którym mają się łączyć klienty XML-RPC,

·       port, z którym mają się łączyć klienty XML-RPC,

·       klasa parsera, którą klient wykorzysta jako sterownik SAX.

To wszystkie informacje, jakie trzeba przekazać serwerowi i klientom, aby te mogły zostać uru­cho­mione z tylko jednym parametrem — położeniem pliku konfiguracyjnego. Pamiętając o tym, zabierzmy się do pisania samego pliku konfiguracyjnego.

Od czego zacząć?

Podobnie jak w przypadku deskryptora wdrożeniowego EJB, nasz plik musi zawierać standardowy nagłówek XML. To chyba nie powinno przedstawiać trudności; poza tym trzeba jeszcze tylko pa­miętać o określeniu przestrzeni nazw i elementu głównego dokumentu. Choć w środowisku pro­duk­cyjnym użylibyśmy przestrzeni nazw kojarzącej się z przeznaczeniem dokumentu (np. XMLRPC lub XmlRpcConfig), tutaj wciąż będziemy używać nazwy JavaXML, starając się zachować je­dnolity schemat we wszystkich przykładach w tej książce. Deklarujemy przestrzeń nazw tak jak we wcześniejszych rozdziałach. Element główny pełni rolę identyfikatora przeznaczenia dokumentu; tak więc nazwa xmlrpc-config będzie tutaj odpowiednia. Często jest tak — szcze­gólnie w złożonych dokumentach XML — że najprostsze rozwiązanie jest rozwiązaniem naj­lep­szym. Nazewnictwo elementów XML nie stanowi tutaj wyjątku.

Po podjęciu tych wstępnych decyzji można rozpocząć budowę pliku konfiguracyjnego dla po­siadanych klas XML-RPC. Poniżej przedstawiona jest początkowa deklaracja XML oraz element główny:

<?xml version="1.0"?>

 

<JavaXML:xmlrpc-config

  xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"

>

 

...

Zgłoś jeśli naruszono regulamin