C/C++ / CGI / Sieć Novell / PHP / Java / SQL / Oracle / WebSphere MQ / WebSphere Message Broker / JavaScript / Humor / IT Quiz


Język Java

<B>Informacje podstawowe</B><br>
O języku : <!--GROUP=java&DATA=info-->
Instalacja : <!--GROUP=java&DATA=install-->
JDBC
Aplikacje internetowe
Serwlety
JSP
Web Services
JNDI
XML
EJB
Konektory J2EE
Technologie portalowe
Technologia cienkiego klienta oraz serwery aplikacji
Wyj?tki : <!--GROUP=java&DATA=exceptions-->
Interfejsy : <!--GROUP=java&DATA=interfaces-->
RMI : <!--GROUP=java&DATA=rmi-->
AWT : <!--GROUP=java&DATA=awt-->
Swing : <!--GROUP=java&DATA=swing-->
Cookies : <!--GROUP=java&DATA=cookies-->
Sesje : <!--GROUP=java&DATA=sessions-->
Operacje sieciowe : <!--GROUP=java&DATA=net-->
Wydajno?ć
Bezpieczeństwo
<br><b>Literatura</b>
<br><b>Jeden plik</b>
<BR><B>Legenda</B>
<font size=1>w przygotowaniu</font><br><font size=1>* w trakcie tworzenia</font><br>


O języku

<p>Krótki opis języka JAVA.


JDBC

Wprowadzenie
Ł?czenie się z baz?
Nawi?zywanie poł?czenia
Wykonywanie zapytań
Metody execute
Obiekt ResultSet
Transakcje
DataSource
Pre-interpretowane zapytania : <!--GROUP=java&DATA=jdbcpreparedstatement-->


JDBC Wprowadzenie

JDBC (Java Database Conectiviti) jest interfejsem pozwalaj?cym poł?czyć aplikację Javy z zewnętrzn? baz? danych za pomoc? odpowiednich sterowników. Duż? zalet? JDBC jest łatwo?ć przej?cia na inny system bazodanowy, co najczę?ciej odbywa się bez zmian w kodzie aplikacji lub ze znikom? ich ilo?ci?. Polega to zazwyczaj na zmianie sterownika JDBC na taki, który współpracuje z systemem bazodanowym do którego chcemy mieć dostęp w aplikacji<br>


Ł?czenie się z baz?

Pierwsz? rzecz?, jak? należy zrobić aby poł?czyć się z baz? danych jest załadowanie odpowiedniego sterownika JDBC. Sterowniki te dostarczane s? najczę?ciej wraz z dystrybucj? systemu bazodanowego lub znajduj? się na stronie WWW producenta.<br><br><b>Załadowanie sterownika:</b><br>
Załadowanie sterownika odbywa się poprzez wywołanie metody <b>ClassforName</b>. Sposób załadowania poszczególnych sterowników może się nieznacznie różnić. Informacja ta powinna być umieszczona w dokumentacji dostarczonego sterownika.<br><font class=code>ClassforName("path");</font>.
gdzie:
path : łańcuch tekstowy okre?laj?cy nazwę klasy sterownika wraz z jego ?cieżk?
np wywołanie dla standardowych sterowników MySQL:
<font class=code>Class.forName("org.gjt.mm.mysql.Driver").newInstance();</font>.


Nawi?zywanie poł?czenia

Nawi?zywanie poł?czenia z baz? danych odbywa się zaraz po załadowaniu odpowiedniego sterownika JDBC. Polega to na poinformowaniu sterownika z jak? baz? chcemy się poł?czyć, na jakim komputerze znajduje się baza danych i na jakim porcie następuje komunikacja.<br><br><b>Wywołanie metody</b><BR>
<font class=code>Connection conn=DriverManager.getConnection("jdbc:subproto://host:port/db","user","pass");</font>
gdzie:
subproto : zazwyczaj nazwa systemu bazodanowego (np. mysql)
host : nazwa komputera
port : port na którym następuje komunikacja
db : nazwa bazy danych
user : nazwa użytkownika
pass : hasło


Wykonywanie zapytań

Pierwszym etapem wykonania zapytania na bazie jest stworzenie obiektu <b>Statement</b> poprzez metodę <b>createStatement</b> obiektu <b>Connection</b><br><br><font class=code>Statement st=conn.createStatement();</font>.
<br>Zasadnicze zapytanie wykonujemy metod? <b> executeQuery</b> obiektu <b>Statement</b>, która zwraca referencję do obiektu typu <b>ResultSet</b> będ?cego zbiorem wierszy zwróconych przez zapytanie.<br><br><font class=code>ResultSet res = st.executeQuery("select * from users");</font>
<br>Wiedz?c, że o obiekcie <b>ResultSet</b> znajduj? się wszystkie wiersze zwrócone przez zapytanie możemy przej?ć przez te wiersze i pobrać wyniki.<br><br><b>Przykład:</b><BR>
<font class=code>while (result.next())<br>{<br>name = res.getString("name");<br>age = res.getString("age");<br>}</font><br>


Metody execute

Rozróżniamy trzy zasadnicze metody rodziny execute obiektu <b>Statement</b>
<br><b>executeQuery()</b> : Wykorzystywana do zapytań typu <b>select</b>. Zwraca obiekt typu <b>ResultSet</b>, będ?cy zbiorem wszystkich wierszy zwróconych przez zapytanie.
np. : <font class=code>Resultset res=st.executeQuery("Select * from tab");</font>
<br><b>executeUpdate()</b> : Wykorzystywana do zapytań modyfikuj?cych bazę typu <b>INSERT</b>, <b>UPDATE</b> i <b>DELETE</b>.
Metoda ta zwraca ilo?ć zmienionych lub usuniętych wierszy w zależno?ci od zapytania.<br>np. : <font class=code>int count=st.executeUpdate("Insert into tab values (1,50)");</font>
<br><b>execute()</b> : Wykorzystywana w sytuacjach, kiedy nie jeste?my w stanie zagwarantować, że wykonywane zapytania na obiekcie będ? tylko pobierać dane, lub tylko je modyfikować.
Metoda zwraca warto?ć logiczn? <b>true</b> je?li zapytanie jest typu <b>select</b>, w przeciwnym razie zwraca <b>false</b>. Je?li już wiemy z jakim typem zapytania mamy do czynienia możemy pobrać wiersze zwrócone przez zapytanie lub ilo?ć zmodyfikowanych rekordów odpowiednimi metodami obiektu <b>Statement</b>, tj. odpowiednio <b>GetResultSet()</b> lub <b>GetUpdateCount()</b>.<br><br><b>Przykład:</b><BR>
<font class=code>ret = st.execute(Query);<br> if (ret)<br>{<br>ResultSet res=st.getResultSet();<br>...<br>}<br>else<br>{<br>int count=st.getUpdateCount();<br>...<br>}<br></font><br>


Obiekt ResultSet

Ciekawsze metody obiektu <b>ResultSet</b><br>
<b>previous()</b> : Przesuwa kursor o jeden wiersz do tyłu. Zwraca <b>false</b> je?li kursor jest wskazuje na pierwszy wiersz.
<b>next()</b> : Przesuwa kursor o jeden wiersz do przodu. Zwraca <b>false</b> je?li kursor jest wskazuje na ostatni wiersz.
<b>beforeFirst()</b> : Ustawia kursor przed pierwszym wierszem.
<b>afterLast()</b> : Ustawia kursor za ostatnim wierszem.
<b>absolute(n)</b> : Ustawia kursor na <b>n</b>-tym wierszu.
<b>relative(n)</b> : Przesuwa kursor o <b>n</b> wierszy względem bież?cej pozycji kursora.


Transakcje

Transakcja jest to poł?czona grupa zapytań SQL stanowi?ca jednolit? cało?ć. Domy?lnie każde pojedyncze zapytanie jest pojedyncz? transakcj?. Aby to zmienić, tj. aby mieć możliwo?ć umieszczenia w transakcji więcej niż jednego zapytania należy skorzystać z metody <b>SetAutoCommit(tryb)</b> obiektu <b>Connection</b>, gdzie jako parametr podajemy warto?ć logiczn? <b>false</b> c obędzie oznaczało, że będziemy okre?lać samodzielnie transakcje. Po wykonaniu wszystkich zapytań w transakcji w celu zamknięcia jej i zapisania zmian wykorzystujemy metodę <b>commit()</b> obiektu <b>Connection</b>, aby transakcję cofn?ć wykorzystujemy metodę <b>rollback()</b>. Do pobrania bież?cy tryb transakcji stosuje się metodę <b>getAutoCommit()</b>.<br>


DataSource

DataSource jest specjalnym zasobem serwera aplikacji zwi?zanym z obsług? bazy danych. Obiekt taki zdefiniowany na serwerze zawiera wszystkie informacje potrzebne do zrealizowania poł?czenia do konkretnej bazy danych, pocz?wszy od klas JDBC implementuj?cych to poł?czenie, a skończywszy na typowych parametrach zwi?zanych z poł?czeniem, nazwa serwera, bazy danych, itp. Same operacje na bazie danych z punktu widzenia programisty niczym się nie różni? poza tym, że taki obiekt DataSource należy najpierw wyci?gn?ć z serwera nazewniczego JNDI, a następnie dopiero z tego obiektu można pobrać obiekt Connection. Zasadnicza różnica polega na tym, że to serwer aplikacji zajmuje się zarz?dzaniem poł?czeń do bazy danych, a programista wywoływaniem odpowiednich operacji bazodanowych. To serwer zarz?dza pul? poł?czeń do bazy i ponownymi próbami poł?czenia w przypadku awarii. Na serwerze mamy możliwo?ć takiego skonfigurowania zasóbu DataSource, aby ograniczyć ilo?ć jednocze?nie otwartych poł?czeń. W celach wydajno?ciowych, maj?c na uwadze to, że często najbardziej czasochłonn? operacj? bazodanow? jest samo poł?czenie, możemy tak skonfigurować zasób aby zawsze na wszelki wypadek niezależnie, czy poł?czenie jest potrzebne czy nie kilka było aktywnych. Rozwi?zanie takie daje nam duż? swobodę przy konfigurowaniu i skalowaniu aplikacji oraz zalecane jest również ze względów bezpieczeństwa.<br><br>


Aplikacje internetowe

Rozwój internetowych nie przebiega od do?ć dawna. Jest to raczej nowy termin. W pierwszej fazie rozwoju internetu był on wykorzystywany do serwowania statycznych stron, gdzie raczej nie było mowy o większej interakcji z użytkownikiem. Następnie zaczęto się zastanawiać nad możliwo?ci? wykorzystania internetu go generowani stron HTML w sposób dynamiczny w zależno?ci od intencji użytkownika. Duże znaczenie ma tu termin "cienki klient". Termin ten okre?la aplikacje, złożon? z odpowiednich warstw. Najczę?ciej tych warstw jest 3. Pierwsza odpowiada za warstwę danych, druga warstwa kontroluje te dane, a trzecia je prezentuje. Rozdział aplikacji na takie warstwy pozwala nam na lepsz? skalowalno?ć aplikacji i łatwo?ć jej rozbudowy, gdzie przy zmianie w każdej z tych warstw pozostałe pozostaj? bez zmian, co w przypadku standardowych aplikacji wi?że się z poważniejszymi zmianami w całej aplikacji.<br><br> Kolejnym plusem wykorzystania programowania trójwarstwowego s? duże oszczędno?ci przy wdrażaniu kolejnych wersji aplikacji. W przypadku standardowych aplikacji każda nowa wersja musi zostać w jaki? sposób zainstalowana u klienta. W przypadku aplikacji trójwarstwowej wdrożenie nowej wersji polega tylko i wył?cznie na wdrożeniu jej na serwerze. Od tej pory każde odwołanie do strony WWW zawieraj?cej aplikację dotyczy już nowej wersji aplikacji serwowanej przez serwer.<br><br> Aplikacje takie s? pisane w większo?ci języków programowania mog?cych pisać na standardowe wyj?cie i maj?cych dostęp do zmiennych ?rodowiskowych. W zasadzie takie możliwo?ci daje nam większo?ć języków programowania obecnie dostępnych na rynku. W internecie na dzień dzisiejszy można znaleĽć aplikacje napisane w C/CGI, Perl, PHP, ASP oraz JSP/Serwlety.<br><br> Języki C/CGI i Perl s? najstarsze na rynku w dziedzinie aplikacji internetowych. Dzi? s? już coraz mniej stosowane ze względu na pojawienie się nowszych i lepszych rozwi?zań. ASP jest komercyjn? odpowiedzi? na darmowe PHP i współpracuje tylko i wył?cznie z serwerami WWW firmy Microsoft. Technologia PHP wykorzystywana jest do szybkiego pisania prostych aplikacji WWW. Do pisania dużych, skomplikowanych projektów WWW najlepszym rozwi?zaniem będzie JSP/Serwlety oparty o język JAVA. Daje nam on możliwo?ć swobodnego pisania dużych modułowych aplikacji z wykorzystaniem możliwo?ci, jakie nam daje język JAVA.<br><br>


Serwlety

Serwlet jest to komponent rozszerzaj?cy funkcjonalno?ć serwera aplikacji, generuj?cy dynamiczn? zawarto?ć strony WWW. S? one rozszerzeniem oferowanym przez serwery potrafi?ce obsługiwać język Java. Korzystaj?c z nich zwiększa się możliwo?ci serwerów WWW, ponieważ s? one wydajn?, przeno?n? i łatw? w użyciu alternatyw? dla skryptów CGI. Serwlet to ładowany dynamicznie moduł, który obsługuje zlecenia serwera WWW. Działa on w oparciu o maszynę wirtualn? Javy. Ponieważ serwlet uruchamiany jest po stronie serwera, jego prawidłowe działanie nie zależy od przegl?darki. Funkcjonalno?ć serwletów wykracza poza ramy CGI dodaj?c pewne specyficzne funkcje nie obsługiwane przez ten mechanizm. <br><br> Rozszerzenia zaprojektowane przez konkretny serwer (NSAPI - Netscape Server API lub Apache Modules), maj? wprawdzie lepsz? obsługę danego typu aplikacji, natomiast nie maj? tak poż?danej uniwersalno?ci. <br><br> Serwlety maj? natomiast następuj?ce cechy, które przebijaj? inne rozszerzenia:<br><br> -        Zdecydowanie większa szybko?ć w porównaniu ze skryptami CGI, ze względu n odmienny model przetwarzania,<br> -        Wykorzystanie standardowego interfejsu API, obsługiwanego przez wiele serwerów WWW,<br> -        Dziedziczenie wszystkich zalet języka JAVA, wł?czaj?c w to łatwo?ć programowania i niezależno?ć sprzętow?<br> -        Dostęp do szerokiej gamy interfejsów API, oferowanych razem z platform? JAVA.<br> <br><br> Serwlety pomagaj? rozwi?zać wiele problemów spotykanych przy projektowaniu systemów sieciowych, a lepsze poznanie zasad ich stosowania ułatwia znajdowanie nowych zastosowań.<br> Ilustracj? najczęstszych zastosowań serwletów mog? być poniższe trzy przykłady:<br><br> -        Opracowywanie zaplecza sprzedaży elektronicznej to jeden z najpopularniejszych obszarów zastosowań serwletów. Serwlet może na bież?co tworzyć katalog dostępnych towarów w oparciu o informacje pobierane z baz danych, a następnie przedstawiać go klientowi, korzystaj?c z dynamicznie generowanego kodu HTML. Klient może zamówić poszczególne towary, zapoznać się z informacjami o płatno?ci i dostarczaniu towarów, a następnie wysłać odpowiednie dane do serwera opisuj?ce jego zamówienie. Serwlet może przetworzyć te dane, uaktualnić bazę danych itp. Wszystkie etapy tego procesu mog? bez problemów być obsługiwane przez serwlety.<br><br> -        Serwlety pozwalaj? prezentować dane zebrane w dużych systemach w sieci Internet. Wiele firm dysponuje duż? ilo?ci? danych gromadzonych w systemach klasy mainframe. Zwykle zmiana architektury tego systemu nie jest możliwa. Można jednak utworzyć prosty i niedrogi interfejs oparty o WWW umożliwiaj?cy operacje na zgromadzonych danych. Dzięki pakietowi JDK i zabezpieczeniom oferowanym przez serwer WWW za pomoc? serwletów można tworzyć interfejsy do systemów korzystaj?cych z dowolnych technologii, od TCP/IP do CORBA.<br><br> -        Przy projektowaniu rozproszonych aplikacji obiektowych, które będ? działać w sieci WWW, często spotkać można problemy z prawami dostępu. Je?li wykorzystane zostan? aplety po stronie klienta, będ? one mogły poł?czyć się wył?cznie z serwerem, z którego pochodz?, a który często znajduje się za firewallem. Zapory takie s? poważnym problemem przy korzystaniu ze zdalnego wywoływania metod (RMI). W przypadku serwletów mamy możliwo?ć tworzenia tunelów prowadz?cych za firewall, korzystaj?c z techniki HTTPTunneling. Dzięki temu aplety mog? uzyskać dostęp do obiektów uruchomionych w zasadzie w dowolnym systemie podł?czonym do sieci.<br><br>Listenery HTTP


Listenery HTTP

HttpSessionListener
Jest to listener zwi?zany z sesj? HTTP. Pozwala on na wykonywanie dowolnych operacji, które będ? trigerowane przy operacjach zwi?zanych z sesja HTTP, takich jak utworzenie, czy tez usuniecie sesji. <br> Aby we własnej aplikacji mieć możliwo?ć wykorzystania tej funkcjonalno?ci należy utworzyć klasę implementuj?c? interfejs HttpSessionListener.<br><br> Interfejs HttpSessionListener posiada dwie metody, które w naszej klasie musza być zaimplementowane: <br><br>sessionCreated(HttpSessionEvent event) : metoda ta jest wywoływana za każdym razem, kiedy tworzona jest sesja HTTP
sessionDestroyed(HttpSessionEvent event) : metoda ta jest wywoływana za każdym razem, kiedy sesja HTTP jest usuwana
<br> Metody te jako parametr przyjmuje klasę HttpSessionEvent. Z obiektu tego następnie można pobrać obiekt sesji, której zdarzenie dotyczy.<br><br> <font class=code> HttpSession session=event.getSession()<br> </font> <br> Po przygotowaniu takiej klasy będ?cej listenerem należy w deskryptorze (pliku web.xml) poinformować, że w aplikacji wykorzystujemy listenera. Dokonujemy tego poprzez umieszczenie w nim wewn?trz bloku web-app kolejnego wpisu o strukturze listener /listener-class, gdzie listener-class wskazuje na nazwę klasy wraz z pakietem. Przykład takiego wpisu może mieć postać :<br><br> <font class=code> <web-app id="WebApp"><br> <display-name>MyWebApp</display-name><br> <listener><listener-class>testapp.MySessionListener</listener-class></listener><br> ...<br> </web-app><br> </font> <br> Najczęstszym zastosowaniem tego listenera jest wykorzystanie drugiej z tych metod w celu usunięcia z systemu pozostało?ci po kliencie, którego sesja wła?nie wygasła. Je?li np. w trakcie pracy aplikacji w bazie danych przechowujemy jakie? dane tymczasowe, to wskazane jest, aby po zakończeniu pracy klienta wskazane jest, aby skasować z bazy dane skojarzone z jego sesja.<br><br>ServletContextListener
Jest to listener zwi?zany z kontekstem aplikacji. Pozwala on na wykonywanie operacji, które będ? trigerowane podczas działań zwi?zanych z uruchomieniem i zatrzymaniem aplikacji WWW.<br><br> Interfejs ServletContextListener posiada dwie metody, które musi posiadać klasa go implementuj?ca. <br><br> contextInitialized(ServletContextEvent event) : metoda ta jest wywoływana podczas uruchamiania aplikacji
contextDestroyed(ServletContextEvent event) : metoda ta jest wywoływana podczas uruchamiania aplikacji
<br> Listener ten najczę?ciej jest używany, kiedy w aplikacji webowej wywoływane s? metody nie poprzez interakcje z użytkownikiem, tylko np. co okre?lony czas. W takim przypadku w metodzie contextInitialized możemy utworzyć własny watek, w którym operacje takie s? wykonywane. Inne sposoby utworzenia takiego w?tku (np. w serwlecie) nie s? zalecane w specyfikacji J2EE.<br><br>


JSP

Technologia JSP (Java Server Pages) nie ogranicza się tylko i wył?cznie do języka skryptowego. Jest to całe ?rodowisko programowania. Język programowania jest tutaj traktowany jako element integralny. W skład technologii wchodz? również pewne struktury, które umożliwiaj? współpracę z innymi językami programowania. Technologia narzuca tylko pewne ramy, w których musi się poruszać programista z niej korzystaj?cy. JSP jest czę?ci? technologii J2EE, pełnej, specjalistycznej platformy dla tworzenia systemów informatycznych.<br><br> Jak sama nazwa wskazuje językiem użytym w omawianej technologii jest język JAVA. Wykorzystanie go do tego celu przynosi wiele korzy?ci. Jedna z pierwszych technologii, jakie zaczęto wykorzystywać do tworzenia dynamicznych stron WWW było CGI. Zapewnia ona poprawne działanie wszystkich elementów, jest jednak oparta archaicznym rozwi?zaniu. CGI jest również bardzo "procesożerne", co w obecnym czasie, szybkiego rozwoju Internetu, przekre?la to rozwi?zanie. <br><br> Obecnie konkurencyjnym rozwi?zaniem dla JSP jest produkt firmy Microsoft o nazwie ASP (Active Server Pages). ASP ma jednak bardzo poważne ograniczenie, jest to platforma dedykowana w swoich zamierzeniach produktom swojego producenta. Język JAVA jest idealnym rozwi?zaniem dla zastosowań w Internecie. Sieć przepełniona jest różnorodnym sprzętem. Odnosi się to zarówno do sprzętu, jak i do systemów operacyjnych. Obecnie każdy szanuj?cy się system operacyjny posiada swoj? wirtualn? maszynę tego języka. Wszystko wskazuje na to, że technologia JSP zajmuje pierwszego miejsca w wy?cigu o rynek aplikacji WWW w?ród języków skryptowych.<br><br> JSP jest technologi? Internetow?, szybko rozwijaj?c? się i nios?c? wielkie oczekiwania. Nie jest językiem programowania, ani językiem znacznikowym. Jest niezależny od systemu operacyjnego i przegl?darki. Zapewnia wsparcie dla języka Java oraz JavaScript.<br><br> Zasada działania mechanizmów JSP
Mechanizmy JSP pozwalaj? na dynamiczne generowanie dokumentów w języku HTML po stronie serwera. S? one bezpo?rednim rozszerzeniem serwletów języka Java, pozwalaj?cym rozdzielić procesy generowania strony i jej prezentacji. Strony JSP s? obsługiwane przez zwyczajny serwlet, uruchamiany dla plików z rozszerzeniem *.jsp. Dokument JSP wygl?da tak jak każdy inny dokument HTML, z tym, że zostały w nim osadzone znaczniki zawieraj?ce polecenia w języku Java. Je?li przegl?darka będzie chciała pobrać tę stronę, serwer rozpozna rozszerzenie *.jsp i na tej podstawie zdecyduje, że plik wymaga specjalnego przetworzenia. Przy pierwszym pobraniu dokument zostanie przetłumaczony do postaci kodu Ľródłowego serwletu w języku Java, skompilowany i zachowany w pamięci, a wynik jego wykonania zostanie zwrócony do przegl?darki. Przy kolejnych pobraniach serwer sprawdza, czy plik *.jsp został zmodyfikowany - je?li nie, uruchamiany jest skompilowany wcze?niej serwlet.<br><br>


Web Services

Pod terminem Usługi Web należy rozumieć zbiór małych funkcjonalnych modułów pracuj?cych w sieci i udostępniaj?cych okre?lone usługi innym systemom czy też innym webservices. Takimi modułami mog? być np. usługi pogodowe, translatory językowe czy mechanizmy przeliczaj?ce waluty, a wykorzystywane mog? być przez inne usługi udostępniaj?ce usługi bardziej złożone. Webservices zwykle nie będ? stanowić samodzielnych aplikacji, a jedynie stanowić interfejs komunikacyjny pomiędzy klientami z sieci a systemami biznesowymi.<br><br> Wyj?tkow? sił? webservices jest wykorzystanie istniej?cych i szeroko stosowanych technologii tj. protokołu HTTP i języka XML. HTTP jest jednym z najbardziej rozpowszechnionych protokołów w sieci, co umożliwia natychmiastowe wykorzystanie tej platformy do przesyłania komunikatów. XML dostarcza metajęzyk za pomoc? którego porozumiewaj? się klienci z usługami oraz poszczególne komponenty. Id?c dalej, przy budowie i wykorzystaniu webservices nie ma znaczenia w jakiej technologii jest napisana usługa, na jakim systemie operacyjnym pracuje. Pełn? interoperatywno?ć zapewnia protokół SOAP, który ma aspiracje stać się następc? technik typu CORBA, RMI czy DCOM.<br><br>SOAP
SOAP to protokół definiuj?cy formaty komunikatów, sposoby wysyłania komunikatów i odbierania odpowiedzi, kodowania danych w języku XML oraz gramatykę XML służ?c? do: okre?lania nazw metod, definiowania typów parametrów i zwracanych warto?ci oraz opisu typów. SOAP okre?la także mechanizmy wywoływania zdalnych procedur (RPC) przy pomocy protokołu komunikacyjnego HTTP. ??dania SOAP s? wysyłane jako ż?dania HTTP POST, choć do komunikacji może być wykorzystany jakikolwiek protokół transportowy.<br><br> Cały proces wymiany komunikatów rozpoczyna się od zapytania SOAP wysłanego jako HTTP POST z typem zawarto?ci text/xml i polem SOAPAction zawieraj?cym nazwę metody SOAP. W komunikacie jest także miejsce na dane w postaci XML. Odbiornik na serwerze (np. servlet) kontroluje pole SOAPAction i w zależno?ci od jego zawarto?ci podejmuje odpowiednie działania. Na podstawie tre?ci XML odnajdywana jest odpowiednia usługa, która wykona metodę i zwróci rezultat. Następnie rezultat jest zwracany klientowi jako dokument XML ze standardowym nagłówkiem HTTP i typem zawarto?ci text/xml.<br><br> Podczas wymiany dużej ilo?ci komunikatów znacz?c? warto?ci? staje się wydajno?ć. W przeciwieństwie do technologii typu CORBA, RMI czy DCOM gdzie dane transportowane s? w postaci binarnej (brak metadanych), SOAP przesyła komunikaty czystym i otwartym XML. SOAP wraz z samoopisuj?cymi się danymi w XML umożliwia łatwe i szybkie przystosowanie każdego systemu do wykorzystania stosowanej implemenntacji SOAP, co w przypadku systemów binarnych sprawia duże problemy w zwi?zku z różnymi sposobami kodowania informacji. Czas potrzebny na zakodowanie/odkodowanie komunikatu SOAP jest nieporównywalnie mały do czasu przesłania takiego komunikatu przez sieć.<br><br>UDDI
UDDI (Universal Description, Discovery and Integration Service) to usługa udostępniaj?ca klientom mechanizmy dynamicznego wyszukiwania innych usług. UDDI stanowi interfejs umożliwiaj?cy dynamiczne poł?czenie się z usług? udostępnian? przez innego usługodawcę. Rejestry UDDI zawieraj?:<br><br> -        informacje o webservices na bazie nazwy usługodawcy, jego adresu, kategorii biznesowej czy informacji technicznej itp., <br> -        operacje dotycz?ce usługi, tj., rejestracji, wyszukiwania i korzystania z usługi<br> -        szczegóły udostępniane przez niskopoziomowe API<br> <br> UDDI posiadaj? dwa rodzaje klientów: usługodawców publikuj?cych swoje usługi oraz klientów pragn?cych skorzystać z tych usług. Warstwa UDDI leży nad protokołem SOAP, przez co komunikaty UDDI stanowi? obiekty w komunikatach SOAP.<br><br>WSDL
WSDL (Web Services Definition Language) jest nadzbiorem języka SDL, umożliwia twórcom usługi Web opisanie co potrafi usługa, gdzie się znajduje i jak j? wywołać. Usługa Web może być pytana o listę udostępnianych metod. OdpowiedĽ powinna zawierać opis w zrozumiałym formacie. Język WSDL jest przydatny przy automatyzacji komunikacji pomiędzy usługami webservices umożliwiaj?c współgranie usług.<br><br>DISCO
Protokół odnajdowania DISCO (Discovery) umożliwia odnajdowanie usług Web Services. Witryna internetowa powinna opublikować dokumenty DISCO zawieraj?ce adresy URL oraz opisy WSDL dla udostępnianych usług web. Dokumenty DISCO zawieraj? odniesienia do innych witryn oraz innych dokumentów DISCO co umożliwia przeszukiwanie drzew katalogów itp.<br><br>


JNDI

JNDI jest to specjalna usług? nazewnicz? i katalogow? uruchamian? w serwerach aplikacji. Jej obecno?ć wymagana jest przez specyfikacje J2EE. Ze względu na te wymagania każdy serwer aplikacji musi dostarczać własn? usługę katalogow? i zazwyczaj jest ona do?ć mocno z nim zintegrowana. Jej zadaniem jest przechowywanie obiektów i ich hierarchii w formie skatalogowanej. Serwer aplikacji korzystaj?cy z JNDI wi?że okre?lon? przez programistę nazwę z fizycznym obiektem i przechowuje go w repozytorium, a klient znaj?c tę nazwę może za pomoc? JNDI wyszukać taki obiekt i wywołać na nim odpowiednie metody. Obiekty takie mog? być wykorzystywane przez aplikacje znajduj?ce sie na tym samym serwerze aplikacji, b?dĽ z zupełnie innego miejsca poprzez sieć za pomoc? protokołu CORBA lub RMI. W katalogu takim przechowywane mog? być różnego rodzaju zasoby. Mog? to być obiekty typu DataSource umożliwiaj?ce poł?czenie z baz? danych, różnego rodzaju zasoby JMS służ?ce do obsługi komunikacji z użyciem kolejek, czy też obiekty EJB (session bean, entity bean). Wszystkie te obiekty będ? bardziej szczegółowo omówione w kolejnych rozdziałach. Poza usługami nazewniczymi dostarczanymi wraz z serwerami aplikacji istniej? inne implementacje tych usług zgodne z interfejsem programistycznym JNDI, które można wykorzystać we własnych aplikacjach. Do najbardziej znanych tych implementacji można zaliczyć t? opart? na usłudze katalogowej LDAP, czy tez opart? o płaskie pliki. Znaj?c ten interfejs programistyczny nie ma również przeszkód aby napisać własn? implementację usługi nazewniczej JNDI. Należy w takim przypadku zaimplementować odpowiednia klasę, która będzie obsługiwała operacje zgodne z API JNDI, takie jak, dodawanie, usuwanie, przeszukiwanie, czy tez pobieranie obiektów i zamieniała je na operacje na wewnętrznym repozytorium. Za przykład można tu przytoczyć bazodanow? implementacje JNDI. W takim przypadku zewnętrzne wywołania API JNDI będ? musiały być zamienione na operacje SQL na bazie danych.<br><br>Poł?czenie z usług? JNDI
Pobranie obiektu z JNDI


Poł?czenie z usług? JNDI

Do poł?czenia do usługi nazewniczej JNDI wystarczy znać położenie szukanej usługi oraz rodzaj takiej usługi. Do okre?lenia tych parametrów używamy dwóch pól klasy Context z pakietu javax.naming. Pierwsze pole INITIAL_CONTEXT_FACTORY okre?la klasę implementuj?c? poł?czenie do usługi nazewniczej. Drugie pole PROVIDER_URL okre?la położenie usługi. W poniższym przykładzie nasza usługa będzie serwowana przez zwykły system plikowy (klasa com.sun.jndi.fscontext.RefFSContextFactory), a położenie usługi okre?la plik /usr/share/JNDI. Dla innego rodzaju usługi, np. serwowanej przez serwer LDAP pole INITIAL_CONTEXT_FACTORY będzie zawierało klasę implementuj?ce taka usługę, a pole PROVIDER_URL będzie okre?lało serwer i port serwera LDAP.<br><br> <font class=code> String icf = "com.sun.jndi.fscontext.RefFSContextFactory";<br> String url = "file:///usr/share/JNDI";<br> Hashtable env = new Hashtable();<br> env.put(Context.INITIAL_CONTEXT_FACTORY, icf);<br> env.put(Context.PROVIDER_URL, url);<br> Context ctx = null;<br> try {<br> ctx = new InitialDirContext(env);<br> } catch (NamingException nx) {<br> ...<br> }<br> </font>


Pobranie obiektu z JNDI

Do pobrania obiektu z serwera nazewniczego używamy metody lookup  klasy Context z pakietu javax.naming. Jako parametr tej metody podajemy nazwę zarejestrowanego obiektu, a zwracany obiekt należy zrzutować na klasę jak? się spodziewamy otrzymać. Poniższy przykłada ilustruje t? operacje.<br><br> <font class=code> ...<br> try {<br> System.out.println("Creating JNDI objects... ");<br> <br> QueueConnectionFactory connectionFactory =<br> (QueueConnectionFactory) ctx.lookup("QCF");<br> Queue queueIN = (Queue) ctx.lookup("QIN");<br> Queue queueOUT = (Queue) ctx.lookup("QOUT");<br> ctx.close();<br> } catch (NamingException nx) {<br> System.out.println("ERROR: " + nx);<br> System.exit(-1);<br> }<br> </font>


XML

XML, Extensible Markup Language, to metajęzyk, w którym nie sprecyzowano ani zestawu znaczników ani jego gramatyki. W swojej budowie przypomina on język HTML służ?cy do budowy stron internetowych jednak czemu innemu ma on służyć i inne jego cechy spowodowały jego popularno?ć. Mówi?c, że XML nie ma sprecyzowanego zestawu znaczników ani gramatykę chciałem zwrócić uwagę wła?nie na jego uniwersalno?ć. Stanowi on pewnego rodzaju szkielet z opisanymi zasadami jakimi ma się rz?dzić, ale w taki sposób aby go nie ograniczać i aby nie stał się standardem wykorzystywanym w niszowych rozwi?zaniach. Tak jak język HTML posiada on znaczniki i ewentualne możliwe atrybuty tych znaczników. Zasadnicz? różnic? jest to, że kiedy w przypadku HTML mamy z góry zdefiniowan? listę znaczników, np., <BODY>, czy też <TABLE>, w przypadku XML mamy pełn? dowolno?ć w nazewnictwie znaczników, np. <FAKTURA>, <NAZWISKO> . Drug? różnic? jest to, że w przypadku HTML każdy znacznik jest tak samo interpretowany i może zawierać elementy prezentacji, jak i konkretnych danych. W przypadku XML zawiera on znaczniki opisuj?ce tylko i wył?cznie dane i jak jest on interpretowany zależy od systemów wymieniaj?cych pomiędzy sob? dane w postaci XML. Zbiega się to z postulatem odseparowywania w aplikacjach warstwy prezentacji od danych. Przykładowe dane XML mog? mieć postać:<br><br> <font class=code> <faktura><br>             <numer>123</numer><br>             <data>01.01.2005</data><br>             <nabywca><br>                         <imie_nazwisko>Jan Kowalski</imie_nazwisko><br>                         <ulica>Prosta 8</ulica><br>                         <miasto>ŁódĽ</miasto><br>                         <kod>91-000</kod><br>             </nabywca><br>             <pozycje_faktury><br>                         <pozycja id='324'><br>                                 <nazwa>zegarek</nazwa><br>                                 <ilosc>2</ilosc><br>                                 <cena>250</cena><br>                         </pozycja><br>                         ...<br>             </pozycje_faktury><br> </faktura><br> </font> <br><br> W przypadku XML każdy znacznik otwieraj?cy musi mieć odpowiadaj?cy znacznik zamykaj?cy, znaczniki mog? być zagnieżdżone (zawierać wewn?trz siebie inne znaczniki) lecz nie mog? być "skrosowane" w postaci <font class=code><a><b></a></b></font>. Dokument XML musi mieć tylko i wył?cznie jeden główny znacznik, natomiast może zawierać nagłówkowe znaczniki META opisuj?ce dokument takie jak strona kodowa itp.<br><br>DTD
XML Schema
XSL
XML JAVA API


DTD

Niekiedy ta dowolno?ć standardu XML stanowi pewnego rodzaju ograniczenie i wskazane jest aby bardziej szczegółowo zdefiniować co może zawierać dokument XML. Do tego celu służy DTD (document type definition) czyli definicja typu dokumentu. Definicja DTD stanowi odrębny plik, do którego następuje wskazanie w dokumencie XML lub stanowi czę?ć dokumentu XML. Za jego pomoc? można okre?lić, jakie  znaczniki mog? się pojawić w dokumencie, czy też jak? warto?ć może mieć dany atrybut. Aby poinformować parser XML, że plik powinien być zwalidowany pod k?tem zgodno?ci z defnicj?   znajduj?c? się w zewnętrznym pliku w pocz?tkowej fazie dokumentu XML należy umie?cić  znacznik:<br><br> <font class=code><!DOCTYPE glowny_tag_XML SYSTEM  plik_z_definicj? .dtd></font> <br><br> Przykładowy plik DTD może mieć postać:<br><br> <font class=code> <!ELEMENT product-catalog (product+)> <br> <!ELEMENT product (description+, price+)><br>         <!ATTLIST product <br>                 sku ID #REQUIRED <br>                 name CDATA #REQUIRED<br>         ><br> <!ELEMENT description (#PCDATA)> <br>         <!ATTLIST description <br>         locale CDATA #REQUIRED<br>         ><br> <!ELEMENT price (#PCDATA)><br>         <!ATTLIST price <br>                 locale CDATA #REQUIRED <br>                 unit CDATA #REQUIRED<br>         ><br> </font><br> Zapis ten oznacza że:<br><br> -        znacznik  product-catalog zawiera jedno lub więcej wyst?pień znacznika product,<br> -        znacznik  product zawiera jedno lub więcej wyst?pień znacznika description oraz jedno lub, więcej wyst?pień znacznika price,<br> -        każdy znacznik product musi zawierać atrybut sku i name,<br> -        każdy znacznik description musi zawierać atrybut locale,<br> -        każdy znacznik price musi zawierać atrybut locale i unit,<br> <br> Dla tak przygotowanego pliku definicji przykładowy plik XML może mieć postać:<br><br> <font class=code> <?xml version="1.0"?><br> <!DOCTYPE product-catalog SYSTEM  product-catalog.dtd><br> <product-catalog><br>         <product sku="123456" name="The Product"><br>                 <description locale="en_US"><br>                         An excellent product.<br>                 </description><br>                 <description locale="es_MX"><br>                         Un producto excellente.<br>                 </description><br>                 <price locale="en_US" unit="USD"> 99.95 </price><br>                 <price locale="es_MX" unit="MXP"> 9999.95 </price><br>          </product><br> </product-catalog><br> </font>


XML Schema

Podczas używania do walidacji dokumentów DTD można szybko zauważyć jego ograniczenia. Kiedy pojawiaj? się bardziej skomplikowane zależno?ci pomiędzy elementami w dokumencie okazuje się, że standard DTD nie wystarcza. Do tego celu służy wła?nie standard XML Schema. Rozwija on możliwo?ci DTD i w zasadzie wypiera go z użycia pozwalaj?c na dziedziczenie ograniczeń i zastosowanie skomplikowanych reguł weryfikacji dokumentu. Bardzo precyzyjnie można w nim okre?li ograniczenia zarówno dla typów prostych, jak i złożonych.<br><br> Standardowo XML Schema ma w sobie wbudowane podstawowe typy danych jakie mog? pojawić się w dokumencie, takie jak xsd:decimal, xsd:string, itp. oraz pozwala na tworzenie rozbudowanych typów danych, w skład których wchodz? typy proste. Przykładowy plik XSD dla dokumentu product-catalog może mieć postać:<br><br> <font class=code> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"><br>         <xsd:element type="product-catalog"/><br>         <xsd:complexType name="productCatalog"><br>                 <xsd:element type="productType" minOccurs="1"/><br>         </xsd:complexType><br>         <xsd:complexType name="productType"><br>                 <xsd:element name="description" type="xsd:string" minOccurs="1"><br>                         <xsd:attribute name="locale" type="xsd:string"/><br>                 </xsd:element><br>                 <xsd:element name="price" type="xsd:decimal" minOccurs="1"><br>                         <xsd:attribute name="locale" type="xsd:string"/><br>                         <xsd:attribute name="unit" type="xsd:string"/><br>                 </xsd:element><br>                 <xsd:attribute name="sku" type="xsd:decimal"/><br>                 <xsd:attribute name="name" type="xsd:string"/><br>         </xsd:complexType><br> </xsd:schema><br> </font><br> Poza standardowymi możliwo?ciami walidacji akie posiada DTD XML Schema poszerza je o ograniczenia co do kolejno?ci występowania elementów w dokumencie, limitów na minimalna i maksymalna ilo?ć wyst?pień, warto?ci domy?lnych itp.<br><br>


XSL

Technologia XSL pozwala w przypadku, kiedy mamy odseparowan? w aplikacji warstwę danych od prezentacji, w łatwy sposób wygenerować na podstawie dokumentu z danymi oraz szablonu prezentacji sformatowane dane wyj?ciowe. Takie rozwi?zanie pozwala w łatwy sposób na podstawie identycznych danych przygotowywać różnie przygotowane prezentacje. Najprostszym przykładem dla aplikacji internetowych będzie sytuacja, kiedy maj?c dane do zaprezentowania będziemy chcieli inaczej te dane zaprezentować klientowi. W przypadku klienta, który odwołuje sie do aplikacji ze zwykłej przegl?darki WWW wygenerujemy dla niego kod HTML, zawieraj?cy dane a poza nimi obrazki i inne elementy graficzne. W przypadku klienta, który będzie się odwoływał do tej samej aplikacji za pomoc? prostego aparatu komórkowego, zostanie dla niego wygenerowany dokument WML, który ze względu na zdecydowanie mniejsz? ilo?ć danych jakie takie aparaty mog? przetworzyć, będzie zawierał w większo?ci tylko same dane z mał? tylko ilo?ci? znaczników WML. Standard ten pozwala swobodnie generować wyj?ciowe dane. Poza zwykłym umieszczeniem danych XML w szablonie XSL posiada on instrukcje warunkowe, pętle, zmienne globalne i lokalne, które w szablonie można używać i wiele innych rozwi?zań.<br><br> Przykładowy dokument XSL może mieć postać:<br><br> <font class=code> <?xml version="1.0"?> <br> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><br> <xsl:template match="/"><br> <html><br> <head><title>My Products</title></head><br>         <body><br>         <h1>Products Currently For Sale in the U.S.</h1><br>         <xsl:for-each select="//product"><br>                 <xsl:value-of select="@name"/> : $<br>                 <xsl:value-of select="./price[@unit='USD']"/> USD<br>         </xsl:for-each><br>         </body><br> </html><br> </xsl:template><br> </xsl:stylesheet><br> </font><br> Przykładowy kod JAVA, którego zadaniem jest transformacja pliku XML i XSL może mieć postać:<br><br> <font class=code>                 StringReader xmlStream= new StringReader(xml);<br>                 StringReader xslStream= new StringReader(xsl);<br>                 <br>                 Source xmlSource= new StreamSource(xmlStream);<br>                 Source xslSource= new StreamSource(xslStream);<br>                 <br>                 TransformerFactory tf = TransformerFactory.newInstance();<br>                 Transformer transformer =tf.newTransformer(xslSource);<br>                 transformer.transform(xmlSource, new StreamResult(out));<br> </font><br>


XML JAVA API

W przypadku API JAVA rozróżniamy dwa rodzaje parsowania dokumentu XML, SAX oraz DOM. Jako parsowanie rozumie się rozbicie dokumentu na jego składowe i opeacje na danych w nim się znajduj?cych. Wymienione sposoby zaimplementowane w parserach XML różni? się pod wieloma względami i przystosowane s? do innego rodzaju dokumentów XML. Odróżnia ich sposób w jaki operuj? na dokumencie i co za tym idzie różni? sie wydajno?ci?.<br><br>SAX
DOM


SAX

W przypadku parsera SAX (Simple API for XML) mamy do czynienia z podej?ciem zdarzeniowym w pasowaniu dokumentów XML.  Podczas parsowania dokumentu występuj? zdarzenia z nim zwi?zane takie jak rozpoczęcie parsowania, pojawienie sie otwieraj?cego tagu znacznika, pojawienie się warto?ci danego znacznika, itp. Zadaniem programisty jest wył?cznie zaimplementowanie we własnej klasie metod odpowiedniego interfejsu, które wywoływane s? w przypadku pojawienia sie odpowiednich zdarzeń XML. Ze względu na swoje podej?cie zdarzeniowe parser ten nie zużywa dużej ilo?ci pamięci, ponieważ nie przechowuje w pamięci całego dokumentu XML, tylko jego mały fragment zwi?zany z obsług? danego zdarzenia. Parser ten działa w oparciu o model sekwencyjny, gdzie nie ma możliwo?ci swobodnego dostępu do dokumentu XML i trzeba brać to od uwagę, ponieważ w pewnych okoliczno?ciach jest to zalet?, a w pewnych wad?. Zaleta jest taka, że ze względy wła?nie na orientację zdarzeniow? i mał? konsumpcję pamięci będzie to do?ć wydajny parser. Jego wad? będzie z tego samego powodu wła?nie brak możliwo?ci swobodnego dostępu do dokumentu XML. Je?li  parser w danym momencie będzie w trakcie wywołania metody implementuj?cej rozpoczęcie danego znaczniki, nie mamy w tej metodzie dostępu do informacji o znaczniku poprzednim, następnym, jego rodzicu, czy też znacznikach w nim zawartych. Metoda SAX często również jest stosowana, kiedy struktura dokumentu XML nie jest ?ci?le okre?lona.<br><br> Aby przeparsować dokument XML można posłużyć się poniższym przykładem:<br><br> <font class=code> SAXParser parser = new SAXParser();<br> parser.setContentHandler(xmlHandler);<br> InputSource iSrc= new InputSource(new java.io.StringReader(xml_data));<br> parser.parse(iSrc);<br> </font> <BR> W przykładzie tym maj?c dane xml w zmiennej  xml_data dokonano parsowania tych danych za pomoc? własnej klasy xmlHandler. Klasa ta powinna implementować interfejs org.xml.sax.ContentHandler. Ciekawsze metody jakie taka klasa powinna zaimplementować to:<br><br> <font class=code>public void characters (char ch[], int start, int length)</font><br>
-        char ch[]: zawarto?ć tagu,<br> -        int start: pocz?tek w tablicy,<br> -        int length: ilo?ć znaków<br> <BR> Metoda wywoływana kiedy parser napotka warto?ć danego tagu, np. dla dokumentu <data>My data</data> metoda będzie wywołana je?li parser napotka warto?ć "My data".<br><br> <font class=code>public void startElement ( String namespaceURI, String localName, String qName, Attributes atts)</font><br>
-        String namespaceURI: przestrzeń nazw danego znacznika,<br> -        String localName:nazwa lokalna lub pusty łańcuch je?li nie było przestrzeni nazw,<br> -        String qName: nazwa znacznika,<br> -        Attributes atts: tablica atrybutów<br> <BR> Metoda wywoływana, kiedy napotkano pocz?tek znacznika XML, np. <data name="person">.<br><br> <font class=code>public void endElement (String namespaceURI, String localName, String qName)</font><br>
-        String namespaceURI: przestrzeń nazw danego znacznika,<br> -        String localName:nazwa lokalna lub pusty łańcuch je?li nie było przestrzeni nazw,<br> String qName: nazwa znacznika<br> <BR> Metoda wywoływana, kiedy napotkano koniec znacznika XML, np. </data>.<br><br> <font class=code>public void startDocument()</font><br>
Metoda wywoływana, kiedy napotkano pocz?tek dokumentu XML.<br><br> <font class=code>public void endDocument()</font><br>
Metoda wywoływana, kiedy napotkano koniec dokumentu XML.<br><br> Przykładowy kod parsuj?cy dokument za pomoc? SAX może mieć postać:<br><br> <font class=code> import java.util.*;<br> import org.apache.xerces.parsers.SAXParser;<br> import org.xml.sax.*;<br> <br> public class XMLProcessor implements ContentHandler <br> {<br>         public static void main(String args[]) throws Exception {<br>         XMLProcessor processor = new XMLProcessor();<br>         processor.execute("<a><b>sssssssssssss</b><c>ABC</c></a>");<br>         }<br>         <br>         public void execute(String indata) throws Exception<br>         {<br>         SAXParser parser = new SAXParser();<br>         parser.setContentHandler(this);<br>         InputSource iSrc= new InputSource(new java.io.StringReader(indata));<br>         parser.parse(iSrc);<br>         }<br> <br>         public void characters(char[] arg1, int arg2, int arg3) <br>         throws SAXException {        <br>         System.out.println("" + new String(arg1, arg2, arg3) );<br>         }<br> <br>         public void startPrefixMapping(String tmp1,String tmp2)<br>         throws SAXException {<br>         }<br> <br>         public void endPrefixMapping(String tmp1,String tmp2)<br>         throws SAXException {<br>         }<br>         <br>         public void processingInstruction(String tmp1,String tmp2)<br>         throws SAXException {<br>         }<br> <br>         public void endDocument() <br>         throws SAXException {<br>         }<br> <br>         public void endElement(String arg1,String arg2,String arg3) <br>         throws SAXException {<br>         }<br> <br>         public void ignorableWhitespace(char[] arg1, int arg2, int arg3)<br>         throws SAXException {<br>         }<br>                 <br>         public void startDocument() <br>         throws SAXException {<br>         }<br>         <br>         public void startElement(<br>         String namespaceURI, String localName, String qName, Attributes atts)<br>         throws SAXException {<br>         System.out.println("<"+qName+">");<br>         }<br> <br>         public void endPrefixMapping(String prefix) <br>         throws SAXException {<br>         }<br> <br>         public void skippedEntity(String name) <br>         throws SAXException {<br>         }<br> <br>         public void setDocumentLocator(Locator locator) {<br>         }<br> }<br> </font> <br><br>


DOM

Metoda DOM (Documen Object Model) parsowania dokumentów XML stanowi zupełnie inne podej?cie niż to zaprezentowane w przypadku metody SAX. Parser dom wczytuje do pamięci cały dokument, a następnie tworzy na jego podstawie drzewo obiektów reprezentuj?cych ten dokument. Obiekt reprezentuj?cy takie drzewo jest przez parser zwracany, a programista może swobodnie przechodzić pomiędzy elementami dokumentu XML, odczytywać jego zawarto?ć, dokonywać operacji na drzewie poprzez dodawanie, modyfikację i usuwanie tagów XML, ich warto?ci, czy też atrybutów. Daje to duża swobodę, jednak ma to swoje często bardzo istotne wady. Metoda ta w porównaniu do metody SAX jest zdecydowanie mniej wydajna i bardziej pamięciożerna wła?nie ze względu na konieczno?ć przechowywania w pamięci całego dokumentu oraz generowania drzewa XML. Z tego powodu metoda ta nadaje się raczej do obsługi małych rozmiarów dokumentówXML i kiedy niezbyt zależy nam tym aby dokument był bardzo szybko sparsowany.<br><br> Przykład aplikacji parsuj?cej dokument za pomoc? metody DOM może mieć postać:<br><br> <font class=code> import javax.xml.parsers.DocumentBuilderFactory;<br> import javax.xml.parsers.DocumentBuilder;<br> import org.w3c.dom.Document;<br> import java.io.File;<br>         <br> public class JAXPandDOM {<br>         <br>         public static void main(String[] args) <br>         { <br>                 try { <br>                 DocumentBuilderFactory factory = <br>                 DocumentBuilderFactory.newInstance(); <br>                 DocumentBuilder builder = factory.newDocumentBuilder();<br>                 File ourExample = new File("product-catalog.xml"); <br>                 Document document = builder.parse( ourExample );<br>                 } <br>                 catch (Exception e) <br>                 { <br>                 System.out.println(e.getMessage()); <br>                 } <br>         } <br> }        <br> <br> </font> W powyższym przykładzie obiekt document będzie zawierał reprezentację całego dokumentu XML w postaci drzewa. <br><br>


EJB

Komponenty EJB (Enterprise Java Beans) s? programowalnymi komponentami umieszczanymi na serwerze aplikacji i zarz?dzanymi przez kontener EJB. Komponenty te odpowiadaj? za logikę aplikacji udostępniaj?c zasadnicze jej funkcjonalno?ci dla innych warstw aplikacji lub zupełnie na zewn?trz zdalnym klientom. W uproszczeniu s? to klasy JAVA, w których okre?lili?my, że pewne kluczowe ich metody mog? być wywoływane zdalnie. Ważn? cech? ze względu na bezpieczeństwo jest tu to, że możliwo?ć wywołania konkretnej metody nie oznacza, że strona wywołuj?ca zna jej implementacje. Dla strony wywołuj?cej znana jest tylko nazwa metody, argumenty metody i warto?ć zwracana. Cała implementacja znajduje sie na serwerze i jest dla strony wywołuj?cej nieznana. Komponenty EJB można uznać za pewnego rodzaju usługi rezyduj?ce na serwerze. Z punktu widzenia programisty komponenty te upraszczaj? proces tworzenia aplikacji. Dla przykładu w przypadku aplikacji bankowej takim ewentualnym komponentem EJB może być komponent zwracaj?cy informacje o kliencie. W takim przypadku możemy taki komponent napisać raz i umie?cić na serwerze aplikacji, a następnie jego funkcjonalno?ć wykorzystywać w innych aplikacjach danego banku. Dodatkowo, przy takim rozwi?zaniu, maj?c dostęp już do istniej?cego EJB, programista nie musi się martwić o logikę aplikacji i dostęp do informacji zwracanych przez konkretny komponent EJB (to wykonywane jest w kontenerze EJB), tylko o zaprezentowanie pobranych danych klientowi.<br><br> W przypadku aplikacji wykorzystuj?cej t? technologię istnieje łatwo?ć ich skalowania. Kiedy zwiększy się ilo?ć użytkowników korzystaj?cych z aplikacji i wyst?pi? problemy z wydajno?ci? istnieje możliwo?ć zainstalowania komponentów EJB na dodatkowych maszynach co spowoduje rozłożenia obci?żenia. Dodatkowo ze względu na przeniesienie implementacji na serwer aplikacje klienckie s? "odchudzone" i mog? być wywoływane z urz?dzeń o ograniczonych zasobach sprzętowych. Kontener EJB dostarcza mechanizmów transakcyjnych. Oznacza to, że w przypadku aplikacji, które wymuszaj? integracje danych mamy możliwo?ć okre?lenia poziomu izolacji danej metody EJB. Oznacza to, że w ramach jednego komponentu EJB możemy nadawać para użytkownikom do konkretnych jego metod, a nie tylko do samego komponentu. Maj?c taki przykładowy bankowy komponent EJB możemy jego metodę odpowiadaj?c? za otwarcie kredytu udostępnić zwykłemu pracownikowi, natomiast zabronić mu możliwo?ci wykonania metody odpowiadaj?cej za przyznawanie kredytu tego samego komponentu.<br><br> Ważne jest tu też to, że je?li mamy konkretny komponent EJB, nie oznacza to, że mamy zdalnie dostęp do wszystkich jego metod. To, które metody udostępniamy jako zdalne, a które nie okre?lamy na etapie projektowania, a następnie implementacji aplikacji.  Komponent do wykonania swoich zdalnych metod może potrzebować wywołać inn? pomocnicz? metodę tego komponentu, która jest potrzebna do poprawnego jego działania, ale wcale nie musi być udostępniana na zewn?trz.<br><br>Deskryptor EJB
Deskryptor EJB, to specjalny plik XML, zawieraj?cy informacje o komponentach EJB. W pliku tym zapisywane s? odwzorowania pół komponentu EJB na kolumny bazodanowe, relacje pomiędzy nimi. Zawiera on informacje o bazie danych będ?cej repozytorium dla komponentów. Dodatkowo zawiera on zapytania w języku EJB QL wyszukuj?ce komponenty EJB wg zadanego kryterium. <br><br> Rozróżniamy następuj?ce zasadnicze typy komponentów EJB:<br><br>Session
Entity
Message-Driven


EJB Session Bean

Komponent ten odpowiada za dostarczanie odpowiednich usług do zdalnego wywołania. Udostępnia on pewne swoje metody dla klienta, a ten z kolei zdalnie wywołuje dan? metodę, a zadaniem komponentu session jest wykonanie zadania na potrzeby klienta. Istniej? dwa typy takich komponentów bezstanowy (czę?ciej wykorzystywany) i stanowy. <br><br>Stateful Session Beans
W przypadku komponentu stanowego z każdym klientem wywołuj?cym dany komponent zwi?zany jest jego stan, który może być wykorzystany do zapisywania w nim danych sesyjnych zwi?zanych z konkretnym klientem. Występuje tu analogia do sesji HTTP, gdzie również jest ona zwi?zana z konkretnym klientem i przechowuje jego stan. Duż? wad? tych komponentów jest ich wydajno?ć, w zwi?zku z tym, je?li nie ma ku temu poważnych przesłanek w wielu dokumentach zaleca się aby z nich nie korzystać. Powodem problemów z wydajno?ci? jest to, że dla każdego klienta takiego komponentu musi być stworzony odpowiedni obiekt sesyjny przechowuj?cy dane z nim zwi?zane. W przypadku małych aplikacji może to nie stanowić większego problemu, natomiast w przypadku dużych aplikacji, gdzie mamy duż? ilo?ć klientów może to stanowić poważny problem wydajno?ciowy.<br><br>Stateless Session Beans
W odróżnieniu od komponentu stanowego, komponent bezstanowy nie przechowuje żadnych informacji stanowych klienta. Kiedy klient wywołuje dan? metodę EJB wszystkie zmienne instancyjne mog? być oczywi?cie wykorzystywane i przechowywać dane, jednak tylko i wył?cznie w trakcie wywoływania danej metody. Po zakończeniu wywołania metody dane te nie s? już przechowywane i nie mog? być wykorzystane przy kolejnych wywołaniach. W porównaniu do komponentów stanowych  mamy lepsz? możliwo?ć skalowania systemu i zdecydowanie lepsz? wydajno?ć. Dzieje sie tak wła?nie z powodu konieczno?ci przechowywania informacji sesyjnych przez komponenty stanowe. Z tego powodu do obsłużenia takiej samej ilo?ci klientów wystarcza mniejsza ilo?ć komponentów bezstanowych niż stanowych. Dodatkowo, ze względu na to, że komponenty stanowe musz? być zapisywane w pamięciach masowych, a bezstanowe zawsze pozostaj? tylko i wył?cznie w pamięci mamy lepsz? wydajno?ć.<br><br>


EJB Entity Bean

Komponent Entity Bean pełni trochę inn? rolę niż Session Bean. Komponent Entity Bean w odróżnieniu od komponentu session Bean nie udostępnia usług dostępnych zdalnie lecz reprezentuje obiekt biznesowy przechowywany w pamięciach masowych, gdzie najczę?ciej jest to baza danych. Za obiekt biznesowy możemy uznać zamówienie, produkt, klient, fakturę. Taki komponent reprezentowany jest przez klasę, której pola mapuj? sie na odpowiednie kolumny tabeli bazodanowej. Na takim komponencie po wyci?gnięciu go z serwera można wykonywać dowolne operacje poprzez wywołanie odpowiednich metod zmieniaj?cych pola takiej klasy, co z kolei przekłada sie na konkretne operacje bazodanowe typu UPDATE. Poza operacjami modyfikuj?cymi można takie obiekty tworzyć co z kolei spowoduje utworzenie nowego rekordu w tabeli. komponenty Entity za pomoc? specjalnych mechanizmów mog? być łatwo wyszukiwane, a jako rezultat programista może otrzymać komponent reprezentuj?cy jeden rekord bazodanowy lub kolekcje takich obiektów. W przypadku zwracania jednego obiektu  używany jest identyfikator komponentu (Primaty Key) i jest on wykorzystywany analogicznie jak to ma miejsce w przypadku kluczy podstawowych bazy danych. Można uznać, że identyfikator EJB jest obiektow? reprezentacj? klucza podstawowego bazy danych. Dostęp do tych komponentów jest dzielony, więc mog? być wykorzystywane jednocze?nie przez wielu klientów co poprawia wydajno?ć aplikacji. Oczywi?cie kontener EJB zapewnia nam transakcyjno?ć operacji zmieniaj?cych komponent i je?li zaznaczymy poziom izolacji w deskryptorze EJB, to taka transakcyjno?ć będzie zapewniona. Dodatkowo tak samo jak ma to miejsce w relacyjnych bazach danych komponent Entity Bean może być w relacji z innym komponentem, pozycje na fakturze mog? być w relacji z faktur?, produkt z kategori?, itp. Tak? relację można traktować jak bazodanowy klucz obcy. Rozróżniamy cztery podstawowe typy relacji. Nie różni? sie one od standardowych definicji relacji bazodanowy.<br><br> one-to-one : Jest to najprostsza forma relacji oznaczaj?ca, że dany komponent jest w relacji tylko i wył?cznie z jedn? instancj? drugiego komponentu. Dla przykładu możemy tu podać obywatela i jego numer PESEL. Jest to typowa relacja one-to-one.<br>
one-to-many : Jest to relacja oznaczaj?ca, że dany komponent może być w relacji z wieloma instancjami drugiego komponentu.  Przykładem takiej relacji jest faktura i pozycje na niej, gdzie na fakturze może być wiele pozycji.<br>
many-to-one : Jest to relacja będ?ca odwrotno?ci? poprzedniej relacji i oznacza, że  wiele instancji komponentu jest w relacji z jedn? instancj? drugiego komponentu. Dla przykładu pozycje na fakturze s? w relacji tylko do jednej faktury.<br>
many-to-many : Jest to relacja oznaczaj?ca, że  wiele instancji komponentu  może być w relacji z wieloma instancjami drugiego komponentu. Dla przykładu studenci uczestnicz? na wiele zajęć i na zajęcia przychodzi wielu studentów.<br>
<br> Rodzaje komponentów Entity Bean
Ze względu na zarz?dzanie komponentami rozróżniamy dwa rodzaje komponentów Entity, CMP (Container-Managed Persistence) oraz BMP (Bean-Managed Persistence). Różnice pomiędzy nimi dotycz? zarz?dzania ich zapisem do pamięci masowych oraz co za tym idzie ich transakcyjno?ci?. <br><br> W przypadku komponentów CMP zarz?dc? takim jest kontener EJB, na działanie którego programista nie ma wpływu. W takim przypadku to kontener zajmuje sie cache-owaniem danych, zapisem do pamięci masowych oraz transakcyjno?ci?. Programista w takiej sytuacji nie ma możliwo?ci zoptymalizowania operacji bazodanowych, wszystko to się dzieje poza jego kontrol?. Z jednej strony może to być wada lecz z drugiej równie dobrze może to być zaleta. Może to być wada, ponieważ programista jest uzależniony od tego, co zostało już stworzone i nie ma możliwo?ci ingerencji , a przecież wiadomym jest, że wła?nie operacje zapisu do pamięci masowych s? najbardziej obci?żaj?ce. Z drugiej strony może to się okazać duż?   zalet?. Przy takim rozwi?zaniu programista może skupić się tylko na  najistotniejszych aspektach aplikacji i pisaniu jej logiki, natomiast sam? implementacje niskopoziomowych operacji powalaj?cych na przechowywanie komponentów w bazie danych pozostawić innym. Dodatkowo duż? zalet? takiego rozwi?zania jest to, że kontenery EJB s? standardowym modułem każdego serwera aplikacji, a to oznacza, że nie jest wymagane przy zmianach w aplikacji testowanie wła?nie tych operacji, które s? dostarczane z pudełka. Drug? bardzo ważna  zalet? takiego rozwi?zania jest łatwo?ć przeniesienia architektury na inny silnik bazodanowy. Standardowo kontenery EJB s? przystosowane do obsługi okre?lonego rodzaju silników bazodanowych. W takim przypadku mamy pewno?ć, że po zmianie silnika aplikacja dalej będzie pracowała poprawnie.<br><br> Z kolej komponenty BMP s? zarz?dzane w zupełno?ci przez programistę. To programista poza sama logik? musi oprogramować wszystkie operacje niskopoziomowe zwi?zane z przechowywaniem komponentów, pobieraniem ich, uaktualnieniem danych, usuwaniem oraz co najważniejsze musi zarz?dzać transakcyjno?cia tych operacji. Takie stosowanie zalecane jest w zasadzie tylko w wyj?tkowych sytuacjach, ponieważ standardowe mechanizmy kontenera EJB bez większych problemów daj? sobie radę z takimi operacjami odci?żaj?c programistę od programowania niskopoziomowych modułów zwi?zanych z komunikacj? z pamięci? masow?. Istniej? jednak sytuacje, kiedy funkcjonalno?ć dostarczana przez kontener EJB nie wystarcza. Dla przykładu je?li aplikacje chcemy osadzić na silniku bazodanowym, którego kontener nie obsługuje. Większo?ć znanych silników baz danych przez kontenery EJB jest obsługiwana, natomiast zawsze może się zdarzyć sytuacja, że aplikacja używa "specyficznego" silnika bazy danych i operacje dostępu do niego programista musi sam oprogramować. Kolejnym przykładem, kiedy użycie komponentów BMP będzie zasadne jest sytuacja, kiedy do przechowywania danych trwałych o stanie komponentu Entity nie jest używana baza danych, tylko jakie? inne repozytorium, np. LDAP lub kiedy istniej? specyficzne wymagania co do transakcyjno?ci operacji. <br><br>


Komponent MDB (Message-Driven Bean)

W przypadku komponentów Entity i Session mamy do czynienia z synchronicznymi operacjami na komponentach, gdzie w komponentach Entity zmieniamy stan komponentu, a w komponentach Session wywołujemy jak?? usługę. Do operacji asynchronicznych, czyli nieblokuj?cych innych operacji stworzono komponenty MDB. Komponent ten jest wywoływany, do obsługi każdego komunikatu JMS znajduj?cego się w kolejce zwi?zanej z tym komponentem. Konfiguruj?c zasoby serwera aplikacji tworzymy w nim zasób opisuj?cy kolejkę JMS i poł?czenie do tej kolejki oraz korelujemy t? kolejkę za pomoc? odpowiednich procesów nasłuchowych z komponentem MDB. Komponent ten, to klasa JAVA,  implementuj?ca odpowiedni interfejs z najważniejsz? jej metod? onMessage, któr? należy zaimplementować. Metoda ta nie zwraca żadnych warto?ci, a jako argument przyjmuje obiekt Message. Obiekt ten reprezentuje komunikat JMS przeczytany z kolejki. Metoda ta jest uruchamiana dla każdego komunikatu oddzielnie. Aby obsługa tych komunikatów nie odbywała się iteracyjnie, tylko współbieżnie można tak skonfigurować serwer aplikacji aby jednocze?nie można było obsłużyć więcej niż jeden komunikat.<br><br> Przykład implementacji metody onMessage wy?wietlaj?cy przeczytany komunikat JMS, jego nagłówki i dane może mieć postać:<br><br> <font class=code>         public void onMessage(Message inMessage) {<br>                 TextMessage msg = null; <br>                 try { <br>                         if (inMessage instanceof TextMessage) { <br>                         msg = (TextMessage) inMessage; <br>                         System.out.println ("MESSAGE BEAN: Message received: " +                                         msg.getText()); <br>                         } else { <br>                                 System.out.println ("Message of wrong type: " +<br>                                  inMessage.getClass().getName()); <br>                         } <br>                 } catch (JMSException e) { <br>                         e.printStackTrace(); <br>                         mdc.setRollbackOnly(); <br>                 } catch (Throwable te) { <br>                         te.printStackTrace(); <br>                 } <br>         }<br> </font><br>


Konektory J2EE

Konektory J2EE to specjalna technologia pozwalaj?ca na podł?czenie z aplikacji działaj?cej na serwerze aplikacji do innych zewnętrznych systemów za pomoc? standardowego API. Występuje tu pewna analogia do technologii JDBC, gdzie mamy standardowe API, za pomoc? którego możemy podł?czyć sie do większo?ci baz danych. Co różni sterowniki JDBC, to niskopoziomowe kwestie zwi?zane z samym poł?czeniem do bazy danych, a realizowane przez specjalne klasy sterownika niewidoczne dla aplikacji  wykorzystuj?cej dany sterownik JDBC. W przypadku konektorów J2EE mamy również takie ustandaryzowane API, które pozwala na podł?czenie się do takiego zewnętrznego systemu oraz na wykonanie na nim dowolnych operacji. Jako zewnętrzny system rozumiemy duży zewnętrzny zamknięty system, np. system SAP, z którym aplikacja internetowa musi się skomunikować. Tu wła?nie wykorzystywana jest technologia konektorów J2EE. Konektor taki instalujemy na serwerze aplikacyjnym w usłudze nazewniczej, a następnie możemy z niego korzystać w dowolnych aplikacjach. W konektorze takim zaszyta jest logika odpowiadaj?ca za poł?czenie do takiego zewnętrznego systemu i możliwo?ć wykonywania na nim odpowiednich operacji.<br><br>


Technologie portalowe

Technologie portalowe, to do?ć ?wieża technologia i stanowi lekko zmienione spojrzenie na aplikacje internetowe i ich budowę. Portlet jest komponentem aplikacji webowej. Można powiedzieć, że jest to wydzielona pewna funkcjonalno?ć aplikacji, któr? można wykorzystywać na dowolnych stronach WWW w ramach danego Portal serwera. Strona taka umieszczona na serwerze to zbiór portletów. Oczywi?cie bardzo często  jest tak, ze na danej stronie instalowane s? portlety w ramach jednej aplikacji portalowej. Jednak największ? zalet? takiego modularnego tworzenia aplikacji webowych jest to, że na danej stronie można umieszczać portlety nie tylko jednej aplikacji webowej. W takiej sytuacji mamy możliwo?ć dodawania do strony zawieraj?cej portlety jednej aplikacji portlety z innej, która może być w pewien, nawet często luĽny sposób powi?zana z t? pierwsz?. Jako przykład można tu przedstawić aplikacje wy?wietlaj?c? najnowsze informacje gospodarcze. Do strony zawieraj?cej tak? aplikację w bardzo łatwy sposób można dodać np. portlet wy?wietlaj?cy najnowsze informacje giełdowe.<br><br> Od strony programistycznej taki portlet to rozszerzony servlet. Portlet może być w kilku stanach (w danej chwili tylko w jednym):<br><br> View : stan wy?wietlania danych,
Edit : stan wy?wietlania formularza do edycji danych,
Configure : stan wy?wietlania formularza do konfiguracji portleta,
Help : stan wy?wietlania pomocy
<br> Do zadań programisty należy odpowiednie zaimplementowanie metod odpowiadaj?cych konkretnym stanom portleta, doView(), doEdit(), doConfigure(), doHelp().<br><br>


Technologia cienkiego klienta oraz serwery aplikacji

Popularno?ć oprogramowania pracuj?cego w architekturze Klient-Serwer powoduje, że często spotykamy się z instalacjami, w których Uniwersalne Końcówki Sieciowe (zwane także cienkimi klientami lub komputerami sieciowymi) musz? współpracować z takimi programami. <br><br> Klasycznymi przykładami s? rozwi?zania oparte o interfejs oparty o przegl?darkę WWW - chociażby system bankowo?ci elektronicznej dla biznesu niektórych banków lub popularny zintegrowany system SAP.<br><br> Architektura Klient-Serwer wymaga współpracy 2 modułów programowych - serwera, który zazwyczaj pracuje na dedykowanym silnym komputerze i komunikuje się z innymi jednostkami za po?rednictwem sieci lokalnej lub rozległej oraz klienta, którego zadaniem jest realizacja interfejsu użytkownika oraz oczywi?cie komunikacja z serwerem.<br><br> Architektura oparta o model serwera aplikacyjnego pozwala na zabezpieczenie poziomu niezawodno?ci, dostępno?ci, łatwo?ci naprawy i skalowalno?ci wymaganej w intranetach przedsiębiorstw i rozwi?zaniach internetowych. Architektura obejmuj?ca serwer aplikacyjny pozwala:<br><br> -        obsługiwać duże ilo?ci zapytań<br> -        obsługiwać nieprzewidywalne obci?żenia<br> -        utrzymywać wysok? dostępno?ć i niezawodno?ć usług<br> <br>Architektura sieciowa.
Sieć może być zaprojektowana w dwóch, trzech lub więcej warstwach w zależno?ci od ?rodowiska. W przedsiębiorstwie, w którym większo?ć dostępu do informacji jest realizowana wewn?trz firmy, z reguły spotkamy architekturę dwuwarstwow?. Do ?rodowiska wymagaj?cego dostępu z zewn?trz, jak np. w przypadku handlu elektronicznego, bardziej pasuje architektura trójwarstwowa.<br><br> W dwuwarstwowej architekturze serwery aplikacyjne stanowi? warstwę pierwsz?, a serwery baz danych - drug?. Interfejs użytkownika znajduje się na serwerach aplikacyjnych a dane na serwerach baz danych.<br><br> W trzywarstwowej architekturze serwery aplikacyjne ustawione s? w drugiej warstwie, z reguły pomiędzy serwerami WWW stanowi?cymi pierwsz? warstwę, a serwerami baz danych stanowi?cymi warstwę trzeci?. Druga warstwa bywa okre?lana również warstw? aplikacyjn?. <br><br> W takim modelu interfejs użytkownika znajduje się na platformach pierwszej warstwy, cała logika aplikacji biznesowych na drugiej warstwie, a dane przechowywane s? na warstwie trzeciej.<br><br>Serwery aplikacji


Serwery aplikacji

Termin "serwer aplikacyjny" może odnosić się tak do sprzętu, jak i oprogramowania. Oprogramowanie serwera aplikacyjnego stanowi platformę do ?wiadczenia wysokiej jako?ci usług aplikacyjnych dla różnorakich serwerów, klientów i urz?dzeń. <br><br> Wykorzystanie oprogramowania serwerów aplikacyjnych pomaga zmniejszyć stopień komplikacji i rozmiary oprogramowania klientów, oraz zwiększyć wydajno?ć poprzez buforowanie danych i kontrolę nad ich przepływem. Również umożliwia zagwarantowanie bezpieczeństwa danych i użytkowników.<br><br> Serwer aplikacyjny w ujęciu sprzętowym stanowi bazę do przetwarzania danych niezbędnych dla zagwarantowania dostępu klientów do aktualnej informacji. W architekturze sieciowej serwery aplikacyjne znajduj? się pomiędzy serwerami sieciowymi a serwerami obsługuj?cymi bazy danych lub aplikacje produkcyjne, umożliwiaj?c dostęp do tych ostatnich z poziomu przegl?darek.<br><br> Zaprojektowanie architektury sieci z wykorzystaniem serwerów aplikacyjnych w drugiej warstwie jest idealnym rozwi?zaniem kwestii dużego ruchu na wej?ciu-wyj?ciu, nieprzewidywalnych obci?żeń, oraz konieczno?ci zapewnienia stałej dostępno?ci.<br><br> Zalety serwera aplikacyjnego.
Serwer aplikacyjny pozwala rozwi?zać problemy zwi?zane z dostarczaniem usług on-line niezależnie od tego, czy dostęp następuje w ramach intranetu przedsiębiorstwa, czy też z zewn?trz, przez internet, jak w przypadku handlu elektronicznego, czy usług ?wiadczonych przez usługodawców.<br><br> Zbudowanie architektury zawieraj?cej warstwę serwerów aplikacyjnych pozwala na zwiększenie skalowalno?ci, co z kolei umożliwia zredukowanie negatywnego wpływu nagłych skoków w obci?żeniu wej?cia-wyj?cia na dostępno?ć usług. Oznacza to, że klienci mog? szybciej dokonać swoich transakcji, a pracownicy maj? stały dostęp do niezbędnych informacji biznesowych.<br><br> Wykorzystywanie serwerów aplikacyjnych niesie za sob? szereg istotnych korzy?ci: <br><br> -        wykorzystywane końcówki nie różni? się między sob? - pozwala to na ich szybk? wymianę w dowolnym momencie <br><br> -        uaktualniania oprogramowania następuj? jedynie na serwerze aplikacji - nie jest konieczne przeprowadzanie uaktualnień oprogramowania końcówek <br><br> -        osobiste pliki użytkowników (historia, adresy stron, pamięć notatnikowa, poczta elektroniczna itp.) s? przechowywane w ich katalogach domowych na serwerze (lub serwerach) aplikacji. Ułatwia to znacznie wykonywanie kopii awaryjnych, skutecznie ogranicza zagrożenia zwi?zane z wirusami lub innymi zło?liwymi programami oraz znacznie upraszcza organizację systemu pomocy dla użytkowników systemu <br><br> -        pozwala na bardzo proste wprowadzanie nowych programów niezależnie od ich architektury i ?rodowiska systemowego - możemy na przykład równocze?nie korzystać z 2 lub więcej serwerów aplikacji. <br><br> -        znacznie upraszcza się administracja całego systemu - jest ona całkowicie scentralizowana, a więc administrator systemu nie jest zmuszony do konfigurowania pojedynczych stacji roboczych, a je?li zachodzi taka potrzeba może skorzystać z systemu administracji zdalnej.<br><br>


Wydajno?ć

Wiadomo jest, że wydajno?ć aplikacji napisanych w języku JAVA jest gorsza niż wydajno?ć aplikacji napisanych np. w języku C/C++. Dzieje się tak dlatego, że aplikacje napisane w języku C s? kompilowane do kodu maszynowego, natomiast aplikacje JAVA s? kompilowane do pseudokodu, który jest potem interpretowany przez wirtualna maszynę JAVA. Plusem jednak programowania w języku JAVA jest, wydaje się, szybszy development. Należy tu również pamiętać, że nawet najszybszy język programowanie nie pomoże, jeżeli programista zastosuje niewydajny algorytm. Dlatego ja osobi?cie skłaniałbym się ku poprawie wydajno?ci wykorzystywanych algorytmów i zostałbym przy języku JAVA niż zastanawiałbym się nad przej?ciem na inny język programowania celem poprawy wydajno?ci aplikacji. w tej czę?ci postaram się zwrócić uwagę na kilka aspektów programowania w języku JAVA. Umieszczę tu również kilka uwag dotycz?cych ogólnych porad dotycz?cych programowania niezależnie od wykorzystywanego języka.<br><br>* Serwlety i JSP
Tablice
Tworzenie obiektów
W?tki
* Bazy danych
Wyj?tki i obsługa błędów
EJB
Operacje na łańcuchach
Operacje na plikach
Operacje sieciowe
XML
Pętle
WebServices
Sortowanie
Algorytmy
Inne


Wydajno?ć a serwlety i JSP

Kompresja<br>
Standardowo tre?ć stron WWW klientowi przez serwer przesyłanych jest w postaci pełnego tekstu opisuj?cego dan? stronę. Jako, że dane te s? przesyłane przez sieć, która w tej komunikacji zdecydowanie stanowi w?skie gardło wskazane jest aby zmniejszyć ilo?ć danych przesyłanych przez sieć w komunikacji klient - serwer WWW. Wiadomo, że wszystkie dane opisuj?ce stronę s? istotne dla poprawnego jej wy?wietlania nie można tu obci?ć pewna czę?ć strony HTML. Z pomoc? przychodzi nam tu kompresja stron WWW wysyłanych klientowi. Funkcjonalno?ć ta polega na tym, że tre?ć strony WWW przed wysłaniem je jest kompresowana i w takiej postaci trafia do klienta. Po stronie klienta przed wy?wietleniem strona jest rozpakowowana i dopiero wtedy jest wy?wietlana. Mimo że w komunikacji tracimy czas na kompresje i rozpakowywanie danych wydajno?ć wzrasta. Dzieje się tak dlatego, że dane tekstowe, jakim z pewno?ci? jest Ľródło strony WWW, bardzo dobrze się kompresuj? w zwi?zku z czym znacznie zmniejszamy tu ilo?ć danych przesyłanych przez sieć. Należy tu jednak dodać , że to czy dane serwer będzie wysyłał w formie oryginalnej, czy skompresowanej nie zależy tylko i wył?cznie od serwera i jego konfiguracji, ale w większym stopniu od klienta. Je?li serwer posiada funkcjonalno?ć i klient wysyła do tego serwera ż?danie o konkretn? stronę WWW, serwer analizuje nagłówki tego ż?dania w poszukiwaniu nagłówka o nazwie Accept-Encoding. Je?li ten nagłówek zawiera w sobie m.in. łańcuch 'gzip' oznacza to, że klient będzie potrafił obsłużyć skompresowan? tre?ć strony. W przeciwnym razie niezależnie, czy serwer potrafi wysłać skompresowane dane, czy nie, do klienta zawsze wysyłane s? strony w formie nieskompresowanej.<br><br>Fragment kodu serwleta analizuj?cego nagłówki ż?dania klienta i wysyłaj?cego skompresowane lub nieskompresowane dane może mieć postać:<br><br><font class='code'>...<br>Enumeration e = ((HttpServletRequest)request).getHeaders("Accept-Encoding");<br>while (e.hasMoreElements())<br>{<br>String header=(String)e.nextElement();<br>if (header!=null && (header.toUpperCase().indexOf("GZIP")>-1))<br>{<br>//Klient obsługuje skompresowany kontent<br>...<br>setGZIPContent(response)<br>out = new GZIPoutputStream(response.getOutputStream());<br>}<br>else<br>{<br>//Klient NIE obsługuje skompresowany kontent<br>...<br>out= response.getOutputStream();<br>}<br></font><br>Automatyczne przeładowywanie serwletów<br>
W większo?ci kontenerach serwletów mamy możliwo?ć ustawienie parametru konkretnego serwleta okre?laj?cego co jaki czas serwlet ten będzie przeładowywany. Niska warto?ć tego parametru jest przydatna tylko i wył?cznie w ?rodowiskach rozwojowych, gdzie cały czas pracujemy nad serwletem i wskazane jest aby jak najszybciej zmiany poczynione w serwlecie były uwzględnione w kontenerze bez potrzeby resetowania kontenera. W przypadku ?rodowiska produkcyjnego t? funkcjonalno?ć zaleca się wył?czyć lub je?li nie jest to możliwe zaleca się ustawić ten parametru na bardzo duż? warto?ć. W ?rodowisku produkcyjnym nie występuj? zmiany serwletów, więc cykliczne przekompilowania serwletów nie będ? miały sensu. Kompilacja serwleta zajmuje czas i zużycie procesora może to spowodować tylko spadek wydajno?ci co w ?rodowisku produkcyjnym nie jest wskazane.<br><br>Sesje HTTP<br>
Sesje HTTP służ? do przechowywania po stronie serwera stanów klienta potrzebnych do poprawnej pracy aplikacji. Dane te s? zapisywane w jaki? trwały sposób po stronie serwera. Pierwsze załadowanie przez klienta strony będ?cej aplikacj? internetow? powoduje wygenerowanie przez serwer specjalnego unikalnego identyfikatora poprzez który dane klienta będ? identyfikowane. Po tej operacji za każdym razem, kiedy klient odwołuje się do stron aplikacji, przekazuje on wcze?niej wygenerowany przez serwer identyfikator. Może to nast?pić na dwa sposoby. Jednym sposobem jest przekazywanie identyfikatora sesji w nagłówkach HTTP. Drugim sposobem jest przekazywanie tego identyfikatora jako kolejnego argumentu wywołania strony. Dokleja się go na koniec zmiennej QUERY_STRING, okre?laj?cej argumenty wywołania. Przykładem takiej aplikacji wykorzystuj?cej sesje HTTP może być sklep internetowy, gdzie w sesji każdego klienta znajduj? się dane jego bież?cego koszyka na zakupy.<br><br>Wielko?ć sesje HTTP<br>
W sesji można umie?cić dowolny obiekt, na którym można dokonać operacji serializacji oraz deserializacji. ważne jest natomiast aby bardzo uważnie rozważyć wielko?ć tych obiektów umieszczanych w sesji. Ważne jest to ze względu na wydajno?ć. Wiadomo, że im więcej danych , tym dłużej trwa zapisanie ich w jakiej? trwałej pamięci.<br><br>Usunięcie obiektów sesje HTTP<br>
Wskazane jest aby niepotrzebne już obiekty z sesji, czy też całych sesji HTTP usuwać zaraz po tym jak już nie będ? potrzebne. przyspiesza to proces wyszukiwania danych zwi?zanych z dan? sesj? ponieważ pętla wyszukuj?ca nie musi przeszukiwać danych, które już nie s? potrzebne do poprawnej pracy aplikacji. Aby ustawić czas trwania sesji wykorzystujemy metodę:<br><br> <font class='code'>setMaxinactiveInterval(int interval)</font><br><br>Aby całkowicie usun?ć obiekty danej sesji z pamięci trwałej wykorzystujemy metodę:<br><br> <font class='code'>invalidate()</font><br><br>Metody redirect i forward<br>
Porównanie tych dwóch metod nie wymaga zbyt skomplikowanej analizy aby dowieĽć, że bardziej wydajne jest użycie metody forward niż redirect. Dzieje się tak, ponieważ w metodzie redirect, jak sama nazwa wskazuje, występuje całkowite przekierowanie ż?dania, gdzie jeszcze raz przegl?darka musi wygenerować ż?danie do przekierowanego zasobu. W przypadku metody forward mamy do czynienia z wewnętrznym dla serwleta przekierowaniem, którego czas obsługi trwa zdecydowanie krócej.<br><br>HTTPS<br>
Protokół HTTPS jest rozszerzeniem protokołu HTTP o szyfrowanie przesyłanych danych pomiędzy klientem a serwerem. Szyfrowanie to ma na celu niedopuszczenie do podsłuchania przesyłanych danych przez osoby trzecie. Dodatkowo poprzez analizę certyfikatów klient ma pewno?ć, że serwer, z którym się poł?czył nie jest fałszywy. Dodatkowo serwer poprzez analizę certyfikatu klienta może zdecydować o przesłaniu klientowi stronę, o któr? prosił, b?dĽ nie. Ma to szczególne znaczenie w przypadku aplikacji biznesowych (banki oraz sklepy internetowe itp.), gdzie bardzo ważna jest poufno?ć przesyłanych danych<br><br>


Wydajno?ć a bazy danych

W przypadku aplikacji współpracuj?cych z baz? danych należy rozważyć kwestie wydajno?ci zapytań wysyłanych do bazy danych, odpowiedniego projektu bazy danych oraz odpowiedniego projektu aplikacji.<br><br>Pula poł?czeń<br>
W przypadku aplikacji standalone pula poł?czeń nie jest nam potrzebna i nie poprawi wydajno?ci naszej aplikacji. W Przypadku aplikacji internetowej natomiast użycie puli poł?czeń niekiedy może drastycznie polepszyć wydajno?ć. Pula poł?czeń jest magazynem kilku poł?czeń do bazy danych z których aplikacji korzysta podczas swojej pracy. Aby zrozumieć zalety użycia puli poł?czeń postaram się tu przedstawić dwie wersje aplikacji, jedna bez puli, a drug? z pul? poł?czeń. WyobraĽmy sobie aplikacje internetowa, która po kliknięciu na link w przegl?darce wykonuje jakie? operacje na bazie danych. W wersji bez puli poł?czeń po kliknięciu aplikacja ł?czy się z baz? danych, a dopiero następnie wykonuje operacje na bazie danych. W przypadku aplikacji z pul? poł?czeń po kliknięciu aplikacja nie ł?czy się z baz? danych, tylko z puli poł?czeń pobiera już istniej?ce poł?czenie do bazy danych i na tym poł?czeniu wykonuje operacje na bazie danych. Pula poł?czeń najczę?ciej inicjowana jest na starcie aplikacji i wtedy następuje taka ilo?ć poł?czeń na jak? skonfigurowana jest pula poł?czeń. Standardowa implementacja puli poł?czeń polega na uruchamianiu podczas startu pewnej ilo?ci poł?czeń (warto?ć startowa). Je?li aplikacja podczas pracy zaż?da poł?czenia z puli poł?czeń poł?czenie z puli do aplikacji jest zwracane, następnie aplikacja na tym poł?czeniu wykonuje operacje na bazie i kiedy poł?czenie nie jest już potrzebne poł?czenie to zwraca do puli poł?czeń. a wielko?ć puli zmniejsza się o jeden. W przypadku je?li pula poł?czeń jest pusta aplikacja zazwyczaj dokonuje jeszcze kilku prób pobrania poł?czenia z puli i je?li to nie pomoże, to zwraca bł?d. Pula może być pusta ponieważ może tak się stać, że jednocze?nie będziemy mieli wiele ż?dań operacji na bazie danych i przy kolejnym ż?daniu może się okazać iż w danej chwili wszystkie poł?czenia s? używane.<br><br>Klasa PreparedStatement<br>
W większo?ci dokumentów opisuj?cych dobre praktyki w aplikacjach wykorzystuj?cych bazy danych widzimy podpowiedĽ "używaj klas PreparedStatement". W przypadku zwykłej klasy Statement za każdym razem, kiedy chcemy wykonać dane polecenie SQL, przed jego wykonaniem następuje parsowanie oraz sprawdzenie poprawno?ci składni zapytania. W przypadku klasy PreparedStatement wygl?da to zupełnie inaczej. W pierwszej fazie tworzymy obiekt PreparedStatement, który jako parametr przyjmuje zapytanie SQL, w którym zamiast istotnych dynamicznych parametrów zapytania podajemy znak '?'.<br><br><font class='code'> PreparedStatement myPreparedStmt=<br> conn.prepareStatement("select position, name from tab1 where id=? and code=?");<br></font><br> W ten sposób stworzyli?my zapytanie, które tylko jeden raz będzie sparsowane w celu zbadania poprawno?ci zapytania. Każde wykonanie zapytania na bazie danych będzie polegało na przekazaniu do obiektu typu PreparedStatement parametrów zapytania oraz wykonania takie go zapytania bez powtarzania operacji parsowania i weryfikacji poprawno?ci oraz do pobrania odpowiedzi bazy danych.<br><br><font class='code'>...<br> myPreparedStmt.setInt(1, id);<br> myPreparedStmt.setString(2, code);<br> ResultSet rs = myPreparedStmt.executeQuery();<br> while (rs.next()) {<br> position = rs.getLong(1);<br> name = rs.getString(2);<br> ...<br> }<br></font>Warto tu zauważyć, iż do przekazania parametrów zapytania używamy odpowiednich metod setXXX klasyPreparedStatement, do operacji pobrania informacji z bazy danych metod getXXX klasy ResultSet, gdzie XXX okre?la jaki typ obiektów przekazujemy jako parametr lub pobieramy z bazy danych.<br><br>Operacje wsadowe<br>
Aby omówić termin operacje wsadowe podzielę go na dwa w zasadzie oddzielne czę?ci, operacje wsadowe przy czytaniu oraz operacje wsadowe przy zmianach.<br><br>Operacje wsadowe przy czytaniu<br>
Kiedy wysyłamy zapytanie do bazy danych zwracaj?ce wiersze baza do sterownika JDBC nie zwraca od razy wszystkie wiersze, tylko tak? ilo?ć wierszy, jak? ustawimy w odpowiednim parametrze sterownika JDBC, klasy Statement lub ResultSet okre?laj?cym wielko?ć bufora rekordów zwracanych w jednej paczce wysyłanej od bazy do klienta. Nazwa tego parametru zależy od odpowiedniego sterownika JDBC. Za przykład opisania zasada działania sterownika w przypadku przyjmijmy zapytanie SQL zwracaj?ce 1000 rekordów oraz bufor rekordów ustawiony na 50. W takim przypadku pierwsza odpowiedz z bazy będzie zawierała pierwsze 50 rekordów odpowiedzi dopóki będziemy operowali tylko na tych pierwszych 50 rekordach. Je?li odwołamy się do 51 rekordu (rekord spoza bież?cej paczki) sterownik wy?le ż?danie do bazy danych ż?danie przesłanie kolejnej paczki zawieraj?cej rekordy od 51 do 100. Analogicznie będzie to wygl?dało przy kolejnych rekordach aż do osi?gnięcie końca rekordów z odpowiedzi. Widzimy tu, żę przy takiej konfiguracji jak tu przedstawionej odczytanie z bazy wszystkich rekordów odpowiedzi wymaga wysłania do bazy 20 ż?dań (1000/50). Operacje wysyłaj?ce te wewnętrzne ż?dania kolejnych bloków odpowiedzi do bazy dla programisty s? przeĽroczyste. Ważne jest, aby mieć na uwadze fakt istnienia tego parametru oraz zasady pobierania odpowiedzi z bazy danych. W naszym przypadku zmieniaj?c warto?ć bufora rekordów na 512 takich zmniejszymy ilo?ć takich wewnętrznych ż?dań do bazy do 2. Należy wzi?ć pod uwagę, że wielko?ci tego bufora nie można zwiększać do woli. Musimy tu znaleĽć złoty ?rodek pomiędzy ilo?ci? operacji sieciowych, a ilo?ci? pamięci wykorzystywanej do buforowania bloku zwracanych rekordów.<br><br>Aby ustawić wielko?ć bufora rekordów zwracanych podczas ł?czenia się z baz? danych np. w przypadku bazy danych Oracle może mieć postać:<br><br><font class='code'>Properties props= new Properties();<br>props.put("defaultRowPrefetch",256);<br></font><br>W przypadku ustawienia tego parametru za pomoc? klasy Statement lub ResultSet operacja ta ma postać:<br><br><font class='code'>Statement.setFetchSize(int size);<br>ResultSet.setFetchSize(int size);<br></font><br>Operacje wsadowe przy zmianach<br>
Standardowo wysyłaj?c kilka zmieniaj?cych instrukcji SQL do bazy danych jedna instrukcja to jedno odwołanie się do bazy danych. Przy operacjach wsadowych przy zmianach celem zwiększenie wydajno?ci aplikacji instrukcje te wysyłamy za pomoc? jednego odwołania się do bazy danych.<br><br> Przykład takich operacji wsadowych może mieć postać:<br><br><font class='code'>...<br>con.setAutoCommit(false);<br>Statement stm= con.createStatement();<br>stm.addBatch("INSERT INTO TAB1 VALUES('Jan','Nowak',6)");<br>stm.addBatch("INSERT INTO TAB1 VALUES('Adam','Kowalski',12)");<br>stm.addBatch("INSERT INTO TAB1 VALUES('Jacek','Szczepański',15)");<br>int[] ret=stm.executeBatch();<br>...<br>con.commit();<br></font><br>Te same operacje używaj?c klasę PreparedStatement:<br><br><font class='code'>...<br>con.setAutoCommit(false);<br>PreparedStatement pstm= con.prepareStatement("INSERT INTO TAB1 VALUES(?,?,?)");<br>pstm.setString(1,"Jan");<br>pstm.setString(2,"Nowak");<br>pstm.setInt(3,6);<br>pstm.addBatch();<br>pstm.setString(1,"Adam");<br>pstm.setString(2,"Kowalski");<br>pstm.setInt(3,12);<br>pstm.addBatch();<br>pstm.setString(1,"Jacek");<br>pstm.setString(2,"Szczepański");<br>pstm.setInt(3,15);<br>pstm.addBatch();<br>int[] ret=pstm.executeBatch();<br>...<br>con.commit();<br></font><br>Minimalizacja ilo?ci zwracanych danych<br>
Podczas projektowania zapytań SQL należy zwrócić uwagę na to aby pobierać z bazy tylko te informacje, które potem w aplikacji będziemy wykorzystywać. I tak je?li w tabeli tab1 znajduje się 10 kolumn, a my w aplikacji zamierzamy wykorzystywać tylko dwie kolumny zapytanie<br><br><font class='code'>select * from tab1</font><br><br> wydaje się być zdecydowanie nadmiarowe. Zaleca się w takiej sytuacji użycie zapytania precyzuj?cego zwracane dane:<br><br><font class='code'>select col1,col2 from tab1</font><br><br> Dla niektórych wydaje się to może mało istotne jednak w przypadku, kiedy zwracana jest do?c duża liczba rekordów polepszenie wydajno?ci spowodowane zmniejszeniem ilo?ci zwracanych danych będzie z pewno?ci? zauważalne.<br><br>Sterowniki JDBC<br>


Wydajno?ć a operacje sieciowe

Niezależne przetwarzanie ż?dań<br>
Aby omówić ten temat posłużę się przykładem aplikacji serwerowej. Niech będzie to aplikacja serwerowa, która w odpowiedzi na ż?danie klienta wykonuje jakie? długotrwałe operacje i zwraca odpowiedĽ klientowi.<br><br> Jedn? z możliwo?ci realizacji takiej aplikacji serwerowej jest iteracyjna obsługa ż?dań. polega ona na obsłudze w danej chwili tylko jednego ż?dania. W przypadku, kiedy przychodzi kolejne ż?danie  i je?li aplikacja w danym momencie już inne ż?danie jest obsługiwane, każde kolejne musz? czekać na koniec obsługi ż?dania poprzedniego. Może to doprowadzić do niepotrzebnego kolejkowania ż?dań i wydłużenia czasu odpowiedzi serwera.<br><br>Innym rozwi?zaniem jest utworzenie tej aplikacji jako serwer wielow?tkowy. W przypadku takiej architektury serwer, tak jak w poprzedniej opcji oczekuje na ż?dania od klienta. Różnica polega na obsłudze nadchodz?cych ż?dań. Kiedy nadchodzi nowe ż?danie od klienta serwer przekazuje obsługę tego ż?dania do jakiego? pobocznego w?tku pracuj?cego równolegle do głównego w?tku nasłuchuj?cego i powraca do oczekiwania na nowe poł?czenia. W?tki na potrzeby obsługi ż?dań klienta najczę?ciej tworzone s? podczas startu aplikacji i najczę?ciej przechowywane w jakiej? puli w?tków. Odpowiednio dobieraj?c wielko?ć tej puli mamy wpływ na wydajno?ć aplikacji. W przypadku, kiedy pula jest pusta i przychodzi kolejne ż?danie aplikacja zwraca komunikat o błędzie, co zapobiega powstawaniu niepotrzebnego kolejkowania. w takiej sytuacji klient może spróbować jeszcze raz poł?czyć się z serwerem po jakim? czasie.<br><br>


XML

W przypadku wykorzystania XML we własnych aplikacjach poza niezaprzeczalnymi plusami standard ten dostarcza również pewne niedogodno?ci. Należy zwrócić uwagę na fakt, że dokument XML nie jest najprostszy do przeanalizowania. Zawiera on zagnieżdżenia, atrybuty oraz reguły, które musz? być sprawdzone. W zwi?zku z tym wydajno?ć pozostawia tutaj wiele do życzenia. Oczywi?cie najbardziej to widać przy dużym dokumencie XML i przy częstym jego analizowaniu. Wydajno?ć ta jest  różna dla metody SAX i DOM (zdecydowanie na korzy?ć tej pierwszej). Drugi aspekt, to konsumowanie zasobów w przypadku metody DOM, gdzie cały dokument musi być wczytany do pamięci. Zaleca się w zwi?zku z tym zawsze przeanalizowanie, czy XML jest dla aplikacji dobrym rozwi?zaniem. Dla przykładu przesyłanie dużej ilo?ci danych pomiędzy systemami można zrealizować nie za pomoc? XML, tylko np. FTP. <br><br>