Web frameworks do budowy aplikacji zgodnych z J2EE

Wielkość: px
Rozpocząć pokaz od strony:

Download "Web frameworks do budowy aplikacji zgodnych z J2EE"

Transkrypt

1 Wydział Informatyki i Zarządzania kierunek studiów: Informatyka specjalność: Systemy Informacyjne Praca dyplomowa - magisterska Web frameworks do budowy aplikacji zgodnych z J2EE Jacek Panachida słowa kluczowe: Spring MVC JavaServer Faces internetowe szkielety programistyczne krótkie streszczenie: Praca stanowi analizę porównawczą najpopularniejszych internetowych szkieletów programistycznych dostępnych dla platformy Java. Celem pracy jest przedstawienie nowoczesnego środowiska pracy dostosowanego do wytwarzania aplikacji internetowych oraz umożliwienie dokonania wyboru odnośnie używanej ramy projektowej. Promotor: dr Dariusz Król imię i nazwisko ocena podpis Wrocław 2007

2 Spis treści Wprowadzenie Wstęp Ewolucja szkieletów programistycznych Historia i rozwój Wzorce projektowe Rozwiązania alternatywne Architektura Model 1 strona JSP Model 2 centralny kontroler Model komponentowy Zadania szkieletów programistycznych Nowoczesne środowisko pracy programisty Narzędzia integrujące Subversion Maven Eclipse Hibernate Spring Framework Narzędzia testujące Spring Mock EasyMock JUnit Selenium Przegląd internetowych szkieletów programistycznych Struts Architektura Znaczniki Interceptory Implementacja wzorca MVC Spring MVC Obiekt nadzorujący Znaczniki Zasada konwencji Tapestry Zasady Moduły JavaServer Faces Specyfikacja Architektura Składowe Implementacja wzorca MVC Porównanie Spring MVC oraz JavaServer Faces

3 4.1. Architektura Spring MVC JavaServer Faces Podsumowanie Model programistyczny Spring MVC JavaServer Faces Podsumowanie Cykl życia żądania Spring MVC JavaServer Faces Podsumowanie Walidacja i konwersja typów Spring MVC JavaServer Faces Podsumowanie Internacjonalizacja Spring MVC JavaServer Faces Podsumowanie Aplikacja Peclinic Opis aplikacji Wykorzystane technologie Encje bazy danych Moduły aplikacji Petclinic-data Petclinic-core Petclinic-web Zaimplementowana funkcjonalność Eksperymenty z wykorzystaniem aplikacji Petclinic Przebieg badania Fazy implementacji aplikacji Petclinic Badanie wydajności Pomiar metryk kodu Badanie łatwości wprowadzania zmian Badanie dostępności komponentów Triniad Analiza wyników Wydajność Metryki kodu Dostępność komponentów Trinidad Łatwość wprowadzania zmian Podsumowanie Bibliografia

4 Streszczenie Praca stanowi analizę porównawczą najpopularniejszych internetowych szkieletów programistycznych o otwartym kodzie źródłowym, dostępnych dla platformy Java. Celem pracy jest przedstawienie nowoczesnego środowiska pracy dostosowanego do wytwarzania aplikacji internetowych oraz umożliwienie dokonania wyboru odnośnie używanej ramy projektowej. Analizie zostały poddane frameworki Spring MVC oraz JavaServer Faces. Uzyskane wyniki bazują na analizie teoretycznej udostępnionych przez szkielety rozwiązań oraz eksperymentach dokonanych na zaimplementowanej aplikacji służącej do zarządzania kliniką weterynaryjną. Praca zaleca stosowanie Spring MVC w tradycyjnych aplikacjach do zarządzania danymi. Abstract A comaparative analysis of chosen open source web frameworks for Java platform is done. The aim of the thesis is to present modern software enviroment designed for implementing web applications and also to enable making final choice about web framework, which is to be used in developing web application. The subjects of the analysis are Spring MVC and JavaServer Faces. The solution of the problem relies upon theoretical analysis of available framework features and upon underwent experiments on implemented application designed to support managing pet clinic. The thesis indicates Spring MVC application in traditional CRUD web systems. 3

5 Wprowadzenie Jednym z najpopularniejszych zastosowań języka Java jest tworzenie aplikacji internetowych. Początkowo wystarczyły rozwiązania ograniczające się jedynie do zastosowania serwletów 1 w połączeniu ze stronami JavaServer Pages. Szybko okazało się jednak że wzrastające potrzeby rynku wymagają zastosowania bardziej kompleksowych rozwiązań, pozwalających na odciążeniu programisty w wielu aspektach związanych z tworzeniem aplikacji internetowych. Odpowiedzią na rosnące potrzeby rynku oraz chęci uproszczenia procesu wytwarzania aplikacji internetowych stało się stworzenie wielu tzw. ram projektowych (ang. web frameworks). Głównym zadaniem stawianym ramom projektowym jest pomoc programiście w tworzeniu, rozwoju i testowaniu powstającej aplikacji. Aktualnie istnieje ponad 40 szkieletów programistycznych z otwartym kodem dostępnych dla platformy Java, 2 nowe wciąż powstają. Wybór spośród wielu dostępnych ram projektowych nie jest z pewnością prosty. Podczas przeglądu dostępnych opracowań nie napotkałem takiego, które omawia w przedstawionym w pracy zakresie wybrane przeze mnie biblioteki. Niniejsza praca ma za zadanie ułatwić dokonanie właściwego wyboru poprzez przedstawienie oraz porównanie wybranych szkieletów programistycznych. Programista stojący przed wyborem nowego narzędzia pracy zwraca uwagę na wiele aspektów z nim związanych. Zbiera informacje między innymi na temat dojrzałości, dostępności wsparcia społeczności czy popularności rozwiązania. Niniejsza praca stanowi wsparcie w ostatnim stadium podejmowania decyzji, w momencie w którym programista stoi przed wyborem dwóch spośród nich Spring MVC bądź JavaServer Faces. Poprzez analizę teoretyczną wsparcia oferowanego przez wspomniane frameworki autor bada ich przydatność podczas tworzenia aplikacji typu CRUD (ang. create, read, update and delete). W związku z mnogością dostępnych opcji dokonano zawężenia liczby badanych projektów do aplikacji o otwartym kodzie źródłowym, których licencja jest zaaprobowana przez organizację Open Source Initiative 3. Na ostateczny kształt listy miała również wpływ popularność wybranej ramy projektowej, jej dojrzałość oraz dostępność mechanizmów umożliwiających integrację ze Spring Framework 4. Porównanie wybranych ram projektowych zostało dokonane z wykorzystaniem przykładowej aplikacji internetowej zaimplementowanej specjalnie na potrzeby niniejszej pracy magisterskiej. Na jej podstawie został zbadany praktyczny aspekt użycia wybranego szkieletu programistycznego. Praca została podzielona na dwie części, poprzedzone wprowadzeniem. Pierwsza z czę- 1 Komponenty działające po stronie serwera. Specyfikacja dostępna na stronie com/products/servlet. 2 Dane według serwisu Java-Source.net (marzec 2007) dostępnego pod adresem java-source.net. 3 Organizacja zajmująca się promocją oprogramowania open source. 4 Szkielet wytwarzania aplikacji w języku Java dla platformy J2EE. 4

6 ści opisuje teoretyczną stronę związaną z zastosowaniem i działaniem poszczególnych ram projektowych. Druga omawia przebieg oraz wyniki badań przeprowadzonych z zastosowaniem przykładowej aplikacji. Rozdział wprowadzający ma za zadanie zapoznanie czytelnika z historią rozwoju szkieletów programistycznych, wyjaśnia podstawowe pojęcia wykorzystywane w dalszej części pracy. Opisuje stosowane architektury aplikacji internetowych oraz funkcje oferowane przez ramy projektowe. Pierwszy rozdział części teoretycznej został poświęcony zagadnieniom związanym z nowoczesnym środowiskiem pracy programisty aplikacji internetowych z podziałem na narzędzia służące do wytwarzania oraz testowania aplikacji. W kolejnym został dokonany przegląd czterech popularnych szkieletów programistycznych. W następnym rozdziale porównującym wybrane ramy projektowe, Spring MVC oraz JavaServer Faces, zwrócono uwagę na ich architekturę, model programistyczny, cykl życia żądania bądź zdarzenia (w przypadku aplikacji opartej o JavaServer Faces), walidację wraz z konwersją typów wprowadzanych przez użytkownika danych. Ostatnia cześć dotyczy procesu związanego z lokalizacją aplikacji. Część praktyczną rozpoczyna opis przykładowej aplikacji internetowej, jej modułów oraz zaimplementowanej funkcjonalności. Następny rozdział składający sie z dwóch części przedstawia trzy fazy implementacji przykładowej aplikacji, sposób przeprowadzenia eksperymentów oraz wyniki badań wraz ich analizą. Ostatnią część pracy stanowi podsumowanie badań dwóch wybranych szkieletów programistycznych. Mam nadzieję, iż wysiłek włożony przeze mnie w realizację pracy, pozwoli osobą stojącym przed dylematem wyboru właściwej dla nich ramy projektowej na podjęcie prawidłowej decyzji. 5

7 1. Wstęp Niniejszy rozdział stanowi wprowadzenie do tematu szkieletów programistycznych dostępnych dla platformy Java. Pierwsza część przedstawia ewolucję oraz rozwój ram projektowych jak i samych aplikacji internetowych związanych nierozerwalnie z tworzeniem aplikacji internetowych od początków ich istnienia. Dodatkowo prezentuje alternatywne rozwiązania internetowe dostępne dla platformy Java. Następny rozdział stanowi przegląd i opis stosowanych architektur programistycznych, wraz z przedstawieniem jedenego z fundamentalnych wzorców projektowych związanych z internetowymi szkieletami programistycznymi, wzorca Model-Widok-Kontroler. W ostatniej z części opisano podstawowe funkcjonalności, realizowane przez twórców ram projektowych Ewolucja szkieletów programistycznych Wraz z rozwojem technologi World Wide Web okazało się iż statycznie serwowane strony nie spełniają oczekiwań użytkowników. W odpowiedzi powstawały różnorodne technologie umożliwiające zwiększenie dynamizmu prezentowanej treści. Pierwsze rozwiązania wykorzystywały interfejs Common Gateway Interface (CGI), w połączeniu z popularnymi ówcześnie językami programowania, takimi jak C czy Perl. Niewystarczające interfejsy programistyczne (API) dostarczane przez wspomniane opcje czy zbyt mała wydajność działających w ten sposób aplikacji doprowadziły do powstawania nowych, ulepszonych rozwiązań. Równocześnie rosnące potrzeby dotyczące aplikacji, wykorzystującej sieć Internet do swojego działania spowodowała, iż obecnie istnieje wiele gotowych rozwiązań umożliwiających serwowanie dynamicznej treści. Język Java jest tylko jednym z alternatyw pośród stron tworzonych w technologiach takich jak ASP.NET [58], Adobe Flash [1] czy PHP [44] Historia i rozwój Początki istnienia ram projektowych sięgają początków pierwszych aplikacji internetowych [42]. Podstawą działania wszystkich aplikacji napisanych przy wykorzystaniu platformy Java w środowisku webowym są serwlety niewielkie programy działające po stronie serwera, nadające dynamiczny charakter działającej aplikacji. Idea serwletów zrodziła się w 1995 roku, czyli rok przed wydaniem pierwszej wersji języka Java [12]. Pomysłodawcami i pierwszymi realizatorami technologi serwletów byli James Gosling oraz Pavani Diwanji. Pierwsza specyfikacja Java Servlet API nosząca wersję 1.0 powstała w maju 1997 roku. Dwa lata później, wydano specyfikację JavaServer Pages mająca również zastosowanie przy tworzeniu aplikacji internetowych. Różnica pomiędzy serwletami a stronami JSP polega na tym, iż w przypadku serwletów programista skupia się na kodzie języka Java generując odpowiedź w postaci tworzonych, często konkatenowanych napisów, w przypadku stron wykonanych w technologi JavaServer Pages użytkownik tworzy odpowiedź, najczęściej stronę HTML, w której używa wstawek języka Java. Osta- 6

8 tecznie strony JSP są kompilowane do serwletów, zatem jedyna różnica dotyczy sposobu ich tworzenia. Szybko okazało się iż dla wielu programistów, ustandaryzowane rozwiązania są niewystarczające. Jednym z powodów był zbyt mały poziom abstrakcji w stosunku do warstwy protokołu HTTP. Powstała specyfikacja wprowadziła pojęcie żądania (ang. request), odpowiedzi (ang. response) oraz obiektu zwanego serwletem (ang. servlet), odpowiedzialnego za interakcję z użytkownikiem. Dodatkowo wprowadzono do bezstanowego protokołu jakim jest HTTP pojęcie stanowości za pomocą obiektu sesji (ang. session). Możliwe się stało wypisanie odpowiedzi użytkownika wprost z poziomu serwletu wykorzystując odpowiednie metody, fragment przykładowego kodu został przedstawiony na listingu 1.1. Tworzy on odpowiedź o charakterze powitalnym na stronie zatytułowanej Prosty serwlet. Dla przejrzystości kodu zrezygnowano z wymaganej, w poprawnej aplikacji SGML, deklaracji DOCTYPE. 1 public class SimpleServlet extends HttpServlet { 2 public void doget(httpservletrequest req, HttpServletResponse res) 3 throws ServletException, IOException { 4 5 // Ustawiamy typ zwracanego dokumentu (strona HTML) 6 res.setcontenttype("text/html"); 7 8 // Pobieramy strumien do zapisu 9 PrintWriter out = res.getwriter(); // Zapisujemy odpowiedz na wyjscie 12 out.println("<html>"); 13 out.println("<head><title> Prosty serwlet </title></head>"); 14 out.println("<body>"); 15 out.println("<h1> Witaj </h1>"); 16 out.println("</body>"); 17 out.println("</html>"); // Zamykamy strumien, zwracamy odpowiedz 20 out.close(); 21 } 22 } Listing 1.1: Serwlet wysyłający odpowiedź do klienta Zastosowanie serwletów po stronie serwera umożliwia generowanie dynamicznej zawartości w zależności od odebranego żądania skierowanego przez przeglądarkę użytkownika. Zwyczajowo generowaną zawartością jest HTML, ale nie istnieją techniczne ograniczenia do zwracania dowolnej zawartości, takiej jak XML. Serwlety działają w środowisku określanym mianem kontenera serwletów. Kontener serwletów stanowi element pośredniczący pomiędzy serwletem a serwerem internetowym. Zarządza cyklem życia serwletów. Mapuje adresy URL żądań do poszczególnych serwletów w celu ich obsłużenia. Ostatnią z ważniejszych funkcji kontenera jest dbałość o bezpieczeństwo aplikacji internetowej poprzez autoryzację żądań użytkownika. Implementacja serwletu wymaga rozszerzenia abstrakcyjnej klasy HttpServlet z pakietu javax.servlet.http oraz nadpisania co najmniej jednej z jej metod w zależności 7

9 od używanych metod. Prezentowany przykład nadpisuje w klasie SimpleServlet metodę o nazwie doget, zatem serwlet wspiera żądania wysłane z użyciem metody HTTP GET. Listing 1.1 prezentuje działanie serwletu, generującego odpowiedź w postaci kodu HTML. Możemy wyróżnić cztery etapy odpowiedzi: 1. Ustalenie typu zwracanego dokumentu (typ mediów), w naszym przypadku text/html, który jest używany przy zwracaniu dokumentu HTML. 2. Utworzenia strumienia do którego nastąpi zapis zwracanego wyniku. 3. Zapis odpowiedzi do strumienia. 4. Zamknięcie strumienia, czyli wysłanie odpowiedzi o ustalonym typie mediów do klienta. Zamieszczony przykład dobrze obrazuje następujące cechy serwletów w kontekście użycia ich do bezpośredniego wygenerowania odpowiedzi: kod serwletu to kod języka Java pomimo że formatem wyjściowym jest HTML, generacja kodu HTML została rozrzucona po różnych miejscach w pliku, rezultat zastosowania obiektu PrintWriter, sposób formatowania charakterystyczny dla kodu Javy sprawia trudności w zorientowaniu się w strukturze dokumentu i wyklucza zastosowanie edytorów szablonów, następuje wymieszanie kodu odpowiedzialnego za logikę aplikacji z kodem odpowiedzialnym za stworzenie wyglądu strony. W odpowiedzi na zaprezentowane powyżej braki serwletów, opracowano specyfikację JavaServer Pages, która stanowi niejako odwrócenie zasady działania serwletów. Zamiast w środowisku dynamicznym (kodzie Javy) tworzyć statyczną zawartość znaczników HTML, postanowiono zawartość dynamiczną zanurzyć w statycznym języku np. HTML. Listing 1.2 prezentuje różne możliwości zanurzenia kodu Javy w stronie JSP. Linia pierwsza przedstawia definicję zmiennej var. W linii drugiej umieszczono przykład wstawki języka Java (ang. scriptlet), która zostanie wykonana w momencie obsługi żądania. Ostatnia linia prezentuje wyrażenie, które zostanie odzwierciedlone bezpośrednio w generowanym kodzie strony (brak znaku średnika na końcu wyrażenia). 1 <%! int var = 1; %> 2 <% int var1 = 1; int var = 2; int var3 = var1 + var2 %> 3 <%= "numer wizyty " + 1 %> Listing 1.2: Zanurzanie elementów języka Java w stronie JSP Pomimo wprowadzenia technologi JavaServer Pages generowanie widoku wciąż posiadało wadę związaną z przemieszaniem logiki biznesowej z kodem odpowiedzialnym za prezentację danych. Ponadto zawieranie kodu języka programowania, takiego jak np. Java, w znacznikach powodowało, iż twórcy szablonów musieli być obeznani z jego stosowaniem, co często okazywało się niepraktyczne. Wyjściem z sytuacji stało się opracowanie, w wersji JSP 1.1, biblioteki tzw. custom tags, których zadaniem było wydzielenie kodu aplikacji z warstwy widoku i zamknięcie jej w specjalne znaczniki. Najpowszechniej używaną biblioteką znaczników jest JavaServer Pages Standard Tag Library (JSTL), która zawiera w sobie wsparcie między innymi dla: wyrażeń warunkowych, iteracji, internalizacji i lokalizacji, języka zapytań SQL, języka znaczników XML, 8

10 walidacji. Biblioteka JSTL stanowi część platformy J2EE i została opracowana pod nadzorem Java Community Process (JCP). Aktualna wersja wydana w maju 2006 roku nosi numer 1.2. Obecna specyfikacja JEE w wersji 5.0 nie posiada w swoich zasobach opisu ustandaryzowanej ramy projektowej, służącej do budowy aplikacji biznesowych. Jednym ze sposobów pisania aplikacji internetowych z użyciem prostej abstrakcji jest bezpośrednie wykorzystanie serwletów i stron JSP w połączeniu z biblioteką znaczników. Takie podejście ma wiele zalet, jeżeli budujemy prostą aplikację webową. Podczas pracy z większymi systemami wydaje się konieczne skorzystanie z jednego ze szkieletów programistycznych. Opisywane w pracy szkielety programistyczne należą do najliczniejszej grupy tzw. szkieletów specjalizowanych, gdyż skupiają w sobie jedynie wsparcie przy tworzeniu warstwy kodu widoku, pozostawiając pozostałe warstwy tradycyjnej aplikacji trójwarstwowej do dyspozycji programisty. Do frameworków próbujących scalić w sobie wiele warstw należy np. biblioteka Rife [47] czy Roma [52]. Na osobną uwagę zasługuje framework Seam, opracowany przez firmę JBoss, który nazywany jest zaginionym Gralem platformy JEE. Łączy w sobie biblioteki JavaServer Faces (JSF), Facelets, Enterprise Java Beans (EJB3), Java Persistence API (JPA). Ze względu na jego odrębność w stosunku do najpopularniejszych szkieletów specjalizowanych, nie został opisany w pracy Wzorce projektowe Trudność w zarządzaniu kodu nieczytelnego, korzystającego z niejasnych rozwiązań architektonicznych oraz chęć wprowadzenia uniwersalnych, sprawdzonych w praktyce rozwiązań, doprowadziła do stworzenia wzorców projektowych [19]. Wzorce projektowe mają zastosowanie w wielu dziedzinach informatyki, takich jak programowanie aplikacji mobilnych czy sieciowych. Poniższe dwa podrozdziały opisują jedynie najczęściej stosowane wzorce wykorzystywane przy projektowaniu szkieletów programistycznych dla platformy Java w technologi J2EE [40]. Wzorcowi Model-Widok-Kontroler, ze względu na jego szczególne znaczenie, został poświęcony osobny rozdział Front Controller Aplikacje działające w sieci Internet zmuszone są, ze swojej natury, obsługiwać wielu użytkowników jednocześnie. W jednym czasie do systemu napływają żądania klientów realizujących swoje, często odmienne, potrzeby biznesowe. Wzorzec Front Controller [19, strony ] stanowi element, który w sposób scentralizowany nadzoruje napływające żądania do aplikacji. Istnieje również rozwiązanie alternatywne, które stosuje zdecentralizowany sposób obsługi żądań. Przedstawione podejście wprowadza jednak do aplikacji zbędną duplikację kodu związaną z tym, iż każdy widok systemu zmuszony jest do implementacji swojego modułu odpowiedzialnego za przetwarzanie nadchodzących żądań. Ponadto opisywane rozwiązanie komplikuje kwestię nawigacji, gdyż brak jest nadrzędnego elementu, który zarządza poszczególnymi widokami i przełącza użytkownika między nimi. Ostatnią sprawą jest zmniejszona zarządzalność kodu powstałego w ten sposób spowodowana bezpośrednio duplikacją kodu. Zadaniem Front Controllera zaimplementowanego w postaci serwletu, może być między innymi zapewnienie wsparcia dla integracji usług systemowych, pomoc w pozyskiwaniu treści czy zarządzanie samymi widokami i nawigacją między nimi. Zastosowanie elementu centralnego pozwala w elegancki sposób rozwiązać kwestię autoryzacji i uwie- 9

11 Rysunek 1.1: Diagram sekwencji dla Front Controllera w momencie odebrania żądania [19] rzytelnienia w aplikacji jest tylko jedno wejście do systemu. Wykorzystywana strategia pozwala na wielokrotne wykorzystanie widoków pełniących podobną funkcję. Kontrolę nad żądaniami umieszczoną w jednym miejscu systemu można łatwo wykorzystać do logowania działalności użytkowników aplikacji i sprawdzania sposobu przemieszczania się po stronie, co może być szczególne przydatne w sklepach internetowych badających zachowanie swoich klientów. Front Controller stanowi pierwszy punkt styku żądania wysłanego przez użytkownika z tworzoną aplikacją, w związku z tym wykorzystany jest do następujących zadań: odebranie żądania, autoryzacja i uwierzytelnienie, delegacja zadań do innych usług systemowych, wybór odpowiedniego widoku, zarządzanie błędami aplikacji. Użycie scentralizowanego kontrolera pozwala na redukcję kodu Javy zawartego w stronach widoku. Rysunek 1.1 przedstawia diagram sekwencji w momencie odebrania żądania od użytkownika systemu. W interakcji przedstawionej na rysunku biorą udział następujący uczestnicy: Controller pierwszy punkt styku wysłanego żądania z systemem. Zarządza wyborem widoku jaki zostanie przedstawiony użytkownikowi. Może skorzystać z pomocy innego uczestnika np. Helper w celu autoryzacji klienta. Dispatcher odpowiedzialny za zarządzanie widokami i nawigacją między nimi. Decyduje o wyborze widoku jaki zostanie przedstawiony użytkownikowi. Może stanowić osobny element systemu, jak w opisywanym przypadku, bądź być zawarty w kontrolerze. Używa obiektu RequestDispatcher w celu przekazania sterowania do widoku. Helper odpowiedzialny za pomoc kontrolerowi w jego działaniach. W zależności od systemu jego działanie może być inne, najczęściej jest odpowiedzialny za zbieranie danych potrzebnych do wygenerowania widoku. 10

12 Rysunek 1.2: Diagram sekwencji dla wzorca View Helper w momencie odebrania żądania [19] View reprezentuje wynik działania aplikacji, który otrzymuje klient. Może wykorzystywać uczestnika Helper w celu enkapsulacji związanej z wyświetlaniem danych. Katalog wzorców zawiera dziewięć różnych implementacji wzorca Front Controller. Najpopularniejszy z nich nosi nazwę Servlet Front i bazuje na serwlecie. View Helper Zastosowanie wzorca View Helper ma miejsce podczas wyświetlania treści, która zmienia się w sposób dynamiczny. Częsta zmiana warstwy widoku, powodowana względami biznesowymi, komplikuje się w momencie przemieszania jej z kodem Javy w postaci tzw. scripletów. Rezultatem jest zmniejszenie elastyczności systemu. Nadużycie kodu Javy w warstwie widoku negatywnie wpływa na zarządzalność systemu. Pojawia się tendencja do kopiowania fragmentów kodu na stronach JSP, co prowadzi w konsekwencji od zwiększonej liczby błędów. Wzorzec View Helper promuje separację kodu odpowiedzialnego za logikę aplikacji od kodu związanego z widokiem. Przedstawiany wzorzec polega na oddelegowaniu kodu związanego z logiką biznesową aplikacji do elementów pomocniczych, zaimplementowanych za pomocą komponentów JavaBean bądź poprzez użycie specjalnych tagów tzw. custom tags. Wpływa to pozytywnie na modularyzację aplikacji. Istnieje wiele sposobów implementacji opisywanej idei, najczęściej za element widoku służą strony JSP i jest to w większości przypadków preferowane rozwiązanie. Użycie pomocników ułatwia ponowne wykorzystanie kodu, gdy zajdzie taka potrzeba. Kod umieszczony w widokach można propagować wyłącznie poprzez kopiowanie jego fragmentów, co czyni system trudnym w utrzymaniu, gdyż nawet drobne modyfikacje wymagają zmian w wielu miejscach. Rysunek 1.2 przedstawia diagram sekwencji obsługiwanego żądania dla systemu wykorzystującego wzorzec View Helper. W swojej zredukowanej postaci pozbawionej elementu pomocnika żądanie odebrane od klienta może być skierowane bezpośrednio do widoku, ma to jedynie sens, gdy strona jest w głównej semistatyczna i nie zawiera w sobie dużo kodu Javy. Diagram sekwencji przedstawia następujących uczestników podczas procesu przetwarzania żądania odebranego od klienta: View reprezentuje widok zwracany użytkownikowi systemu. Dynamiczne dane użyte podczas generowania strony pobierane są z modelu, pomocnicy są odpowiedzialni za enkapsulację pobierania i przetwarzania danych. 11

13 Helper jest odpowiedzialny za pomoc uczestnikowi View w wygenerowaniu widoku. Pomocnicy w zależności od rodzaju systemu mogą pełnić różna funkcję, najczęściej gromadzą dane na potrzeby widoku oraz odpowiedniu je przygotowują. Widok może korzystać z wielu pomocników jednocześnie. ValueBean jest to inna nazwa dla pomocnika, którego rola ogranicza się do przechowywania stanu modelu na potrzeby widoku. W typowym zastosowaniu pełni rolę przedstawioną na rysunku 1.2, zwraca żądaną wartość wykorzystując z ustalonej usługi. BusinessService pełni role usługową w stosunku do aplikacji, jego celem jest wykonywanie zadań powierzonych mu przez kontroler. Istnieje sześć różnych implementacji opisywanego wzorca. Preferowaną ze względu na łatwość użycia i zarządzalność jest JavaBean Helper Rozwiązania alternatywne Ważne miejsce w historii aplikacji internetowych miały również aplety. Jest to dosyć skrajny przykład aplikacji internetowej, który polega na tym iż program stworzony z wykorzystaniem J2SE ściągany jest przez przeglądarkę na dysk komputera użytkownika, przy czym działa w kontekście strony internetowej go zawierającej. Pracując z apletem mamy wrażenie pracy z aplikacją napisaną w technologi Swing, wprasowaną niejako w stronę internetową. Aplety są technologicznie młodsze od serwletów ich pierwsza wersja została dostarczona wraz z wersją 1.0 języka Java, w 1995 roku. Należy zaznaczyć iż aplety pomimo działania po stronie klienta są niezależne od platformy sprzętowej i programistycznej na której pracuje użytkownik, jest to bezpośrednia konsekwencja użycia platformy Java, którą główną cechą jest właśnie wieloplatformowość. Do działania apletu w przeglądarce konieczny jest specjalny program tzw. wtyczka. W celu zwiększenia bezpieczeństwa użytkowników aplikacji opartej o aplety, działa ona w specjalnym ograniczonym środowisku zwanym piaskownicą (ang. sandbox), które między innymi nie pozwala na dostęp do zasobów lokalnych. Obecnie aplety po fazie fascynacji nimi przez użytkowników straciły znacznie na popularności. Alternatywami dla nich są wcześniej opisane aplikacje wykorzystujące dynamiczny HTML lub aplikacje napisane z wykorzystaniem Adobe Flash. Kolejnym standardem platformy Java wykorzystywanym w środowisku internetowym jest technologia Java Web Start. Jest to rama projektowa, której pierwsza wersja została opublikowana w marcu 2001 roku, umożliwiająca uruchomienie aplikacji Javy bezpośrednio z poziomu przeglądarki użytkownika. Wraz z wydaniem Java Runtime Environment w wersji 1.4 została standardowo włączona do dystrybucji. W odróżnieniu od wspomnianych wcześniej apletów, pobrany w taki sposób program nie działa w środowisku przeglądarki lecz poza nią. Ma to bezpośredni związek ze wspomnianą piaskownicą, która nie musi być aż tak restrykcyjna jak w przypadku aplikacji opartych o aplety. Programy wykonane w technologi Java Web Start nie posiadają możliwości łatwej komunikacji z przeglądarką, po uruchomieniu, stanowią program który jest nie do odróżnienia ze standardową aplikacją stworzoną z wykorzystaniem Swinga. W celu ułatwienia migracji dopuszczalne jest również uruchomianie aplikacji opartych o aplety w opisywanej technologi. Przy prawidłowo skonfigurowanej przeglądarce, istnieje możliwość uruchomienia aplikacji bezpośrednio ze strony internetowej, po jej automatycznym ściągnięciu na dysk. Elementem odróżniającym aplikacje JWS od apletów jest wykorzystanie specjalnie opracowanego protokołu Java Network Launching Protocol (JNLP), opisującego sposób uruchomienia aplikacji w systemie użytkownika. W przypadku nie posiadania przez użytkownika wymaganej wersji biblioteki uruchomieniowej (JRE), na- 12

14 Rysunek 1.3: Różnorodność technologi platformy Java a środowisko działania stępuje automatycznie jej ściągnięcie i instalacja. Program podczas uruchomienia rezyduje w lokalnej pamięci podręcznej. Najpowszechniejszym zastosowaniem aplikacji wykorzystujących technologię JWS są dema programów, które użytkownik może ściągnąć bezpośrednio na dysk, bez potrzeby instalacji jak również część grubych klientów, gdy istnieje uzasadnienie dla zastosowania opisanej technologi. Wszystkie opisywane wcześniej rozwiązania działają w środowisku internetowym. Na jednym z biegunów są aplikacje napisane za pomocą serwletów, na drugim samodzielne aplikacje oparte na technologi Java Web Start, które wykorzystują sieć jedynie do dystrybucji. Aplikacje internetowe w powszechnej opinii należą do pierwszej ze wspomnianych grup. Czynnikiem różnicującym w tym przypadku jest sposób wykorzystania przeglądarki do pracy z aplikacją. W przypadku systemów opartych o serwlety, przeglądarka jest elementem niezbędnym do pracy z aplikacją. Inaczej przedstawia się ma sprawa związana z apletami. Aplikacje oparte o aplety można uruchamiać w poziomu przeglądarki ale równie dobrze mogą zostać uruchomione z wykorzystaniem programu standardowo dołączonego wraz z Java SE Development Kit (JDK). Kolejną z opisanych technologi jest Java Web Start, w swojej istocie bardzo podobna do idei apletów. Programem służącym do uruchomiania aplikacji tego typu jest javaws, dostarczana standardowo ze środowiskiem uruchomieniowym i operujący na plikach JNLP, opisujących daną aplikację. Rysunek 1.3 przedstawia różnorodność sieciowych technologii wspieranych przez firmę Sun w kontekście zastosowania ich w określonym środowisku. Najbardziej rozpowszechnione aplikacje internetowe swoje działanie ograniczają do przeglądarki, przeglądarka jest im niezbędna do prawidłowego funkcjonowania. Aplety w głównej mierze działają w środowisku przeglądarki, takie jest ich główne zastosowanie, mogą jednak również funkcjonować poza nią, przy użyciu dodatkowego oprogramowania. Ostatnią grupę stanowią aplikacje napisane z wykorzystaniem technologi Java Web Start (JWS), które po uruchomieniu działaja na zasadzie standardowej aplikacji Swing. Protokół JNLP służy im jedynie do dystrybucji Architektura Wraz z upływającym czasem, zmieniało się podejście do tworzenia aplikacji internetowych. Ma to szczególne odzwierciedlenie w architekturze [30], wykorzystywanej przez 13

15 projektowane szkieletety programistyczne. Ewolucja była związana również z postępem technologicznym, dopiero wydanie JavaServer Pages, w dwa lata po pierwszej specyfikacji Java Servlet API, wraz w połączeniu z biblioteką JSTL pozwoliło na rzeczywiste odseparowanie poszczególnych warstw aplikacji a tym samym na opracowanie najdogodniejszej architektury aplikacji, wykorzystywanej po dzień dzisiejszy. Niniejszy rozdział prezentuje modele aplikacji związane z projektowaniem aplikacji webowych, począwszy od stosowanych najwcześniej Model 1 strona JSP Architektura aplikacji stosująca Model 1 jest najprostszą z opisywanych. Serwlet bądź strona JSP odbierająca żądanie jest odpowiedzialna za wszelkie przetwarzanie prowadzące do zwrócenia odpowiedzi użytkownikowi aplikacji. W typowej aplikacji omawiane zadania sprowadzają sie do: odebrania i przetworzenia żądania, walidacji danych, przeprowadzenia procesów biznesowych, wygenerowaniu odpowiedzi. Pomimo swojej prostoty opisywana architektura nie sprawdza się pod względem skalowalności, gdyż znaczący stopień funkcjonalności jaką oferuje porozrzucana jest po wielu duplikujących się plikach jsp. Ponadto przedstawiany model niepotrzebnie miesza logikę biznesową i logikę prezentacji aplikacji. Trudno jest wprowadzić w aplikacji budowanej według Modelu 1 nową, odmienną warstwę widoku, np. w postaci XML-a, gdyż oznaczałoby to duplikację logiki biznesowej w stosunku do systemu opartego o stary widok np. HTML. Pewną modyfikację Modelu 1 wprowadza użycie obiektów JavaBean, których zagnieżdżenie w kodzie strony JSP sprawia, iż logika biznesowa zostaje oddzielona w znacznym stopniu od logiki prezentacji. Rozwiązanie takie ma jednak pewne wady, związane z dużą ilością kodu Javy umieszczonego w szablonach. Nie ma to takiego dużego znaczenia jak w przypadku pierwotnej wersji Modelu 1 jednak wprowadza pewne zamieszanie, szczególnie w większych firmach gdzie nad aplikacją pracuje wielu grup programistów. W tego typu sytuacjach następuje podział pracy pomiędzy programistami a twórcami szablonów, jeżeli kod szablonu zawiera w sobie dużo kodu języka Javy to stanowi to utrudnienie dla webmastera i jednocześnie rozmywa granicę w odpowiedzialności pomiędzy kodem tworzonym przez programistów i projektantów stron internetowych. Rysunek 1.4 przedstawia architekturę aplikacji opartej o Model 1. Żądanie odebrane od użytkownika aplikacji kierowane jest to strony JSP, która zajmuje się dalszym przetwarzaniem żądania. Operacje na modelu oddelegowywane są do obiektów JavaBean, które są odpowiedzialne za pobranie i przetworzenie modelu. Gotowy model znajduje miejsce w zwracanej odpowiedzi, która zostaje skierowana do przeglądarki użytkownika, który zainicjował żądanie Model 2 centralny kontroler Jednym z niezwykle ważnych aspektów podczas tworzenia aplikacji internetowej jest separacja poszczególnych części aplikacji o różnym przeznaczeniu. Esencją wspomnianej zasady jest wzorzec Model-Widok-Kontroler przedstawiony w dalszej części rozdziału. Zdecydowana liczba frameworków których celem jest pomoc przy tworzeniu aplikacji internetowych, implementują właśnie ten wzorzec. Pouczające może się okazać próba zasto- 14

16 Rysunek 1.4: Architektura aplikacji internetowej według modelu prostego sowania opisywanego wzorca z wykorzystaniem czystych serwletów i stron JSP. Proponowane rozwiązanie bazujące na samych serwletach nie może konkurować pod względem funkcjonalności zastosowania z rozwiązaniem wykorzystującym szkielety programistyczne, jednakże w wielu przypadkach może być wystarczające, dodatkowo pomaga w zrozumieniu zasady działania frameworków dedykowanych. Model 1 ze względu na swoją prostotę, jest stosowany w prostych aplikacjach, natomiast architektury opartej o Model 2 zaleca się używanie w aplikacjach złożonych. Model 2 to w rzeczywistości model wykorzystujący wzorzec projektowy Model-Widok-Kontroler (MVC). W skrócie, praca aplikacji opartej o ten model składa się z serwletu odbierającego i przetwarzającego żądanie oraz decydującego o użytym widoku. Szerzej o wzorcu MVC traktuje następny rozdział. Rysunek 1.5 przedstawia szczegółowo zasadę działania Modelu 2. Żądanie (krok 1) wysłane przez klienta z użyciem przeglądarki internetowej kierowane jest do serwletu ten inicjalizuje potrzebne do pracy obiekty JavaBean (krok 2). Sterowanie zostaje przekazane w następnej kolejności do strony JSP (krok 3), która korzysta z wcześniej przygotowanych obiektów, w celu pobrania danych modelu z bazy danych bądź innego systemu odpowiedzialnego za przechowywanie danych (krok 4 i 5). Kiedy strona jest wypełniona danymi uzyskanymi z modelu następuje odpowiedź systemu (krok 6). Wzorzec Model-Widok-Kontroler Początki zastosowanie wzorca MVC sięgają języka Smalltalk-80. Podstawowym celem wzorca Model-Widok-Kontroler (MVC) jest oddzielenie warstwy widoku związanej z prezentacją interfejsu użytkownikowi a logiką biznesową zwaną również logiką domeny (ang. domain logic). Separacja wspomnianych warstw i ich odpowiedzialności (ang. separation of concerns) sprawia, iż są one niezależnie ma to znaczący wpływ podczas wprowadzania zmian w jednej z nich. Opisywany wzorzec dzieli aplikację na trzy części w zależności od pełnionej w niej funkcji: model, enkapsuluje dane na których operuje aplikacja, widok, odpowiedzilany za pozyskiwanie danych z modelu i prezentacji ich użytkownikowi, kontroler, odpiera i przetwarza żądania korzystając z pozostałych elementów. 15

17 Rysunek 1.5: Architektura aplikacji internetowej według modelu złożonego Przedstawiony wzorzec został zainspirowany mechanizmem przetwarzania informacji, gdzie kontroler reprezentuje wejście, model przetwarzane dane a widok wyjście systemu. Założeniem modelu jest jego niezależność od pozostałych składowych wzorca MVC, widoku i kontrolera. Możliwe jest wykorzystanie jednego modelu w wielu aplikacjach posiadających inne widoki bądź używające innych kontrolerów. Możemy wyróżnić dwa rodzaje modeli, model pasywny i aktywny. W modelu pasywnym obiekty nie mają najmniejszej świadomości uczestniczenia w triadzie MVC. Kontroler informuje widok w momencie dokonania zmian, które powodują konieczność jego aktualizacji. Model pasywny jest najbardziej popularnym modelem w zastosowaniach MVC, szczególnie w aplikacjach internetowych które pracują według cyklu żądanie odpowiedź, aktualizując za każdym razem wyświetlany widok, bez względu na dokonane zmiany. Model aktywny zawiera mechanizm notyfikacji, który pozwala na informowanie pozostałych uczestników triady o zaistniałych zmianach, najczęściej stosując wzorzec Observer. Podejście takie wymaga rejestracji widoku i kontrolera w modelu, jakkolwiek nie ma on świadomości ich istnienia nie narusza to zasad opisywanego wzorca. Widok pozyskuje dane z użyciem modelu i prezentuje je użytkownikowi, reprezentując wyjście aplikacji. Pomimo posiadania dostępu do modelu, widok nie powinien dokonywać w nim żadnych zmian a jedynie dokonywać operacji odczytu. W modelu aktywnym widok ma możliwość rejestracji a tym samym szansę na otrzymywanie informacji o dokonanych w nim zmianach. Kontroler otrzymuje żądania użytkownika i przetwarza je z użyciem modelu i widoku. W standardowej implementacji opisywanego wzorca kontroler wywołuje metody modelu w celu jego uaktualnienia. W modelu aktywnym po dokonaniu zmiany w modelu widok zostaje automatycznie powiadomiony o dokonanych zmianach, w modelu pasywnym zadanie to spoczywa bezpośrednio na kontrolerze. Element kontrolera nie pełni funkcji mediatora pomiędzy widokiem a modelem. Kontroler i widok mają równe prawa w dostępnie do modelu. Rola kontrolera nie polega również na kopiowaniu danych z modelu i osadzaniu ich w widoku a jedynie na informowaniu, w przypadku modelu pasywnego, o aktualizacjach. Rysunek 1.6 przedstawia relacje pomiędzy poszczególnymi składowymi wzorca MVC. Zależność pomiędzy kontrolerem a widokiem jest bezpośrednia. Dane wejściowe użyte 16

18 Rysunek 1.6: Zależności pomiędzy poszczególnymi składowymi wzorca MVC w formularzach mają swoje odzwierciedlenie w prezentowanym widoku. Często się zdarza, iż w wielu szkieletach programistycznych implementujących opisywany wzorzec, widok i kontroler są połączone razem tworząc tzw. Document View. Użycie pasywnego modelu dodaje kontrolerowi zadanie poinformowania widoku o zmianach w nim dokonanych. W wielu obecnie używanych szkieletach programistycznych kontroler ma znacznie większe, niż przedstawione znaczenie. Jest on odpowiedzialny dodatkowo za stworzenie i wybranie odpowiedniego widoku oraz przekazaniu mu odpowiednich danych w celu wyświetlenia. Zależność modelu i widoku odbywa się na zasadzie zależności widoku od modelu. Zmiany dokonane w modelu wymagają aktualizacji widoku. Ostatnią z opisywanych zależności dotyczy modelu i kontrolera. Kontroler zależy od modelu, zmiany dokonane w modelu mogą wymagać dokonania zmian w samym kontrolerze. Implementacja wzorca MVC Niniejsza sekcja prezentuje prostą implementacja wzorca MVC wykorzystującą następujące składniki: serwlet, w roli kontrolera, stronę wykonaną w technologi JSP, w roli widoku, obiekt użytkownika, reprezentującego model. Celem aplikacji jest wyświetlenie informacji powitalnej dla użytkownika o podanym w żądaniu id. Zakładamy, iż obiekt klienta user posiada pole name oraz unikalny numer identyfikacyjny id i spełnia zasady konwencji dla JavaBean. Kod fragmentu serwletu przedstawiony na listingu 1.3, składający się z metody doget pobiera numer id (uid) użytkownika przekazany za pomocą metody HTTP GET. Następnie przy wykorzystaniu usługi userservice pobiera określoną osobę z zewnętrznego źródła danych (linia 4), np. z relacyjnej bazy danych. W kolejnym kroku umieszcza obiekt użytkownika w żądaniu (linia 5). Poźniej tworzy widok, wykorzystując stronę welcome.jsp do której nastąpi przekierowanie w ostatniej linii skryptu. Zadaniem strony będzie wyświetlenie powitania wraz z imieniem użytkownika, który został przekazany przez kontroler. Kod strony prezentuje listing 1.4. Rezultatem prezentowanej strony będzie wyświetlenie kominikatu Witaj Adam!, w przypadku podania w żądaniu inicjalizującym id użytkownika o imieniu Adam. 17

19 1 public void doget(httpservletrequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 Long userid = Long.parseLong(request.getParameter("uid")); 4 User user = userservice.getuser(userid); 5 request.setattribute("user", user); 6 7 RequestDispatcher view = request.getrequestdispatcher("/welcome.jsp"); 8 view.forward(request, response); 9 } Listing 1.3: Kontroler aplikacji opartej o wzorzec MVC 1 <jsp:usebean id="user" type="user" scope="request" /> 2 <html> 3 <head><title>strona powitalna</title></head> 4 <body> 5 <h2>witaj <jsp:getproperty name="user" property="name" />!</h2> 6 </body> 7 </html> Listing 1.4: Widok aplikacji opartej o wzorzec MVC Przedstawiony sposób obrazuje oddzielenie danych i sposobu ich przetwarzania od warstwy prezentacji, w tym przypadku strony HTML. Bez trudu można byłoby stworzyć inny widok, osadzający dane pobranego użytkownika np. w treści bedącej XML-em. Osadzenie logiki biznesowej w kontrolerze pozwala równocześnie na zmiany w sposobie przetwarzania pobranych danych bez modyfikacji szablonów widoku. Przykładowa zmiana kolejności liter w imieniu użytkownika, skutkowałaby wyłącznie zmianą w kodzie serwletu, szablon którego jedynym celem jest przedstawienie imienia użytkownika wraz z powitaniem, pozostałby bez zmian Model komponentowy Model komponentowy [17] stanowi zastosowanie idei komponentowego tworzenia aplikacji w zastosowaniu do warstwy prezentacji. Bazuje na wcześniej opisanym modelu złożonym, wprowadzając zasady komponentowego tworzenia interfejsu użytkownika. Szkielety programistyczne stosujące model komponentowy mają wiele wspólnego ze środowiskami typu Rapid Application Development (RAD) które mają na celu usprawnienie procesu tworzenia aplikacji desktopowych. Wspomniane komponenty, zwane również kontrolkami, są składowymi interfejsu użytkownika, mogą to być np. przyciski bądź skomplikowane tabele. Ważną cechą komponentów jest możliwość ich zawierania w sobie. Istnieją komponenty niewizualne, których rolą może być między innymi tworzenie układu strony bądź grupowanie innych komponentów. Ważnym elementem wyróżniającym komponenty jest posiadanie przez nie wewnętrznego stanu. W podejściu klasycznym stosującym pierwotną wersję Modelu 2 aplikacja składa się z szablonów, które są kierowane w odpowiedzi do przeglądarki, po uprzednim otrzymaniu żądania do kontrolera, który podaje widokowi dane. Model komponentowy prezentuje inne podejście do prezentowanego zagadnienia. Strona składa się z komponentów, które reagują na zdarzenia, których źródłem jest najczęściej użytkownik aplikacji. Do zdarzeń można 18

20 Rysunek 1.7: Model komponentowy w implementacji JavaServer Faces zaliczyć naciśniecie przycisku, wypełnienia pola, wybrania pozycji z menu. Odpowiednie metody są odpowiedzialne następnie za przechwycenie powstałego zdarzenia. Rysunek 1.7 przedstawia schemat modelu opartego o podejście komponentowe, zaimplementowane w szkielecie programistycznym JavaServer Faces [26]. Model (ang. Model) reprezentuje własności obiektów domenowych na których operuje aplikacja, np. imię wyświetlanego użytkownika. Komponenty (ang. components) interfejsu użytkownika deklarują zdarzenia, które użytkownik z ich użyciem może wygenerować. Wychwytywaniem pojawiających zdarzeń zajmują się metody nasłuchujące (ang. event listeners), których zadaniem jest reakcja na otrzymane zdarzenia. Do przykładowych zadań metody nasłuchującej może być przetworzenie odebranych danych bądź wyświetlenie szczegółów wybranej osoby w systemie. Osobna klasa odpowiedzialna za widok tworzy poszczególne komponenty użytkownika. Możliwa jest zmiana klasy renderującej (ang. renderer) w przypadku, gdy chcielibyśmy np. wyświetlić naszą stronę z użyciem innego języka znaczników. Efektem wprowadzenia komponentowego modelu tworzenia interfejsu użytkownika z wykorzystaniem ramy projektowej, otrzymujemy dostęp do gotowego zbioru komponentów, które mogą zostać wykorzystane podczas pracy nad aplikacją, począwszy od prostych przycisków po skomplikowane, stronicowane tabele. Obecnie na rynku szkieletów programistycznych jedynie niektóre stosują opisywany model. Ma to związek z między innymi wykorzystaniem stosunkowo nowego podejścia, nie rozpowszechnionego jeszcze wśród programistów Javy Zadania szkieletów programistycznych Internetowe szkielety programistyczne stanowią zbiór bibliotek i narzędzi mających na celu ułatwienie programiście zrealizowanie zamierzonego celu w zakresie budowy aplikacji webowej. Opisywane narzędzia mogą stanowić pewien ograniczony, niewielki zbiór ułatwiający pracę np. z bazami danych poprzez aplikacje pomocne przy implementacji warstwy 19

21 prezentacji tworzonego systemu po frameworki, które dostarczają kompleksowej pomocy podczas budowania aplikacji internetowej, dostarczając rozwiązań w postaci utrwalania danych, tworzenia warstwy biznesowej czy warstwy prezentacji. Do ostatniej grupy należy szkielet JBoss Seam [34], który wykorzystuje odpowiednio bibliotekę Hibernate [27] jako maper obiektowo-relacyjny, Enterprise JavaBean 3.0 do enkapsulacji logiki biznesowej i JavaServer Faces do budowy warstwy prezentacji. Opisywane w pracy szkielety programistyczne należą do grupy pośredniej i zajmują się jedynie wsparciem w implementacji warstwy prezentacji tworzonego systemu. Do najczęściej implementowanych funkcjonalności frameworków webowych należą: zapewnienie mapowania nadchodzących żądań do odpowiednich kontrolerów, a w przypadku szkieletów opartych o model komponentowy do odpowiednich metod nasłuchujących, stworzenie systemu nawigacji między stronami aplikacji, umożliwienie dostępu do warstwy modelu aplikacji z uwzględnieniem konwersji i walidacji wprowadzanych danych, integracja z językami znaczników, pomocnymi przy tworzeniu szablonów stron, dostarczenie zbioru komponentów (w przypadku frameworków komponentowych), pomoc w internacjonalizacji i lokalizacji tworzonych stron, wsparcie dla alternatywnych technologii widoku takich jak FreeMaker, przełączanie motywów wyglądu aplikacji (ang. theme). Zdecydowana większość szkieletów korzysta również z Modelu 2 w celu separacji poszczególnych składowych aplikacji. Mapowanie nadchodzących żądań najczęściej odbywa się z udziałem wcześniej opisywanego obiektu tzw. Front Controllera, który przechwytuje wszystkie kierowane do aplikacji żądania i decyduje o ich późniejszym losie. Spotykane podejścia rozwiązujące opisywany problem sprowadzają się do stworzenia konfiguracji, najczęściej w postaci pliku XML, z mapowaniami adresów URL do poszczególnych kontrolerów i ich metod. We frameworkach opartych o komponenty, które są sterowane zdarzeniami, stosuje się przejścia między stronami oparte o komunikaty, zwracane przez poszczególne metody nasłuchujące. Typowe użytkowanie aplikacji internetowej sprowadza się do wysyłania żądania przez jej użytkowników oraz udzielania odpowiedzi przez system. W celu sprawnego poruszania się po aplikacji, szkielety programistyczne dostarczają wsparcia dla nawigacji. Ma to szczególne znaczenie w przypadku skomplikowanych ciągów zdarzeń nawigacyjnych wykorzystujących pojęcie stanowości. Bardzo ważnym aspektem aplikacji internetowych jest interakcja z użytkownikiem, odbywająca się najczęściej z wykorzystaniem formularzy. Rolą szkieletu programistycznego pozostaje wówczas przekształcanie własności obiektów modelu na pola formularza oraz tworzenie z wypełnionych przez użytkownika pól formularza obiektów dziedziny. Nieodzowną funkcjonalnością związaną z formularzami jest walidacja wprowadzonych przez użytkownika danych, zarówno po stronie klienta jak i serwera. Podczas tworzenia aplikacji, również webowych, korzystna jest separacja pracy poszczególnych grup osób. Ma to szczególne znaczenie w oddzieleniu pracy twórców szablonów od programistów implementujących logikę aplikacji. Najczęściej jest to osiągane poprzez użycie znaczników ze specjalnymi atrybutami, które są następnie przekształcane po stronie serwera w gotową do wyświetlenia stronę. Pożądaną cecha jest również możliwość dziedziczenia szablonów, co skutkuje znacznie łatwiejszą w utrzymaniu bazą szablonów. W przypadku frameworków komponentowych możliwe jest użycie komponentów w ce- 20

22 lu przyspieszenia budowy interfejsu użytkownika. Komponenty te biorą na siebie wszelkie aspekty związane z poprawnym wyświetlaniem ich w różnych przeglądarkach, zaoszczędzając tym samym czas programisty, który nie musi już rozwiązywać problemów niekompatybilności poszczególnych przeglądarek. Ujemną stroną takiego rozwiązania jest ograniczony wpływ programisty na kod tworzonej strony, gdyż głównymi jej elementami są gotowe komponenty. Jednym z wyróżników aplikacji internetowych jest łatwość ich użycia przez ludzi z różnych stron świata wystarczy jedynie przeglądarka, przy braku wymogu co do instalacji jakiegokolwiek innego oprogramowania. Dlatego często niezbędna jest internacjonalizacja/lokalizacja tworzonych stron, obejmująca takie aspekty prezentowanej treści jak: tłumaczenie treści i komunikatów systemu, poprawne formatowanie daty, liczb i walut, uwzględnienie stref czasowych w których działa użytkownik, zmianę kolorów bądź grafiki w zależności od zasad kulturowych klienta, zmianę kolejności sortowania elementów. W zależności od prezentowanej treści często jest wygodniej używać alternatywnych, w stosunku do stron JavaServer Pages technologi, takich jak szablony FreeMaker czy XML połączony z transformacjami XSLT. Czasami zachodzi również konieczność przedstawienia treści w specyficzny sposób z użyciem formatu PDF czy arkuszy Excela. Ostatnią z przedstawianych funkcji szkieletów programistycznych jest wsparcie dla możliwości zmiany motywu wyglądu aplikacji. Funkcjonalność ta może mieć szczególne znaczenie w przypadku serwisów, których celem jest maksymalne dopasowanie serwowanej treści do preferencji użytkownika, np. w systemach rekomendujących [38]. 21

23 2. Nowoczesne środowisko pracy programisty Celem niniejszego rozdziału jest opis środowiska pracy wraz z wybranymi narzędziami użytymi podczas procesu tworzenia przykładowej aplikacji, przedstawionej w rozdziale 5. Pierwszy z podrozdziałów przedstawia narzędzia, tworzące platformę do budowy aplikacji webowych w środowisku Java. Przeznaczeniem narzędzia Subversion jest wersjonowanie kodu źródłowego systemu, z możliwością powrotu do poprzedniego stanu. Aplikację Maven można uważać za następcę Anta, służącą do zarządzania tworzonym projektem. Potrafi uczestniczyć w procesie budowy, raportowania i dokumentowania projektu. Biblioteka Hibernate stanowi najpopularniejsze obecnie narzędzie służące do translacji obiektowo-relacyjnej dostępnej na platforme Java. Spring Framework to szkielet programistyczny usprawniający tworzenie aplikacji poprzez użycie, między innymi, wzorca odwróconego sterowania (ang. Inversion of Control). W drugiej części zostały zaprezentowane narzędzia wspomagające pracę programisty podczas testowania tworzonego oprogramowania. Spring-mock jest jedną ze składowych szkieletu Spring Framework, służącą do przeprowadzania testów integracyjnych na aplikacjach tworzonych za pomocą tego narzędzia. EasyMock to biblioteka pomocna w testowaniu warstwy biznesowej aplikacji, tworząca obiekty zastępcze (ang. mock objects) na podstawie już istniejących. JUnit 4 stanowi sztandarowe narzędzie wykorzystywane podczas testów jednostkowych. Selenium jest biblioteką wspomagającą testowanie aplikacji webowych w środowisku przeglądarki internetowej Narzędzia integrujące Obecnie na rynku istnieją narzędzia wspomagające tworzenie oprogramowana praktycznie na każdym stadium rozwoju aplikacji. Począwszy od systemów wersjonowania kodu (ang. source code management) po specjalizowane szkielety programistyczne. W rozdziale zostaną przedstawione jedynie wybrane z nich, użyte podczas tworzenia przykładowej aplikacji Subversion Aplikacja Subversion (svn) stanowi przykład systemu kontroli wersji (ang. revision control system), umożliwiającego śledzenie zmian dokonanych w kodzie źródłowym (w przypadku projektów informatycznych) oraz pomocnej podczas łączenia zmian dokonywanych przez wielu programistów podczas wspólnej pracy nad projektem. Subversion nie jest w ścisłym sensie aplikacją typu SCM (ang. Software Configuration Management), gdyż nie zawiera w sobie funkcji specyficznych dla zarządzania kodem projektów informatycznych. Do wspomnianych funkcji można zaliczyć zrozumienie języków programowania, których kod jest składowany w repozytorium czy wsparcie w zakresie narzędzi do budowy aplikacji na podstawie kodu przechowywanego w repozytorium. Subversion jest narzędziem uniwersalnym, nadaje się równie dobrze do wersjonowania kodu 22

24 źródłowego aplikacji webowej jak do wersjonowania notatek sporządzanych podczas pisania pracy dyplomowej. Subversion stanowi scentralizowany system kontroli wersji, kod przechowywany jest we wspólnym repozytorium, dostępnym dla wszystkich aplikacji klienckich. Dane składowane są w postaci wirtualnego, drzewiastego systemu plików, który w trakcie dokonywania zmian, podlega ciągłemu wersjonowaniu. Aplikacje kliencie łączące się z repozytorium mają możliwość pobierania jego treści lub jego modyfikacji. Opisywany system działa według zasady pobierz-zmodyfikuj -dołącz, która jest stosowana również przez CVS, stanowi zarazem alternatywę dla blokowania plików podczas edycji. Programiści wyrażający chęć pracy nad kodem, składowanym w wspólnym repozytorium tworzą swoją własną lokalną kopię repozytorium, będącą odzwierciedleniem repozytorium centralnego. Następnie każdy z nich wprowadza swoje modyfikacje będące wynikiem pracy nad kodem. Ostatnim krokiem jest wprowadzenie dokonanych zmian do repozytorium. Historia Prace w CollabNet, kolebce Subversion, rozpoczęły się w lutym 2000 roku, jako poszukiwania następcy CVS-a. Budowany system nie miał stanowić rewolucji dla standardu de facto jakim był darmowy Concurrent Versions System (CVS), miał jedynie poprawić jego braki i niedociągnięcia. Do niedostatków systemu (CVS), które były bezpośrednimi powodami rozpoczęcia pracy nad opisywanym projektem należą: zmiany w repozytorium nie są operacjami atomowymi co może doprowadzić do powstawania niespójności w kodzie repozytorium w przypadku wystąpienia błędu podczas wprowadzania zmian do repozytorium, operacje przenoszenia plików lub zmiany ich nazwy nie maja swojego odzwierciedlenia w systemie wersjonowania, brak wersjonowania dowiązań symbolicznych (ang. symbolic links), ograniczone wsparcie dla standardu Unicode. Przy projekcie, od jego początków, uczestniczyli Karl Fogel, autor książki Open Source Development with CVS oraz Jimy Blandy, którzy już wcześniej zaczęli poszukiwania nowego systemu wersjonowania, a poproszeni przez CollabNet wyrazili chęć współpracy. Wraz z końcem sierpnia 2001 roku projekt osiągnął stan w którym mógł sam przechowywać swoje własne źródła. Programiści pracujący nad Subversion zawiesili używanie systemu CVS do składowania kodu projektu Subversion. Firma CollabNet przez cały czas trwania projektu, opłaca pracę wybranych programistów tworzący nowy system wersjonowania. Posiada do niego prawa licencyjne, które są jednak w pełni zgodne z wytycznymi Debian Free Software Guidelines [18]. Każdy ma prawo do bezpłatnego pobierania, modyfikacji oraz używania kodu projektu Subversion, zgoda CollabNet nie jest wymagana. Funkcjonalność Subversion dostarcza wiele usprawnień w stosunku do systemu CVS, który był jego pierwowzorem, niektóre spośród nich to: Wersjonowanie katalogów, podczas gdy CVS potrafił tylko wersjonować jedynie pojedyncze pliki, Subversion wprowadza pojęcie wersjonowanego, wirtualnego systemu plików. Wszystkie operacje podejmowane w jego obrębie są rejestrowane. Dotyczy to 23

25 plików jak i samych katalogów. Można w dowolnej chwili cofnąć się do poprzedniej wybranej wersji systemu. Usprawnione wersjonowanie, dziennik systemu CVS obejmuje wyłącznie zmiany dokonywane na zawartości plików. Subversion potrafi wersjonować operacje kopiowania, zmiany nazwy, przenoszenia plików jak i katalogów. Ponadto jest możliwe stworzenie nowego pliku o nazwie pliku już istniejącego, który nie dziedziczy jego historii. Atomowe dokonywanie zmian, podczas wprowadzania zmian do większej liczby plików, zmiany wprowadzane są wszystkie albo żadne. Nie ma możliwości, aby do repozytorium były wprowadzone tylko częściowe zmiany. Metadane, z każdym plikiem bądź katalogiem w repozytorium można skojarzyć metadane, w postaci pary klucz wartość. Własności te są wersjonowane tak samo jak zawartość plików. Najczęściej definiują typ pliku lub jego autora. Efektywne tworzenie nowych rozgałęzień (ang. branches) i znaczników (ang. tags), tworzenie nowych rozgałęzień zajmuje stałą ilość czasu, wykorzystuje koncepcję podobną do twardych dowiązań (ang. hard links). System Subversion składa się z wielu komponentów, które w połączeniu z podkomendami realizują odmienne cele, do ważniejszych z nich należą: svn, aplikacja kliencka wykorzystywana między innymi do pobierania kodu źródłowego z repozytorium, svnlook, służy do przeglądania zawartości repozytorium, svnserve samodzielny serwer svn, który może być uruchomiony jako demon systemowy lub usługa typu inetd. Praca z repozytorium Podczas wspomnianego modelu pracy może się zdarzyć, że dojdzie do konfliktu w momencie, gdy dwóch programistów wprowadziło rozbieżne zmiany w tym samym fragmencie kodu. Rozwiązaniem jest proces scalenia kodu, który dokonuje programista chcący wprowadzić nowy kod, pozostający w konflikcie z kodem już istniejącym. Do programisty należy wówczas decyzja o postaci kodu wprowadzonej do repozytorium. Kluczowym czynnikiem pomagającym rozwiązywać konflikty jest komunikacja pomiędzy programistami pracującymi nad wspólnym projektem. Pobranie kodu z repozytorium odbywa się za pomocą polecenia svn wraz z użyciem podkomendy checkout. Następujący kod (listing 2.1) tworzy lokalną wersję projektu o nazwie calc na podstawie centralnego repozytorium, w katalogu bieżącym o nazwie kalkulator. Podczas łączenia z repozytorium został wykorzystany protokół svn. 1 svn checkout svn://dev.firma.com/repos/calc/trunk kalkulator Listing 2.1: Pobranie kodu z repozytorium Wraz ze wprowadzonymi zmianami (ang. revisions) następuje inkrementacja numeru wersji dla repozytorium. Opisywany numer jest wspólny dla wszystkich projektów, które dzielą jeden wersjonowany system plików wspomniane repozytorium. Prowadzi to do sytuacji w której aktywny projekt zwiększa numer zmian projektów mniej aktywnych, dzielących wspólne repozytorium. W większości przypadków nie ma to znaczenia i nie wprowadza zamieszania wśród twórców różnych projektów. Rozwiązaniem jest stworzenie różnych repozytoriów dla projektów o odmiennym przeznaczeniu. Należy jednak pamiętać, iż Subversion wersjonuje jedynie zmiany dokonane w obrębie projektów znajdujących się w jednym repozytorium. 24

26 Rysunek 2.1: Inkrementacja numeru rewizji a zmiany w repozytorium Podczas wprowadzania zmian następuje zróżnicowanie numerów zmian poszczególnych plików przechowywanych w repozytorium, gdyż akcja wprowadzania zmian nie implikuje akacji pobrania kodu z centralnego repozytorium. W momencie modyfikacji przykładowego pliku plik.txt, przechowywanego w repozytorium oznaczonego numerem wersji 10, po wprowadzeniu zmian wersja repozytorium zostaje inkrementowana, jednak tylko zmodyfikowany plik otrzymuje nowy numer zmiany 11. Reszta plików posiada numer 10 bądź jedne z wcześniejszych. Sprawę wprowadzanych zmian w repozytorium i ich skutków na numery zmian (rewizji) poszczególnych plików jak i całego projektu, prezentuje rysunek 2.1. Liczba w kwadracie oznacza numer zmiany dla całego repozytorium, jeżeli nie oznaczono inaczej. Literą Z został oznaczony etap zmiany nazwy pliku. Liczba w okręgu oznacza numer rewizji pliku bezpośrednio się przy nim znajdującego. W trakcie wprowadzania modyfikacji polegającej na zmianie nazwy jednego z plików przechowywanych w repozytorium, zostają wykonane dwie operacje. Jedna dodaje do repozytorium plik o nowej nazwie, druga usuwa dotychczas istniejący. Pomimo wykonania dwóch operacji, rewizja zmienianego pliku zmienia się o jeden, z 5 na 6. Numer zmiany dla pozostałej części projektu pozostaje bez zmian, wynosi 5. Przykładowy zapis wykonanych poleceń został przedstawiony na listingu 2.2. Duże litery A i B zaczynające odpowiednio drugą i trzecią linię oznaczają odpowiednio dodanie pliku do repozytorium oraz usunięcie poprzednio istniejącego pliku noszącego starą nazwę. 1 svn commit "/project/calc/a" "/project/calc/b" -m "Zmiana nazwy pliku" 2 A /project/calc/b 3 D /project/calc/a 4 Transmitting file data: /project/calc/a 5 Committed revision 6 Listing 2.2: Zmiana nazwy pliku w repozytorium Subversion W trakcie budowy aplikacji może zajść potrzeba stworzenia odmiennej gałęzi od głównej linii kodu, np. w celu wprowadzenia nowej czasochłonnej funkcjonalności. Tworzenie nowej gałęzi odbywa się poprzez skopiowanie głównego kodu do nowego katalogu, zwyczajowo podkatalogu katalogu branches. Do przełączania się pomiędzy poszczególnymi gałęziami służy komenda switch. Po zakończeniu procesu tworzenia nowej funkcjonalności następuje scalenie jej (ang. merge) z główną linią kodu. Równie częstą praktyką jest znakowanie projektu tzw. tagami. Tag wskazuje na określony, konkretny moment w cyklu życia projektu. Kod oznaczony znacznikiem, w przeci- 25

27 wieństwie do kodu znajdującego się w gałęzi, nie ulega zmianom. Typowym przykładem użycia znakowania jest przypadek wydania kolejnej wersji oprogramowania. Tworzony jest wówczas tag o nazwie stworzonej wersji, reprezentujący kod aplikacji w momencie kolejnego wydania Maven Maven jest narzędziem zaliczanym do grupy określanej mianem szkieletów wspomagających zarządzanie projektem (ang. project managment framework). Według [60] opisywane narzędzie stanowi zbiór standardów, formatów repozytoriów oraz oprogramowania używanych w celu zarządzania i opisu projektów. Uczestniczy w definiowaniu standardowych etapów życia oprogramowania od budowy poprzez testy po wdrożenie. Wprowadza modularność, pozytywnie wpływającą na możliwość ponownego użycia poszczególnych elementów tworzonego oprogramowania z użyciem Mavena. Historia Idea projektu Maven zrodziła się z potrzeby posiadania wspólnej platformy wytwarzania oprogramowania przez Apache Software Foundation (ASF). Wcześniej każdy z projektów realizował własną wizję procesu tworzenia oprogramowania, począwszy od budowy oprogramowania po tworzenie strony domowej projektu. W rezultacie, pomimo istnienia pewnych wspólnych elementów, każdy z projektów istniał jako samotna wyspa. Brak standardowego narzędzia zarządzającego cyklem życia tworzonego oprogramowania prowadził do tego, iż każdy z nowych projektów był zmuszony do powtórnego tworzenia własnego systemu. Często odbywało się to na zasadzie kopiowania pomysłów podpatrzonych w innych projektach. Kłopoty przeżywały projekty, które wymagały szczególnie skomplikowanego systemu budowy oprogramowania, takie jak Jakarta Taglibs [57]. Uwaga programistów skupiała się w dużej części na zapewnieniu infrastruktury dla projektu kosztem pracy nad funkcjonalnością tworzonego produktu. Bezpośrednim powodem powstania Mavena był niezadowalający proces budowy innego projektu, Turbine [32]. Programiści szybko zrozumieli zalety stosowania szkieletu wytwarzania oprogramowania jakim jest Maven. Wprowadzenie usystematyzowanego procesu spowodowało iż zrozumienie zasad działania jednego projektu skutkuje poznaniem wszystkich pozostałych stosujących ten sam proces. Zakres wpływu Mavena sięga od procesu budowy, testowania, wdrażania, po przeprowadzanie testów zarówno jednostkowych jak i integracyjnych, generowanie dokumentacji i raportów. Wersja Mavena oznaczona wersją 1.0 wydano w lipcu 2004 roku, szybko została zaaprobowane przez społeczność Codehaus. Obecne stabilne wydanie Mavena nosi wersję 2.0.5, zostało wydane w lutym 2007 roku. Maven często jest porównywany do innego standardu w zakresie budowy aplikacji, Anta. Maven stanowi nadzbiór funkcjonalności jaką oferuje Ant [5], stanowi narzędzie o szerszym zakresie działania. Wprowadza pojęcie wzorców stosowanych przy budowie aplikacji, definiując między innymi standardowe rozmieszczenie katalogów w projekcie. Maven może w sposób całkowity zastąpić Anta. Podstawy Maven wprowadza nowy poziom abstrakcji w procesie budowy oprogramowania. O ile każdy z projektów informatycznych posiada indywidualną naturę, wszystkie je łączy pewien określony cykl życia, nad którym Maven stara się zapanować. Elementy specyficzne 26

28 dla danego projektu deklaruje się w pliku POM (Project Object Model), który jest wyrażony za pomocą składni języka XML. Zasady, którymi kieruje się projekt Maven zostały zaczerpnięte z dzieła Christopera Alexandra pod tytułem A Pattern Language [3], należą do nich: konwencja względem konfiguracji, tworzenie w sposób deklaratywny, nacisk na ponowne wykorzystanie istniejących już elementów, spójne zarządzanie zależnościami. Jedną z największych zalet tworzenia oprogramowania z użyciem Mavena jest możliwość szybkiego skorzystania z gotowego systemu budowy dla tworzonego systemu, dzięki skorzystaniu z domyślnych ustawień oferowanych przez Mavena. Ważną informacją jest możliwość zmiany domyślnych ustawień, poprzez nadpisanie ustawień standardowych. Takie praktyki są jednak niezalecane. Zaleca się przestrzeganie domyślnych ustawień dla projektu. Opisana praktyka pozytywnie wpływa na łatwość sposobu opisu zachowania i struktury systemu budowania wśród programistów stosujących domyślne ustawienia. Projekty tworzone z użyciem Mavena posiadają standardowe rozmieszczenie katalogów dla źródeł, plików zasobów (ang. resources), plików konfiguracyjnych, dokumentacji czy tworzonego projektu. Ta prosta na pozór zasada, pozwala w drastyczny sposób skrócić czas potrzebny za zaznajomienie się z nowym projektem. Kolejną zasadą którą stosuje Maven jest zasada podziału odpowiedzialności (ang. separation of concerns), która w zastosowaniu do opisywanego systemu powoduje, iż na wyjściu każdego z projektów znajduje się zawsze jeden plik wyjściowy jar, lub w przypadku aplikacji webowych plik war. Powoduje to, że dany projekt skupia się na jednej głównej funkcjonalności, korzystając równocześnie w razie potrzeby z innych projektów. W przypadku aplikacji (projektów) tworzonych z wykorzystaniem Mavena, separacja odbywa się na poziomie jednostek zwanych modułami. Każdy moduł może być uważany za osobny projekt dostarczający innej funkcjonalności, a w połączeniu dających pełną funkcjonalność końcową. Maven stara się również wprowadzić wspólne zasady nazewnicze dla zarządzanych elementów, ma to bezpośrednie odzwierciedlenie np. w nazwach tworzonych projektów które są zapisywane w formacie, reprezentowanym przez następujący przykład log4j jar, który oznacza plik biblioteki Log4j w wersji Ponowne użycie komponentów, oprócz wspomnianych modułów, jest również realizowane przez wtyczki (ang. plugins), które dostarczają opisywanej funkcjonalności Mavena. Wszystkie funkcjonalności jakie oferuje Maven są implementowane z wykorzystaniem wtyczek. Z listą dostępnych wtyczek można się zapoznać na stronie org/plugins/. Istnieją pluginy pomocne przy kompilacji, wdrażaniu, przeprowadzaniu testów, generowaniu raportów czy plików projektu specyficznych dla środowisk programistycznych takich jak Eclipse czy IDEA. Ostatnia ze wspomnianych możliwości, umożliwia pracę nad projektem stworzonym z wykorzystaniem Mavena w wybranym środowisku programistycznym, gdyż standardowo wygenerowany projekt nie posiada plików charakterystycznych dla żadnego z nich. Maven wprowadza do projektu ściśle określony cykl życia projektu (ang. build life cycle). Poszczególne etapy składają się z faz, do których mogą zostać przypisane określone akcje, dostarczane za pomocą wtyczek. Przykładowo jeżeli zleci się Mavenowi kompilację projektu za pomocą komendy compile, wówczas zostaną wykonane następujące fazy: walidacja, inicjalizacja, generowanie źródeł, przetworzenie źródeł, przetworzenie plików zasobów oraz kompilacja. Z każdą z przedstawionych faz skojarzone są konkretne akcje 27

29 dostarczane przez wtyczki. Obecnie domyślny cykl życia projektu składa się z 21 faz, począwszy od wspomnianej walidacji po końcowe wdrożenie aplikacji. Dodatkowo istnieją inne cykle życia związane z czyszczeniem projektu (clean) czy generowaniem strony domowej (site). Project Object Model Akcje podejmowane przez Mavena są sterowane w sposób deklaratywny zawartością pliku projektu POM, o standardowej nazwie POM.xml. Każdy z projektów/modułów posiada dokładnie jeden taki plik, opisujący jego cechy. Listing 2.3 prezentuje przykład poprawnego pliku POM, który umożliwia przeprowadzenie kompilacji, testów i wygenerowaniu dokumentacji. Wszystkie te czynności są możliwe dzięki możliwości dziedziczenia pomiędzy plikami POM. Każdy z tworzonych 1 <project> 2 <modelversion>4.0.0</modelversion> 3 <groupid>com.mycompany.app</groupid> 4 <artifactid>my-app</artifactid> 5 <packaging>jar</packaging> 6 <name>maven Project</name> 7 <version>1.0-snapshot</version> 8 <dependencies> 9 <dependency> 10 <groupid>junit</groupid> 11 <artifactid>junit</artifactid> 12 <version>3.8.1</version> 13 <scope>test</scope> 14 </dependency> 15 </dependencies> 16 </project> Listing 2.3: Zawartość pliku pom.xml projektu Mavena plików POM dziedziczy domyślnie ustawienia z predefiniowanego pliku POM o nazwie Super POM. Definiuje on wszystkie wspomniane wcześniej standardowe ustawienia dla projektu. W zrozumieniu jego istoty, pomaga analogia do nadrzędnego obiektu języka Java java.lang.object. Listing 2.3 przedstawia zawartość pliku POM. Znacznik project stanowi znacznik będący korzeniem całego dokumentu. W linii drugiej podano zastosowaną wersję pliku POM. W liniach od 3 do 7 podano informacje na temat projektu. Element groupid ma znaczenie podobne do pakietów znanych z języka Java i służy do grupowania powiązanych pakietów w repozytorium Mavena bądź lokalnym. Znacznik artifactid symbolizuje nazwę projektu, wygenerowany projekt będzie posiadał nazwę my-app-1.0-snapshot.jar. Element packaging definiuje typ aplikacji. Pozostałe znaczniki reprezentują krótką nazwę projektu oraz jego wersję. Znacznik dependency symbolizuje konkretną zależność z jakiej korzysta dany projekt, w tym wypadku jest to biblioteka JUnit, w wersji Zarządzanie zależnościami Jednolite zarządzanie zależnościami jest jedną z kluczowych zalet stosowania projektu Maven przy budowie tworzonej aplikacji. Na listingu 2.3, za pomocą znacznika dependency 28

30 została wyrażona zależność budowanego projektu. Najpopularniejszym artefaktem platformy Java, służącym dystrybucji programów są pliki jar. Wspomniana zależność jest referencją do artefaktu znajdującego się w repozytorium. Położenie artefaktu jest jednoznacznie definiowane poprzez jego groupid oraz artifactid. Maven powiadomiony o potrzebie spełnienia zależności łączy się z serwerem i na podstawie wspomnianych danych ściąga go do lokalnego repozytorium. Deklaracja zależności polega na tym iż programista jest zwolniony z obowiązku fizycznego wskazywania wymaganej zależności. Wystarczy iż opisze potrzebne biblioteki w pliku mieszczącym opis specyficznych cech projektu a Maven zajmie się resztą. Programista przestaje operować niskopoziomowymi pojęciami takimi jak pliki jar, deklaruje po prostu potrzebę użycia biblioteki JUnit w określonej wersji. Pobrana ze zdalnego serwera zależność zostaje umieszczona w repozytorium lokalnym, które pełni również funkcję pamięci podręcznej. Jeżeli żądana zależność nie znajduje się w lokalnym repozytorium wówczas Maven sięga do repozytorium zdalnego. Szkielet lokalnego repozytorium jest tworzony podczas pierwszego uruchomienia Mavena. Opisywana biblioteka nie zawiera w sobie żadnych z domyślnych bibliotek ani bibliotek wykorzystywanych wtyczek. Uruchomienie po raz pierwszy komendy czyszczącej projekt mvn clean spowoduje pobranie wtyczki o nazwie clean z repozytorium i umieszczeniu jej na dysku lokalnym w strukturze repozytorium lokalnego. W procesie poszukiwania zależności najpierw jest sprawdzane repozytorium lokalne, gdy zależność nie zostanie spełniona wówczas Maven przystępuje do sprawdzenia repozytoriów zdalnych, gdy zostały zdefiniowane dodatkowe sprawdzane są wszystkie w kolejności ich definicji w pliku POM. Jeżeli zależność zostanie spełniona w jednym z opisywanych miejsc, jest zapisywana do repozytorium lokalnego a proces ulega zakończeniu. Od tego momentu każdy projekt żądający pobranej wcześniej zależności będzie używał tej z repozytorium lokalnego. Zaprezentowane podejście sprawia, iż wszystkie zależności tworzonych projektów definiowane są w jednym miejscu, lokalnym repozytorium, ma to szczególne znaczenie podczas pracy nad wieloma projektami, gdyż nie ma potrzeby dublowania tych samych bibliotek w wielu projektach co wielokrotnie ma miejsce. Projekt składowany w repozytorium kodu jest pozbawiony zależności, które są pobierane ze wspólnego repozytorium Mavena. Częstą praktyką jest zakładanie oprócz repozytoriów lokalnych, również repozytorium na poziomie firmy, do którego wszyscy programiści mają szybki dostęp. Repozytorium oprócz funkcji typowej dla pamięci podręcznej służy również do składowania artefaktów produkowanych przez samych programistów. Artefakt umieszczony zdalnie w repozytorium firmy sprawia iż wszyscy pozostali mają do niego ułatwiony dostęp i mogą pracować zawsze z najnowszymi elementami systemu. Domyślnie dostępność nowszych wersji bibliotek jest sprawdzana raz dziennie. W przypadku zależności oznaczonych sufiksem SNAPSHOT, obecność nowszej wersji jest sprawdzana za każdym razem gdy zajdzie taka potrzeba Eclipse Efektywna praca wykorzystująca platformę Java nie jest możliwa bez wsparcia ze strony odpowiedniego środowiska programistycznego. Niniejszy podrozdział stanowi wprowadzenie do środowiska rozwijanego przez Eclipse Foundation [2]. Idea zintegrowanego środowiska wytwarzania oprogramowania (IDE) polega na połączeniu wymaganych podczas pracy narzędzi w formie jednolitego, autonomicznego pakietu oprogramowania. Integracja narzędzi wspierających budowę, kompilację, diagnozowanie 29

31 projektu czyni pracę bardziej efektywną oraz zwalnia z potrzeby korzystania z innych często niekompatybilnych zewnętrznych narzędzi. Dla prostych projektów użycie zintegrowanych środowisk programistycznych nie jest warunkiem koniecznym. Skuteczną alternatywą może być edytor tekstu, wzbogacony o możliwość kolorowania składni bądź wspomagający poruszanie się po strukturze projektu. Dodatkowym wsparciem może być narzędzie do automatycznej budowy aplikacji takie jak Ant czy Maven. Praca nad projektem złożonym zgodnym z J2EE wymaga szerokiego wsparcie od strony środowiska programistycznego. Do kluczowych funkcjonalności należą: wsparcie dla używanych w projekcie języków oprogramowania takich jak Java, Python, SQL czy XML, obecność konfigurowalnych generatorów kodu jak i określonych artefaktów programistycznych, pomoc w zakresie używanych interfejsów programistycznych, możliwość skorzystania z operacji refaktoryzacji kodu, integracja z systemami kontroli wersji takimi jak CVS czy Subversion, wsparcie w testowaniu i diagnozie tworzonego systemu. Z wszystkich z wymienionych funkcjonalności można skorzystać używając środowiska Eclipse, część z nich wymaga instalacji dodatkowych wtyczek. Nazwą Eclipse przyjęło się nazywać popularne wśród programistów języka Java środowisko programistyczne. Jednak pod tą nazwą, kryje się cała platforma programistyczna mająca na celu wspomaganie przy wytwarzaniu oprogramowania. Obecnie platforma Eclipse dostarcza rozwiązań w zakresie tworzenia aplikacji korporacyjnych, przeznaczonych do urządzeń typu embedded, desktopowych. Dostarcza wsparcia w programowaniu z użyciem takich języków jak Java, C, Cobol, PHP. Dodatkowo stanowi podstawę wielu szkieletów wykorzystywanych podczas projektowania, testowania czy raportowania. Cechy środowiska Platforma Eclipse wprowadziła koncepcję obszarów roboczych (ang. workspace), które funkcjonują na poziomie projektów i pozwalają na grupowanie ich w logiczne jednostki. Podczas uruchomiania środowiska użytkownik ma możliwość wyboru obszaru roboczego z którym chce pracować. Dodatkowo z wyborem obszaru roboczego wiąże się dostępność poszczególnych wtyczek. Środowisko wykorzystywane do tworzenia projektów skupionych w obszarze roboczym wykorzystującym język Python będzie korzystało z innych komponentów niż projekty wykorzystujące język Java. Na poziomie interfejsu użytownika wprowadzono pojęcie perspektyw (ang. perspectives), które pomagają przy wykonywaniu różnych prac związanych z wytwarzaniem oprogramowania. Użycie określonej perspektywy wpływa na wygląd menu, obecności i rozkład okien. Istnieją perspektywy wykorzystywane podczas pisania kodu, podczas przeglądania plików projektu, testowania, śledzenia błędów czy pracy z systemem wersjonowania kodu. Zalętą platformy Eclipse jest możliwość użycia wtyczek w celu zwiększenia, rozbudowania możliwości środowiska. Strona projektu Eclipse Plugin Central (EPIC) http: // zawiera katalog wtyczek dostępnych dla opisywanej platformy. Obecnie jest ich prawie 1000 pogrupowanych w kategoriach począwszy od wtyczek wspomagających projektowanie po wtyczki związane z wdrożeniem. Wsparcie dla języka Java jest implementowane przez projekt Java Development Tools (JDT), dostarczające między innymi następujących elementów: obsługi składni, adnotacji, przyrostową kompilację kodu, refaktoryzację, śledzenie błędów czy wsparcie w operacjach 30

32 związanych z zarządzaniem kodem. Projektem wspierającym programistę podczas budowy aplikacji J2EE z wykorzystaniem platformy Eclipse jest Web Tools Platform (WTP) Project. Wspomniane cechy Eclipse realizuje z wykorzystaniem następujących elementów: współpraca z CVS jest wbudowana w środowisko, pracę z repozytoriami Subversion zapewnia wtyczka Subversive, wsparcie dla języków SQL, XML, HTML zapewnia projekt WTP, pozostałe z wymienionych elementów (testy, kreatory, diagnoza) zapewniają odpowiednie projekty, charakterystyczne dla danego języka bądź środowiska, w przypadku Javy jest to JDT, w przypadku języka Ruby RDT. Istnieje również możliwość dodania własnych wtyczek poprzez mechanizm Update Site, wykorzystując protokół HTTP. Instalacja oraz ewentualne dalsze uaktualnienia zostaną przeprowadzone automatycznie poprzez platformę Eclipse Hibernate Hibernate [36] jest narzędziem wspomagającym proces odwzorowania obiektowo-relacyjnego. W przeciwieństwie do znanych z wersji EJB 2.0 ciężkich komponentów encyjnych, opisywana biblioteka umożliwia operację na zwykłych obiektach Javy (ang. Plain Old Java Object), oferując przeźroczyste wsparcie w zakresie składowania i odczytu obiektów z magazynu danych. Przedstawiana biblioteka posiada wsparcie dla aplikacji korporacyjnych, obsługuje transakcje, obiekty wartości, pule połączeń. Posiada również swój własny język zapytań Hibernate Query Language (HQL), który w przeciwieństwie do języka SQL [?] operuje na obiektach. Oprócz tego biblioteka oferuje wsparcie w przypadku klas stosujących dziedziczenie, asocjacje czy złożenie. Hibernate posiada wsparcie w zakresie współpracy z ponad dwudziestoma różnymi dialektami języka SQL, począwszy od bazy HSQLDB po Oracle. Oznacza to iż teoretycznie, zmiana silnika bazodanowego nie będzie się wiązała ze zmianą kodu w samej aplikacji. Konfiguracje mapowań można przeprowadzić w dwojaki sposób. Pierwszy z nich jest szerzej znany i sprowadza się do zastosowania plików wykorzystujących język XML w celu opisania mapowań pomiędzy obiektami i tabelami w bazie danych jak również pól klas do kolumn w tabelach bazy danych. Drugi sposób konfiguracji polega na wykorzystaniu, wprowadzonej w wersji 5.0 języka Java, adnotacji za pomocą których opisuje się zwykłe obiekty Java, nadając im charakter obiektów trwałych. Podstawą architektury systemu Hibernate jest obiekt SessionFactory, który posiada informację o wszystkich mapowaniach aplikacji związanych z pojedynczą używaną bazą danych, jest obiektem o bezpiecznych wątkach (ang. thread-safe). Jego tworzenie jest kosztowne, przeznaczony jest do wielokrotnego użycia. Obiektem wytwarzanym przez opisaną wcześniej fabrykę jest Session, który reprezentuje konwersację pomiędzy obsługiwanymi obiektami a magazynem danych. Jest obiektem krótkotrwałym, jednowątkowym, przeznaczonym do wykonywania operacji na obiektach trwałych. Obiekty trwałe stanowią reprezentację danych pobranych z magazynu danych, przeważnie są to zwykłe obiekty Java. W typowym scenariuszu aplikacja posiada jeden obiekt SessionFactory, który w razie potrzeby jest wykorzystywany do tworzenia obiektów typu Session, które służą z kolei do wykonywania operacji na obiektach trwałych. Obiekty w czasie pracy z biblioteką Hibernate mogą przybierać w danym czasie jeden z następujących trzech stanów: 31

33 Ulotny (ang. transient), obiekt nigdy nie został skojarzony z żadną sesją Hibernate, nie posiada przypisanego mu identyfikatora. Typowym przykładem jest nowo stworzony bądź odebrany obiekt. Trwały (ang. persistent), obiekt jest reprezentowany przez otwartą sesję oraz posiada swój identyfikator oraz odpowiadający mu wiersz w bazie danych. W opisywanym stanie Hibernate gwarantuje zgodność obiektu przechowywanego w pamięci z jego postacią w magazynie danych. Typowym przykładem jest obiekt świeżo pobrany z magazynu bądź niedawno tam zapisany. Odłączony (ang. detached), obiekt był już w zasięgu sesji jednak utracił z nią kontakt bądź został przekazany do innego procesu. Posiada swój identyfikator oraz odpowiadający mu wiersz w bazie danych. Dla obiektów tego typu Hibernate nie może zagwarantować spójności z ich odpowiednikiem w bazie danych. Programista używający narzędzia Hibernate musi być świadomy stanu obiektów z którymi pracuje. Domyślnie włączona opcja leniwego pobierania kolekcji (ang. lazy fetching) może spowodować rzucenie wyjątku związanego z brakiem żądanej kolekcji, gdy obiekt znajduje się w stanie odłączonym. Przykład mapowania obiektów Niniejsza sekcja prezentuje prosty przykład mapowania pomiędzy dwoma obiektami POJO z wykorzystaniem adnotacji. Obiekt właściciela Owner może posiadać wiele zwierząt Pet, przy czym dane zwierze może posiadać tylko jednego właściciela. Jest to typowy przykład relacji n m, prezentowana relacja dodatkowo jest dwustronna. Listing 2.4 przedstawia mapowanie obiektu POJO odpowiadającemu właścicielowi. W bazie danych zostanie zapisane nazwisko name właściciela oraz jego kolekcja zwierząt. = "owners") 3 public class { 4 private String name; 5 private Set<Pet> pets = new HashSet<Pet>(); 6 = "pets") = org.company.domain.pet.class, 9 cascade = { CascadeType.ALL }, mappedby = "owner") = "owner_id") 12 public Set<Pet> getpets() { 13 return pets; 14 } 15 } Listing 2.4: Mapowanie obiektu właściciela Obiekty właściciela zostaną zmapowane do tabeli o nazwie wskazywanej przez adnotację Table. Relacja jeden do wielu została wyrażona adnotacją OneToMany z użyciem zależności kaskadowej. Skasowanie właściciela skutkuje automatycznym skasowaniem wszystkich należących do niego zwierząt. Listing 2.5 prezentuje encję zwierzęcia, zawierającą imię oraz referencję do swojego właściciela. Adnotacja ManyToOne reprezentuje relację wiele do jednego. Nie możliwe jest 32

34 = "pets") 3 public class Pet { 4 private String name; 5 private Owner owner; 6 = false) = "fk_owner") 10 public Owner getowner() { 11 return owner; 12 } 13 } Listing 2.5: Mapowanie obiektu zwierzęcia zapisanie obiektu w magazynie danych nie posiadającego referencji do właściciela, dba o to właściwość nullable należąca do adnotacji JoinColumn. Właściwość name adnotacji ForeignKey nadpisuje automatycznie generowaną nazwę dla klucza obcego relacji właściciel zwierzę Spring Framework Szkielet programistyczny Spring Framework powstał, według autora Roda Johnsona, w reakcji na niedostatki związane z zastosowaniem ciężkiego modelu jaki wiązał się z użytkowaniem technologi Enterprise JavaBeans w wersji 2.0 [51]. Pierwsze wydanie biblioteki, noszące numer wersji 1.0 pojawiło się w marcu 2004 roku. Obecnie Spring jest wymieniany wśród najczęściej stosowanych frameworków warstwy środkowej, używanych podczas tworzenia aplikacji webowych z wykorzystaniem platformy Java. Spring do swojego działania nie wymaga serwera aplikacji takie jak np. JBoss [33], wystarczy kontener serwletów, Tomcat [8] bądź Jetty [37]. Użycie lekkich środowisk skraca znacznie czas potrzebny na wdrożenie aplikacji, co ma szczególne znaczenie podczas tworzenia oprogramowania, podczas częstych zmian kodu. Skrócony czas potrzebny na wdrożenie aplikacji oznacza szybką informację zwrotną. Programista nie musi długo czekać żeby zobaczyć rezultaty swojej pracy. Wzorzec odwróconego sterowania Podstawowymi obiektami wykorzystywanymi podczas tworzenia aplikacji z wykorzystaniem frameworka Spring są zwykłe obiekty Javy. Całość integrowana jest z wykorzystaniem wzorca odwrócenia sterowania (ang. Inversion of Control) a dokładniej jego odmiany noszącej nazwę wstrzykiwania zależności (ang. Dependency Injection) [23]. Używany wzorzec pozwala na usunięcie bezpośrednich powiązań pomiędzy obiektami wpływając pozytywnie na stan luźnego powiązania obiektów (ang. loose coupling), pożądanego w aplikacjach dowolnego typu. Odpowiedzialność zapewnienia wzajemnego powiązania pomiędzy obiektami używanymi w aplikacji spoczywa na tzw. kontenerze IoC. Jego zadanie polega na udostępnianiu wcześniej zdefiniowanych obiektów i dostarczaniu ich wraz z zależnościami zwracanego obiektu. Istnieją dwie metody wstrzykiwania zależności, jedna z nich (wstrzykiwanie konstruktorem) wykorzystuje konstruktor tworzonego obiektu do dostarczenia zależności, 33

35 druga (wstrzykiwanie metodami modyfikującymi) polega na wykorzystaniu standardowych metod ustawiających dla obiektów spełniających specyfikację JavaBeans. Opisywane podejście wykorzystujące wstrzykiwanie zależności wpływa pozytywnie na łatwość testowania aplikacji. Luźno powiązane obiekty łatwiej jest testować. Osiągane jest to poprzez definicję odpowiednich interfejsów które implementują określone obiekty Java. Poszczególne zależne od siebie obiekty opierają się w swoich relacjach na wyspecyfikowanych interfejsach. Ułatwia to zastosowanie obiektów zastępczych (ang. mock objects). Wzorzec odwróconego sterowania pozwala w łatwy sposób podmieniać współpracujące ze sobą obiekty. W przypadku szkieletu Spring zależności są deklarowane poza kodem w postaci plików wykorzystujących do opisu powiązań język XML. Moduły Spring składa się z szeregu niewielkich modułów o ściśle określonych funkcjach, dopiero użycie ich razem pozwala na zbudowanie aplikacji oferującej pełną funkcjonalność. W związku z posiadaniem ściśle określonych zadań przez każdy z opisywanych modułów, możliwe jest również użycie ich oddzielnie. Do najważniejszych modułów opisywanego szkieletu zaliczają się: kontener odwróconego sterowania, którego zadaniem jest dostarczanie skonfigurowanych obiektów oraz zarządzanie ich cyklem życia, szkielet Aspect-oriented programming (AOP), niezwykle ważna część frameworka Spring używana między innymi przy implementacji deklaratywnego zarządzania transakcjami, szkielet dostępu do danych enkapsuluje standardowe mechanizmy JDBC, używając wspólnej hierarchii niesprawdzalnych wyjątków. Równocześnie wprowadza możliwość integracji tworzonej aplikacji z bibliotekami typu Hibernate czy SQL ibatis [29], szkielet zarządzania transakcjami, nie wymaga do działania serwera aplikacji. Dostarcza różnych strategi zapewnienia spójności transakcyjnych danych, własny szkielet warstwy prezentacji implementujący wzorzec MVC o nazwie Spring Web MVC, jego największą zaletą jest łatwość integracji z reszta infrastruktury dostarczanej przez Springa, szkielet wspomagający testowanie aplikacji z wykorzystaniem testów jednostkowych jak i integracyjnych. W architekturze frameworka Spring ważna rolę tworzą szablony, które ułatwiają implementację określonych zadań. Przykładowo istnieje szablon HibernateTemplate, który wspiera programistę w użyciu szkieletu Hibernate. Listing 2.6 prezentuje metodę pobierającą listę produktów loadproductsbycategory wykorzystującą opisywany szablon. Dla przejrzystości kodu zrezygnowano z deklaracji generowanych wyjątków. Linia druga zawiera utworzenie nowego szablonu, w kolejnej linii następuje wywołanie metody execute, która jako parametr przyjmuje anonimową klasą wewnętrzną HibernateCallback będącą interfejsem implementowanym z wykorzystaniem metody doinhibernate. Ciało metody (linie 5 do 8) tworzy kod charakterystyczny dla frameworka Hibernate. Wynik będący listą produktów z żądanej kategorii zostaje zwrócony w linii 8. Wzorzec Dependency Injection Celem niniejszej części jest przedstawienie odmiany wzorca Inversion of Control zwanego Dependency Injection. Podstawowym zastosowaniem wzorca wstrzykiwania zależności jest zmniejszenie zależności występujących w kodzie pomiędzy obiektami systemu oraz umożliwienie łatwej wymiany poszczególnych elementów systemu. 34

36 1 public Collection loadproductsbycategory(string category) { 2 HibernateTemplate ht = new HibernateTemplate(this.sessionFactory); 3 return (Collection) ht.execute(new HibernateCallback() { 4 public Object doinhibernate(session session) { 5 Query query = session.createquery( 6 "from test.product product where product.category=?"); 7 query.setstring(0, category); 8 return query.list(); 9 } 10 }); 11 } Listing 2.6: Użycie szablonu HibernateTemplate W przykładzie ilustrującym opisywany wzorzec występują dwie, zależne od siebie klasy MessageRenderer oraz SimpleMessageProvider. Pierwsza z nich jest odpowiedzialna za wyświetlenie komunikatu, który uzyska od drugiej klasy. Klasa MessageRenderer 2.7 posiada referencję do interfejsu MessageProvider z metodą getmessage(), wykorzystywaną podczas wyświetlania wiadomości. 1 public class MessageRenderer { 2 private MessageProvider messageprovider; 3 MessageRenderer(MessageProvider messageprovider) { 4 this.messageprovider = messageprovider; 5 } 6 public void render() { 7 System.out.println(messageProvider.getMessage()); 8 } 9 } Listing 2.7: Klasa wyświetlająca komunikat Rola klasy SimpleMessageProvider (listing 2.8) polega na dostarczeniu określonej wiadomości. Dla uproszczenia przykładu wiadomość posiada stałą treść. Inne implementacje interfejsu MessageProvider mogą pobierać wiadomość z zewnętrznego źródła np. bazy danych. 1 public class SimpleMessageProvider implements MessageProvider{ 2 public String getmessage() { 3 return "Hello World!"; 4 } 5 } Listing 2.8: Klasa dostarczająca komunikat do wyświetlenia Rola kontenera IoC ogranicza się do dostarczania żądanych zależności. W opisywanym przypadku należy połączyć instancję klasy SimpleMessageProvider z polem messageprovider w ramach procesu zwanego wstrzykiwaniem zależności. Ponieważ klasa posiadająca zależność posiada konstruktor, wykorzystane zostanie wstrzykiwanie zależności z wykorzysta- 35

37 niem konstruktora. Listing 2.9 prezentuje plik konfiguracyjny odpowiedzialny za określenie zależności pomiędzy obiektami. Bean simpleprovider jest przekazywany jako argument konstruktora beanowi renderer. 1 <beans> 2 <bean id="simpleprovider" class="simplemessageprovider" /> 3 <bean id="renderer" class="messagerenderer"> 4 <constructor-arg ref="simpleprovider" /> 5 </bean> 6 </beans> Listing 2.9: Konfiguracja zależności Zbiór beanów umieszczono w pliku beans.xml. Uruchomienie kodu zaprezentowanego na listingu 2.10 spowoduje wyświetlenie oczekiwanego komunikatu. 1 public static void main(string[] args) { 2 BeanFactory fact = new XmlBeanFactory(new ClassPathResource("beans.xml")); 3 MessageRenderer renderer = (MessageRenderer) fact.getbean("renderer"); 4 renderer.render(); 5 } Listing 2.10: Użycie skonfigurowanego obiektu wyświetlającego komunikat 2.2. Narzędzia testujące Niezmienność wymagań podczas wytwarzania oprogramowania jest niemożliwa do utrzymania. Zmiany dokonywane są na każdym z etapów życia oprogramowania. Mogą wynikać ze zmiany wymagań, nowej wizji produktu bądź poprawy niezauważonych wcześniej błędów. Niniejszy rozdział przedstawia rozwiązania, które starają się reagować w sposób dynamiczny na pojawiające się w projekcie systemu zmiany. Prezentowane podejście wspomaga zastosowanie techniki wytwarzania oprogramowania sterowaną testami (ang. Test-Driven Development) Spring Mock Biblioteka Spring Mock [50] jest składową szkieletu Spring Framework i stanowi platformę dla testowania aplikacji tworzonych z wykorzystaniem wspomnianej biblioteki. O jej dojrzałości może świadczyć fakt, iż jest ona używana przez autorów Springa podczas tworzenia projektu. Spring Mock wspomaga testy integracyjne z wykorzystaniem bazy danych przeprowadzane na aplikacji wykorzystującej infrastrukturę Spring Framework. Najczęściej jest stosowany przy testowaniu warstwy Data Access Object (DAO), zapewniającej jednolity interfejs między warstwą usług a magazynem danych. Kluczową funkcjonalnością dostarczaną przez opisywaną bibliotekę jest dodanie aspektu transakcyjnego do testowanych obiektów DAO. W typowym przypadku podczas testowania obiektów DAO, wywołuje się wybrane metody testowanego obiektu mające odzwierciedlenie w operacjach na obiektach domeny. 36

38 Jedną z zasad przeprowadzania testów jest dbałość o to, aby wynik działania jednego testu nie wpływał na działanie testu drugiego. W przypadku testowania obiektu DAO oznacza to, iż wcześniej wykonana operacja na obiekcie domeny w jednym z przypadków testowych nie może mieć wpływu na później wykonywany przypadek testowy. Sprowadza się do operacji testowania, które podczas działania dokonują zmian w używanej bazie danych. Najczęściej operacje tego typu polegają na usunięciu określonych obiektów z bazy podczas operacji testowania. Rola opisywanej biblioteki polega na przywróceniu stanu sprzed wykonania przypadku testowego, dzięki temu wykonywane testy zyskują poczucie izolacji. Przykład Testowane obiekty DAO muszą korzystać z klasy TransactionProxyFactoryBean, która w sposób przeźroczysty dodaje transakcyjność do używanych obiektów, opisana funkcjonalność jest wykorzystywana podczas odwracania zmian dokonanych w bazie danych podczas wykonywania testu. Kolejne przypadki testowe uruchomiane są w ramach izolowanych transakcji, po zakończeniu każdego z nich zmiany są wycofywane. Klasą odpowiedzialną za przeprowadzanie testów w środowisku transakcyjnym jest klasa AbstractDependencyInjectionSpringContextTests, po której bezpośrednio dziedziczą klasy testujące obiekty DAO. 1 public class HibernateUserDaoTests extends 2 AbstractDependencyInjectionSpringContextTests { 3 4 // zaleznosc wstrzykiwana zewnetrznie 5 private HibernateUserDao userdao; 6 7 // metoda ustawiajaca wykorzystywana podczas wstrzykiwania zaleznosci 8 public void setuserdao(hibernateuserdao userdao) { 9 this.userdao = userdao; 10 } // test przeprowadzany w srodowisku izolowanym 13 public void testloaduser() throws Exception { 14 User user = this.userdao.loaduser(new Long(17)); 15 assertnotnull(user); 16 } // metoda ladujaca plik konfiguracyjny przygotowany na potrzeby testu 19 protected String[] getconfiglocations() { 20 return new String[] { "classpath:com/daos.xml" }; 21 } } Listing 2.11: Test integracyjny w środowisku transakcyjnym Przykład klasy używającej wspomnianą klasę prezentuje listing Przedstawiona klasa ma za zadanie przetestowanie obiektu UserDao, którego zadaniem jest wykonywanie operacji na obiekcie domeny User. Linia 5 zawiera referencję do testowanego obiektu DAO, który jest wstrzykiwany za pomocą metody ustawiającej w linii 8. Metoda testloaduser 37

39 została przygotowana w celu przetestowania procesu pobrania obiektu User z magazynu danych. Warunkiem sukcesu pobrania użytkownika posiadającego id równego 17, jest uzyskanie referencji do niego (linia 14). Metoda z linii 19 ładuje plik konfiguracyjny zawierający definicję obiektów DAO, które zostały wzbogacone aspektem transakcyjności EasyMock Biblioteka EasyMock jest przykładem implementacji idei obiektów zastępczych (ang. mock objects) podczas przeprowadzania testów jednostkowych. Rola obiektów zastępczych polega na symulowaniu zachowania obiektów rzeczywistych w sposób kontrolowany. Ich rolę można przyrównać do roli manekina używanych podczas testów zderzeniowych podczas testowania samochodów. W obu przypadkach, testowania oprogramowania i samochodu, wykorzystywany jest pewien obiekt pozorny, który pozwala na przeprowadzenie i weryfikację powodzenia przeprowadzonego testu. Pierwotnie możliwe było wyłącznie zastępowanie interfejsów. Obecnie większość popularnych bibliotek wspomagających przeprowadzanie testów z użyciem obiektów pozornych, umożliwia zastępowanie również obiektów. Użycie obiektów pozornych ma uzasadnienie podczas przeprowadzania testów jednostkowych obiektów, które muszą w określony sposób współpracować z innymi klasami w celu zrealizowania powierzonego mu zadania. Często działanie obiektów z którymi konieczna jest współpraca jest skomplikowane, bądź samo ich zastosowanie nie jest możliwe w środowisku testowym. Sytuacje wymagające zastosowania obiektów zastępczych, pojawiają się w przypadku wystąpienia następujących zależności: użycie niedeterministycznych w czasie wartości, takich jak czas bądź temperatura, testowanie trudnych do powtórzenia stanów aplikacji, występujących np. w przypadku błędu sieci, potrzeby skrócenia czasu wykonywania testów, gdy używane zależności wykonują długotrwałe prace wiążące się np. z otwarciem połączenia z bazą danych. Zastosowanie obiektów zastępczych we wszystkie opisanych powyżej przypadkach pozwala na zwiększenie izolacji poszczególnych testów. Przykład Testowanie z wykorzystaniem obiektów zastępczych wymaga przestrzegania ściśle określonych faz podczas testowania. Listing 2.12 przedstawia przykładową metodą wykorzystującą podczas testów obiekt pozorny. Prezentowana metoda testuje metodę usługi, związanej z zarządzaniem wizytami w przychodni weterynaryjnej, pobierającą trzy najbliższe wizyty. Obiekt usługi visitservice jest zależny od obiektu DAO VisitDao, którego rola polega na pobraniu z magazyny danych żądanych wizyt. W związku z tym, że prezentowany test ma charakter jednostkowy, wykluczone jest korzystanie z bazy danych. Rozwiązaniem jest skorzystanie z obiektu zastępczego dla rzeczywistego obiektu DAO o nazwie visitdaomock, utworzonego w linii trzeciej. W następnej linii następuje utworzenie testowanego obiektu usługi z wykorzystaniem obiektu pozornego. Linia 6 zawiera oczekiwane zachowanie względem obiektu zależnego, polegające na wywołaniu metody getmostrecent z odpowiednim parametrem oraz zwróceniu obiektu odpowiedniego typu w tym przypadku ArrayList. W linii 8 następuje aktywacja obiektu zastępczego, po czym odbywa się wywołanie testowanej metody serwisu. Weryfikacja poprawności wywołań oraz przekazywanych typów odbywa się w linii 10. Na podstawie zaprezentowanej metody można wyróżnić następujące etapy stosowane przy budowaniu testów opartych o obiekty pozorne: 1. Utworzenie obiektu pozornego. 38

40 1 public void testadddocument() { 2 control = EasyMock.createStrictControl(); 3 visitdaomock = control.createmock(visitdao.class); 4 visitservice = new DefaultVisitService<Visit, Long>(visitDaoMock); 5 6 expect(visitdaomock.getmostrecent(3)).andreturn(new ArrayList<Visit>()); 7 8 replay(visitdaomock); 9 visitservice.getmostrecentfrom(3); 10 verify(visitdaomock); 11 } Listing 2.12: Testowanie z użyciem obiektu pozornego 2. Zastąpienie rzeczywistej zależności obiektem pozornym. 3. Wyrażenie za pomocą interfejsu biblioteki EasyMock, oczekiwanej interakcji z obiektem pozornym (metoda expect). 4. Wywołanie metody obiektu testowanego. 5. Weryfikacja poprawności wykonania wcześniej zdefiniowanego scenariusza. Błąd weryfikacji scenariusza wywołań skutkuje wygenerowaniem błędu typu AssertionError i przerwaniem wykonywania dalszych testów JUnit 4 Celem testów jednostkowych jest zapewnienie zgodności testowanego komponentu z wytycznymi projektu. Testy jednostkowe stanowią podstawę techniki określanej mianem programowania sterowanego testami (ang. Test-Driven Development) [39]. Celem tworzonego testu jest zazwyczaj weryfikacja poprawności działania publicznych metod pojedynczej klasy bądź komponentu. Narzędzie JUnit [4] stanowi standard de facto podczas przeprowadzania testów jednostkowych na platformie Java. Jego idea została przeniesiona również na inne języki programowania takie jak C#, Python czy Ruby. Wspólnym terminem xunit określane są wszystkie narzędzia służące do przeprowadzania testów jednostkowych charakterystyczne dla danej platformy programistycznej. Pierwsze służące testom jednostkowym nosiło nazwę SUnit i służyło do testowania kodu napisanego w języku Smalltalk. Pozytywne wyniki działania testów jednostkowych zapewniają poprawność działania poszczególnych, możliwie jak najmniejszych, komponentów systemu. Zaletą testów jednostkowych jest możliwość ich użycia podczas testów regresywnych, ujawniających błędy wprowadzone zazwyczaj podczas dodawania nowej funkcjonalności. Dobre testy jednostkowe posiadają wysoki stopień pokrycia kodu (ang. code coverage), obejmują wszystkie lub prawie wszystkie możliwe ścieżki wykonania programu. Stosowanie testów jednostkowych ułatwia integrację całości projektu, gdyż pracujący nad nim programiści mają pewność poprawności działania poszczególnych jego części. Łatwość automatyzacji testów jednostkowych sprawia, iż można je przeprowadzać wystarczająco często aby wykryć wkradające się zmiany wynikające ze zmian dokonanych w systemie. W określonych sytuacjach może być pożądane przeprowadzania testów po każdej kompilacji oprogramowania, w celu natychmiastowego wykrycia wprowadzonych błędów. 39

41 Kolejną cechą testów jednostkowych jest dostarczenie informacji na temat funkcjonowania poszczególnych komponentów oprogramowania. Dokumentacja w postaci testów jednostkowych ma tę zaletę, że jest zawsze aktualna i odzwierciedla sposób użycia testowanych jednostek. Testy jednostkowe nie są w stanie zazwyczaj wychwycić wszystkich błędów tworzonego systemu. Stanowią jednak podstawę dla pozostałych typów testów, takich jak testy integracyjne, funkcjonalne czy regresyjne [2, rozdział 14]. Przykład Kod przedstawiony na listingu 2.14 prezentuje przykład zastosowania testu jednostkowego do weryfikacji poprawności działania klasy Adder, której zadaniem jest zwrócenie sumy podanych dwóch liczb. W przykładzie zastosowano bibliotekę JUnit w wersji 4, która wprowadza wiele usprawnień w porównaniu z poprzednią wersją. Do najważniejszych zaliczają się dodanie obsługi adnotacji oraz specjalnych metod typu BeforeClass oraz AfterClass. Nowa biblioteka posiada tryb zgodności przy przetwarzaniu testów przygotowanych z poprzednią wersją biblioteki. Klasa sumatora (listing 2.13) składa się z metody add, której zadaniem jest dodanie dwóch przekazanych jej liczb. Klasa przypadku testowego została przedstawiona na li- 1 public class Adder { 2 public static int add(int x, int y) { 3 return x + y; 4 } 5 } Listing 2.13: Klasa sumatora stingu Składa się z jednej metody, której zadaniem jest przetestowanie statycznej metody klasy Adder. W odróżnieniu od poprzedniej wersji biblioteki nie ma potrzeby dzie- 1 public class AdderTest { 3 public void testadd() { 4 assertequals("dodawanie dwoch liczb", 7, Adder.add(2, 3)); 5 } 6 } Listing 2.14: Klasa testowa sumatora dziczenia przypadku testowego po klasie junit.framework.testcase, wystarczy jedynie oznaczyć odpowiednie metody klasy testującej adnotacją Test. Kluczowym elementem metody testujących są asercje, wykorzystywane do badania określonych warunków. Wykorzystywana metoda assertequals ma za zadanie porównanie przekazanej jej wartości z wynikiem metody add, przekazanej jako trzeci argument. Napis przekazany jako pierwszy argument ma zadanie jedynie informacyjne i jest wyświetlany w przypadku niepowodzenia testu, w formie przedstawionej na listingu Do metody dodającej sumatora zostały przekazany liczby 2 i 3, jednak w metodzie przypadku testowego wprowadzono błędną spodziewaną wartość wynoszącą 7. W związku z niespełnieniem asercji, sprawdzającej wynik 40

42 1 java.lang.assertionerror: Dodawanie dwoch liczb expected:<7> but was:<5> Listing 2.15: Komunikat o błędzie asercji szkieletu JUnit rzeczywisty ze spodziewanym został wygenerowany błąd. Wspomniany napis pozwala na szybkie zorientowanie się o miejscu wystąpienia błędu Selenium Biblioteka Selenium [53] stanowi przykład narzędzia wykorzystywanego podczas testów akceptacyjnych, zwanych również testami funkcjonalnymi, aplikacji webowych. Testy akceptacyjne działają na zasadzie czarnej skrzynki i wykonywane są zazwyczaj podczas przekazywania gotowego oprogramowania odbiorcy. Wykonanie testów akceptacyjnych zazwyczaj składa się z określonego zbioru testów pokrywających żądane przez zleceniodawcę funkcjonalności systemu [28]. Wynik testów jest prezentowany w postaci dwuelementowego zbioru określającego sukces bądź porażkę każdego z testów. Mianem testów akceptacyjnych w programowaniu ekstremalnym określa się testy funkcjonalne, używane do weryfikacji tworzonych historii użytkownika (ang. user stories). Odbiorca systemu specyfikuje scenariusze, które mogą obejmować kilka scenariuszy testowych w celu weryfikacji poprawności zachowania się aplikacji. Postępy w pracy mierzone są liczbą zatwierdzonych przez klienta testów akceptacyjnych. Specyficzną cechą biblioteki Selenium jest fakt iż działa wewnątrz przeglądarki internetowej. Obecnie wspierane są między innymi Internet Explorer, Firefox oraz Opera. Stopień wsparcia jest uzależniony od platformy na której działa dana przeglądarka. Działanie systemu Selenium polega na dodaniu do testowanych stron języka JavaScript w celu umożliwienia przeprowadzenia testów. Testy przebiegają w sposób automatyczny i polegają na wykonywaniu następujących czynności: klikanie w linki bądź wypełnianie i wysyłanie formularzy. Opisywany system składa się z wyspecjalizowanych komponentów pomocnych w tworzeniu i przeprowadzeniu testów. Selenium IDE (wcześniej znane pod nazwą Selenium Recorder) jest wtyczką przeglądarki Firefox, umożliwiającą rejestrowanie, edycję oraz śledzenie tworzonych testów. Selenium Core jest podstawowym serwerem działającym bezpośrednio i tylko w przeglądarce, wykorzystuje język selense. Rozszerzeniem komponentu Selenium Core jest Selenium Remote Control, który stanowi serwer proxy przyjmujący komendy wysłane za pomocą protokołu HTTP, utworzone za pomocą dowolnego języka programowania. W celu dalszego uproszczenia procesu tworzenia testów udostępniono API dla popularnych języków programowania takich jak Java, Python czy PHP, umożliwiające dostęp do obiektów obudowujących (ang. wrapper objects). Podczas testów zapytania HTTP kierowane są do serwera Selenium Remote Control i tłumaczone na język selense. Łącznikiem pomiędzy silnikiem, przeprowadzającym testy a badaną stroną jest serwer proxy, które wzbogaca przetwarzaną stronę o wyrażenia języka JavaScript. Użycie proxy jest konieczne z powodu funkcjonowania różnych implementacji języka JavaScript w różnych przeglądarkach. Przykład Niniejsza sekcja prezentuje użycie biblioteki Selenium z wykorzystaniem komponentu Selenium Remote Control, umożliwiającego użycie języka Java do skonstruowania testu. 41

43 Tworzony test wspierany jest przez użycie dodatkowej biblioteki JUnit. Przypadek te- 1 import com.thoughtworks.selenium.*; 2 import junit.framework.*; 3 public class GoogleTest extends TestCase { 4 private Selenium sel; 5 public void setup() { 6 sel = new DefaultSelenium("localhost", 4444, "*firefox", 7 " 8 sel.start(); 9 } public void testgoogle() { 12 sel.open(" 13 sel.type("q", "hello world"); 14 sel.click("btng"); 15 sel.waitforpagetoload("5000"); 16 assertequals("hello world - Google Search", sel.gettitle()); 17 } public void teardown() { 20 sel.stop(); 21 } 22 } Listing 2.16: Test Selenium Remote Control w języku Java stowy zawiera referencję do obiektu sel, który odpowiada za wysyłanie odpowiednich poleceń protokołu HTTP do serwera testującego. Metoda setup jest metodą specyficzną dla JUnita wykonywaną przed każdym z testów. Położenie serwera testującego zostało zdefiniowane w linii 6, znajduje się maszynie lokalnej i nasłuchuje na porcie Instrukcja umieszczona w linii 8 startuje przeglądarkę Firefox i rozpoczyna sesję. Badaną stroną jest strona wyszukiwarki 1. Metoda testująca znajduje się w linii 11. W pierwszej instrukcji zostaje wczytana żądana strona. W linii 13 następuje wypełnienie formularza wyszukiwawczego, o nazwie q tekstem hello world. Po pięciu sekundach następuje weryfikacja obecności w tytule pobranej stronie tekstu hello world - Google Search. Jeżeli asercja zwróci wartość true, test uznaje się za zakończony pozytywnie. Ostatnia metoda teardown jest przeciwieństwem pierwszej metody prezentowanej klasy i służy do oczyszczenia środowiska po wykonanym teście, w tym przypadku jej rola sprowadza się do zamknięcia sesji testowej i zakończeniu pracy przeglądarki wykorzystanej podczas testów. 1 Przykład zaczerpnięty ze strony 42

44 3. Przegląd internetowych szkieletów programistycznych W niniejszym rozdziale przedstawiono przegląd najpopularniejszych bibliotek implementujących zadania typowe dla szkieletów programistycznych przeznaczonych do tworzenia aplikacji internetowych, wymienione w rozdziale 1.3. Dwa z przedstawionych frameworków stosują Model 2. Dwa pozostałe wykorzystują model komponentowy, który w założeniach ma uczynić tworzenie aplikacji internetowych podobnym do tworzenia aplikacji desktopowych. Rozdział rozpoczyna opis niedawno 1 wydanej biblioteki Struts 2, która stanowi kontynuację projektu WebWork w połączeniu z biblioteką Struts 1. W kolejnej części został przedstawiony framework Spring MVC, będący częścią biblioteki Spring Framework, wspomagający programistę podczas tworzenia warstwy prezentacji z wykorzystaniem wspomnianej biblioteki. Tematem przedostatniej części jest biblioteka Tapestry 5, która stosuje model komponentowy podczas tworzenia warstwy prezentacji. Ostatna część przedstawia standard JavaServer Faces, będący częścią specyfikacji JEE, wykorzystywany przy tworzeniu interfejsu użytkownika Struts 2 Struts 2 [7] jest projektem, którego początki sięgają roku 2005, konferencji JavaOne Wówczas powstał pomysł na dalszy rozwój znanego frameworka Struts. Programiści Martin Cooper, Don Brown wraz z Richem Feitem zaproponowali powstanie projektu Struts Ti, którego celem było dodanie elementów, które stworzyła społeczność szkieletu Struts do jego głównej części. Jednocześnie Jason Carreira zaproponował wykorzystanie szkieletu WebWork. Zbieżność rozwiązań stosowanych w tym frameworku oraz pomysłów osób rozwijających Struts 2, doprowadziła do powstania kolejnej wersji szkieletu Struts. Opisywany framework do sprawnego działania wymaga implementacji serwletów zgodnych z wersją API 2.4, stron JSP w wersji 2.0 oraz platformy Javy w wersji Architektura Rozwiązanie bazujące na Struts 2, w warstwie kontrolera, wykorzystuje takie technologie jak: filtry, JavaBeans, XML, XWork, Locales. W warstwie danych opisywany szkielet umożliwia wykorzystanie JDBC, EJB, jak również translatorów obiektowo-relacyjnych takich jak Hibernate czy ibatis. Warstwa prezentacji bazuje na stronach JavaServer Pages, ze wsparciem w postaci znaczników JSTL, dodatkowo możliwe jest wykorzystanie szablonów FreeMarker [24], Velocity [9] bądź generowanie stron w postaci plików PDF. Możliwa jest definicja procedury obsługi sytuacji wyjątkowych (ang. exception handlers), których rola polega na wychwytywaniu sytuacji potencjalnie niebezpiecznych dla 1 Pierwsze oficjalne wydanie biblioteki Struts 2, oznaczone numerem wersji 2.0.6, miało miejsce 22 lutego 2007 roku. 43

45 Rysunek 3.1: Architektura szkieletu programistycznego Struts 2 działania aplikacji i wyświetleniu zdefiniowanej strony. Interceptory umożliwiają dodawanie akcji po lub przed wykonaniem akcji, głównej związanej bezpośrednio z obsługą żądania. Podczas wykonywania standardowego scenariusza obsługi żądania (rysunek 3.1), żądanie przechodzi w pierwszej kolejności przez zestaw predefiniowanych filtrów, które można wykorzystać między innymi podczas tworzenia kompozycji stron. Następnie trafia do obiektu FilterDispatcher, który konsultuje się z obiektem ActionMapper w celu określenie czy z danym żądaniem została skojarzona akcja. Jeżeli obiekt odpowie twierdząco, sterowanie jest przekazywane do obiektu ActionProxy. Zadaniem ostatnio wspomnianego obiektu jest wygenerowanie, na podstawie plików konfiguracyjnych, akcji oraz poprzedzających ją interceptorów (wykorzystanie wzorca command pattern). Opisany ciąg zdarzeń wykonuje obiekt ActionInvocation, który jest dodatkowo odpowiedzialny za skojarzenie wyniku akcji z odpowiednim szablonem, najczęściej stroną JSP. Ostatnim z kroków jest ponowne wywołanie interceptorów, tym razem w odwrotnej kolejności i zwrócenie obiektu typu HttpServletResponse. Podczas pierwszego wywołania interceptorów, wywoływany jest warunek before. Natomiast podczas powrotu, warunek after. Do elementów tworzonych przez użytkownika należą: akcje, szablony, oraz pliki konfiguracyjne takie jak struts.xml. Interceptory oraz filtry są elementami opcjonalnymi. Pozostałe z wymienionych elementów zapewnia szkielet Struts Znaczniki Struts 2 wyposaża programistę w zestaw gotowych do wykorzystania znaczników (ang. tags), za pomocą których można tworzyć szablony w oderwaniu od używanej technologii widoku takiej jak strony JSP czy szablony Velocity. Większość ze znaczników jest uniwersalna, jednak niektóre z nich są charakterystyczne dla określonego języka wykorzystywanego podczas tworzenia warstwy widoku. 44

46 Rola znaczników polega na wyświetlaniu danych dynamicznych. W celu wyświetlenia pola zawierającego kod pocztowy, można wykorzystać fragment kodu przedstawiony na listingu 3.1. Jeżeli przekazany widokowi obiekt będzie zawierał opisywane pole, zosta- 1 <s:textfield name="postalcode" /> Listing 3.1: Znacznik Struts 2 przedstawiający pole kodu pocztowego nie ono automatycznie wyświetlone we wskazanym miejscu, podobnie podczas wysłania formularza pole obiektu zostanie uaktualnione. Można wyróżnić dwa typy znaczników: generyczne (ang. generic) oraz znaczniki interfejsu (ang. UI tags). Różnica, poza funkcją i implementowaną odpowiedzialnością, polega na tym iż znaczniki interfejsu, zwane również znacznikami HTML, posiadają wsparcie dla szablonów i motywów. Znaczniki generyczne kontrolują przepływ wykonania podczas generowania strony. Pozwalają również na wydobywanie danych z niestandardowych miejsc takich jak obiekty lokalizacji czy JavaBeans. W celu kontroli przepływu zawierają wyrażenia if, else czy iteratory. Przy manipulowaniu danymi wykorzystywane są znaczniki typu bean, push czy i18n. W przeciwieństwie do znaczników generycznych, znaczniki interfejsu nie posiadają wpływu nad logikę czy strukturę kontroli. Ich celem jest wyświetlanie przekazanych im danych. Wszystkie znaczniki interfejsu są sterowane szablonami bądź motywami. Podczas gdy znaczniki generyczne wyświetlają (w razie konieczności) zawartość w niesformatowany sposób, znaczniki interfejsu wykorzystują do tego celu szablony. Domyślnie Struts 2 dostarcza znaczników dla takich języków jak JSP, Velocity czy FreeMarker. Szablony, najczęściej tworzone z wykorzystaniem biblioteki FreeMarker, są grupowane w motywy (ang. theme) w celu zwiększenia ich funkcjonalności. Istnieją również znaczniki zaprojektowane do tworzenia formularzy. Standardowa dystrybucja opisywanego szkieletu, dostarcza szablony generujące strony oparte o język XHTML, wykorzystujące kaskadowe arkusze stylów bądź używające technologii AJAX [25]. Możliwe jest również skorzystanie z prostego szablonu, który wykorzystuje proste elementy HTML-a, jednak bez wsparcia dla walidacji, raportowania o błędach czy pomocy w formatowaniu treści Interceptory Wiele z użytych w aplikacji akcji wymaga zastosowania wspólnych rozwiązań. Przykładowo wiele akcji wymaga walidacji danych wprowadzonych przez użytkownika bądź przeprowadzenia wstępnej obróbki pliku umieszczanego na serwerze. Na osobną uwagę może zasługiwać problemem związany z podwójnym wysłaniem danych. Idea interceptorów wprowadza rozwiązanie pozwalające na współdzielenie rozwiązań, dotyczących wspomnianych wcześniej czynności. Podczas wysłania żądania, przed wykonaniem głównej akcji, następuje wywołanie metod ciągu obiektów. Podobna możliwość, w razie zaistnienia takiej potrzeby, jest możliwa po wywołaniu akcji głównej. Większość funkcjonalności dostarczanych ze szkieletem Struts 2 jest zaimplementowanych w postaci interceptorów. To wspomnianych funkcjonalności można zaliczyć: problem podwójnego wysłania danych, konwersję typów, automatyczne wyświetlanie własności obiektów, walidację, wsparcie w umieszczaniu plików na serwerze czy przygotowanie stro- 45

47 ny do wyświetlenia. Każdego z interceptorów wykorzystywanych do wymienionych zadań można dowolnie wyłączyć. Domyślny cykl wywołań interceptorów przedstawia się w sposób następujący: 1. Obiekt ServletDispatcher tworzy instancję nowego obiektu ActionProxy i wywołuje jego metodę execute(). 2. Poszczególne interceptory przechwytują żądanie wysłane do głównej akcji oraz powracające z niej. Za drugim razem ciąg wywołań interceptorów jest odwrotny w stosunku do pierwszego wywołania. 3. Kiedy ciąg wywołań interceptorów ulegnie zakończeniu, żądanie przesyłane jest do obiektu Result w celu wygenerowania odpowiedzi. Konfiguracja interceptorów odbywa się w pliku konfiguracyjnym struts.xml z wykorzystaniem języka XML. Możliwe jest łączenie interceptorów, implementujących określoną wspólną funkcjonalność, z wykorzystaniem elementu zwanego Interceptor Stack. Domyślny stos interceptorów jest wystarczający do działania większości aplikacji Implementacja wzorca MVC Struts 2 stanowi przykład szkieletu programistycznego implementującego wzorzec Model-Widok-Kontroler. Dostarcza obiektów kontrolerów, komponentów widoku oraz zapewnia wsparcie w zakresie integracji z innymi technologiami operującymi na modelu. W celu efektywniejszego wyświetlania dynamicznych danych, szkielet oferuje wsparcie w postaci znaczników. Rola znaczników polega na interakcji z frameworkiem i zapewnieniu walidacji oraz internacjonalizacji wprowadzanych i wyświetlanych danych. Wspomniane znaczniki mogą być wykorzystane z technologiami stron JSP czy szablonami FreeMaker bądź Velocity. Możliwe jest również wykorzystanie znaczników JSTL oraz technologii AJAX. Ponadto Struts 2 oferuje wsparcie podczas użycia komponentów JavaServer Faces. Po otrzymaniu żądania przez kontroler, wywoływana jest odpowiednia akcja, która przeprowadza aktualizację modelu. Podczas transferu danych z modelu do widoku, mogą zostać wykorzystane własności akcji bądź obiekty JavaBean. Szkielet zapewnia wsparcie w zakresie transformacji, tekstowej postaci własności przedstawionych jako pola formularza HTML do własności obiektów domeny Spring MVC Niniejsza sekcja stanowi wprowadzenie do biblioteki Spring MVC, jako iż została ona wybrana jako biblioteka przeznaczona do badań, znacząca część informacji jest umieszczona w dalszych rozdziałach. Działanie frameworka Spring MVC [48], części biblioteki Spring Framework implementującej Model 2, skupiona jest wokół obiektu DispatcherServlet, który przetwarza nadchodzące żądania i wywołuje odpowiednie kontrolery w celu ich obsłużenia. Jedną z zasad projektowych, stosowanych przy implementacji opisywanego szkieletu jest otwartość na rozszerzalność (ang. extension) przy jednoczesnej zamkniętości na zmiany. Wspomniana zasada została zaimplementowana poprzez zastosowanie słowa kluczowego final na wielu jego klasach. Świadomą decyzję autorów wprowadzającą opisywaną metodę, wyjaśnia artykuł [49]. Spring MVC promuje użycie obiektów biznesowych podczas interakcji z formularzami. Błędy związane z walidacją wprowadzanych danych stara się rozwiązać na poziomie aplikacji. Zwracany przez kontroler obiekt modelu powiązany z wybranym widokiem nosi 46

48 nazwę ModelAndView. Jest to mapa poszczególnych obiektów modelu przekazywanych do widoku. Jedną z zalet opisywanego szkieletu jest jego integracja z biblioteką Spring Framework, która dostarcza rozwiązania dla warstwy środkowej architektury trójwarstwowej. Do kluczowych funkcjonalności szkieletu Spring MVC należy: separacja ról kontrolera, modelu, widoku, walidatora każdej z ról odpowiada osobny wyspecjalizowany w działaniu obiekt, możliwość ponownego użycia kodu związanego z logiką biznesową aplikacji poprzez unifikację obiektów biznesowych z obiektami formularzy, konfigurowalność bindowania obiektów i ich walidacji, przygotowany zestaw znaczników JSP. Ponadto możliwe jest wykorzystanie biblioteki Spring Web Flow, której rola polega na zarządzaniu nawigacją między poszczególnymi stronami, z zachowaniem stanu pomiędzy wywoływaniami kolejnych stron Obiekt nadzorujący Opisywany framework implementuje Model 2, oparty na przetwarzaniu kierowanych do aplikacji żądań użytkownika. Rola obiektu DispatcherServlet polega na scentralizowanym przetwarzaniu nadchodzących żądań jak również oferowaniu innego wsparcia dla tworzenia aplikacji internetowych, poprzez wykorzystanie modułu Spring IoC, do którego ma dostęp. DispatcherServlet implementuje wzorzec zwany Front Controller, który oddelegowuje żądanie do odpowiedniego kontrolera, który w rezultacie swojego działania zwraca obiekty modelu wraz z wybranym widokiem. Więcej informacji na temat prezentowanego obiektu można znaleźć w następnym rodziale, szczegółowo opisującym framework Spring MVC. Szczegóły konfiguracyjne standardowo umieszczone są w pliku o nazwie, będącej połączeniem nazwy opisywanego pliku, zdefiniowanego w pliku web.xml oraz przyrostka -servlet.xml. Przykładowo dla obiektu dispatchera noszącego nazwę golfing, plik konfiguracyjny aplikacji opartej o Spring MVC będzie nosił nazwę golfing-servlet.xml. We wspomnianym pliku konfiguracyjnym możliwe jest zdefiniowanie obiektów Springa zwanych beans, tj.: obiekty kontrolerów, obiekty odpowiedzialne za wybór określonego kontrolera po odebraniu żądania skierowanego do aplikacji przez użytkownika, zwane handler mappings, obiekty które tłumaczą nazwy widoków do plików zawierających żądany szablon, najczęściej w postaci pliku JSP, zwane view resolvers, obiekty umożliwiające internacjonalizację serwowanej strony, zwane locale resolvers, obiekty pozwalające na szybką zmianę wystroju strony, zwane theme resolver, ponadto istnieje możliwość zdefiniowania obiektów odpowiedzialnych za odbieranie nadesłanych, za pomocą formularza plików (multipart file resolvers) czy obiekty przechwytujące wyjątki aplikacji (handler exception resolvers). Lista obejmuje jedynie ziarna charakterystyczne dla warstwy widoku implementowanej z użyciem biblioteki Spring MVC. Obiekt DispatcherServlet posiada ponadto możliwość, zwracania atrybutu last-modification-date, opisanego w specyfikacji Servlet API, zwracającego datę ostatniej modyfikacji żądanego zasobu. Definicje opisanych obiektów przechowywane są we wspomnianym pliku konfiguracyjnym, który posiada również odpowiednik w postaci klasy Java o nazwie specyficznej dla 47

49 aplikacji internetowej WebApplicationContext. Każda z instancji obiektu nadzorującego posiada własną kopię wspomnianego obiektu, którego obiektu automatycznie dziedziczą po obiektach zdefiniowanych domyślnie. WebApplicationContext stanowi rozszerzenie standardowego kontekstu aplikacji noszącego nazwę ApplicationContext, wzbogacony o elementy przydatne podczas działania aplikacji internetowej, np. zmienianie motywu wyglądu Znaczniki Począwszy od wersji 2.0 biblioteki Spring Framework wprowadzono zbiór znaczników, ułatwiających pracę nad tworzeniem szablonów. Generowany, przez bibliotekę, kod znaczników jest zgodny z specyfikacją HTML 4.01/XHTML 1.0. Działanie wszystkich znaczników jest podobne. Spring MVC posiada odpowiedniki następujących znaczników znanych ze specyfikacji HTML: form, input (checkbox, radio, password), select, option, textarea. Ponadto posiada znacznik errors służący do wyświetlania błędów związanych z przetwarzaniem formularza. Zastosowanie znaczników dostarczanych wraz ze Springiem ułatwia przede wszystkim, operowaniu ma obiektach formularza. Przykładowo formularz umieszczony na listingu 3.2, powoduje automatyczną obsługę obiektu user przekazanego widokowi przez kontroler. 1 <form:form commandname="user"> 2 <table> 3 <tr> 4 <td>imie:</td> 5 <td><form:input path="firstname" /></td> 6 </tr> 7 <tr> 8 <td>nazwisko:</td> 9 <td><form:input path="lastname" /></td> 10 </tr> 11 <tr> 12 <td colspan="3"> 13 <input type="submit" value="zapisz zmiany" /> 14 </td> 15 </tr> 16 </table> 17 </form:form> Listing 3.2: Zastosowanie znacznika form biblioteki Spring MVC Znaczniki dodatkowo wprowadzają rozróżnienie poszczególnych elementów formularzy. W specyfikacji HTML duża część znaczników stosowanych przy formularzy nosi po prostu nazwę input, dopiero atrybut type, wprowadza rozróżnienie na pola typu password, radio czy checkbox. Spring MVC zawiera intuicyjne nazwy dla każdego ze wspomnianych wcześniej elementów. Innym elementem związanym z zastosowaniem znaczników jest obsługa pól typu checkbox, które mogą być mapowane w zależności od potrzeb do zmiennych logicznych, kolekcji bądź obiektów. 48

50 Zasada konwencji Jedną z nowości drugiego wydania biblioteki Spring, było wprowadzenie elementów, które wykorzystują określone konwencje względem konfiguracji (ang. convention over configuration). Jest to wzorzec, który propaguje określony porządek rzeczy, wynikiem czego jest znacznie uproszczona konfiguracja lub często pozbycie się jej całkowicie. Podobny zabieg można zauważyć w opisanej wcześniej bibliotece Maven. Pierwsza z opisywanych konwencji dotyczy nazewnictwa dla kontrolerów przy odbieraniu żądań. Przykładowo kontroler noszący nazwę WelcomeController będzie odpowiedzialny za odbieranie żądań pasujących do wyrażenia URL /welcome*. Kolejna konwencja dotyczy nazewnictwa dla przekazywanego do widoku modelu. Przykładowo obiekt reprezentowany przez klasę User, będzie dostępny w szablonie widoku pod nazwą user, a lista kotów (obiektów typu Cat), zaimplementowana w postaci ArrayList będzie nosiła nazwę catlist. Ostatnia z proponowanych konwencji dotyczy powiązania nazwy kontrolera, obsługującego żądanie z widokiem. Kontroler posiadający uzgodnioną przez konwencję, nazwę RegistrationController, będzie domyślnie używał szablonu widoku o nazwie registration, co w połączeniu z innymi elementami konfiguracyjnymi prowadzi do uzyskania widoku znajdującego się w następującej lokalizacji /WEB-INF/jsp/registration.jsp Tapestry 5 Tapestry jest przedstawicielem frameworków, stosujących model komponentowy podczas tworzenia warstwy prezentacji. Wprowadza podział aplikacji internetowej na poszczególne strony, składających się z komponentów. Biblioteka odciąża użytkownika od spraw związanych z zarządzaniem adresami URL, zajmuje się utrzymaniem stanu zarządzanych obiektów, zarówno po stronie serwera jak i klienta. Tworzenie aplikacji sprowadza się do tworzenia szablonów oraz wsparcia ich w postaci kodu języka Java. Programista używający Tapestry operuje pojęciami obiektów, ich metod oraz własności, tworząc abstrakcję obejmującą adresy URL czy parametry żądania. Udostępniona wersja biblioteki nosi numer 4, opisywana wersja 5 [56] wciąż jest w fazie rozwoju. Planowane wydanie wersji jest zapowiadane na jesień 2007 roku. W wersji 5 w stosunku do wersji poprzedniej wprowadzono następujące zmiany: nie jest wymagane rozszerzanie klas szkieletu przez klasy komponentów, klasy komponentów nie są klasami abstrakcyjnymi, lecz zwykłymi obiektami Javy, zastąpiono konfigurację w postaci plików XML, adnotacjami umieszczanymi w kodzie języka Java, zmiany dokonywane na komponentach mają natychmiastowe odzwierciedlenie w działającej aplikacji, nie jest wymagany restart serwera, zwiększono szybkość działania samej biblioteki. Wprowadzone zmiany mają głównie za zadanie zwiększenie produktywności uzyskiwanej w pracy z opisywaną biblioteką oraz naprawiają błędy zgłaszane przez użytkowników poprzedniej wersji (obowiązek dziedziczenia w klasach komponentów). Działanie opisywanej biblioteki zostało zweryfikowane na serwerach Jetty, w wersji 5, 6 oraz Tomcat w wersji

51 Zasady Celem autora biblioteki jest utrzymanie wysokiej skalowalności tworzonego systemu. Możliwe jest to do osiągnięcia poprzez zastosowanie zasady statycznej struktury oraz dynamicznego zachowania. Idea statycznej struktury została wyrażona poprzez wykorzystanie statycznych stron szablonów, rozwiązanie korzystne w momencie tworzenia puli stron. Raz utworzona strona jest przechowywana w puli stron gotowa do ponownego użycia. Możliwe jest wykorzystanie dowolnego serwera do przetworzenia żądania, w przypadku użycia klastra. W porównaniu do JavaServer Faces strona jest mniej dynamiczna, konsekwencją tego jest mniejsza ilość danych przechowywanych w sesji, co w rezultacie daje większą skalowalność. Różnicą w stosunku do poprzedniej wersji jest wprowadzenie separacji między API publicznym a prywatnym biblioteki Tapestry. Stosowane uprzednio dziedziczenie sprawiało iż klasy komponentów były nieumyślnie wzbogacone o zbędne dla nich metody. Rozwiązaniem okazało się wprowadzenie interfejsów. Klasy znajdujące się w pakiecie org.apache.tapestry.internal stanowią wewnętrzne API biblioteki. Tapestry w nadchodzącej wersji będzie bazowało wyłącznie na klasach języka Java oraz adnotacjach. Za pomocą adnotacji będzie możliwe zarządzanie stanem obiektów czy wstrzykiwaniem zasobów Moduły Autorzy Tapestry 5, korzystają z Mavena podczas tworzenia swojej aplikacji. Pośrednią konsekwencją takiego wyboru jest zdefiniowanie modułów, będących częścią frameworka, posiadających ściśle określone zadania. Lista modułów wraz z krótkim opisem przedstawia się następująco: tapestry-core, główna część biblioteki Tapestry, zawierająca wszystkie najważniejsze elementy potrzebne przy korzystaniu z niej, tapestry-hibernate, moduł odpowiedzialny za integrację z biblioteką Hibernate, tapestry-ioc, kontener odwróconego sterowania, wykorzystywany przez moduł core, tapestry-spring, moduł odpowiedzialny za integrację z biblioteką Spring Framework, tapestry-test, narzędzia związane z przeprowadzaniem testów. W chwili obecnej (kwiecień 2007) najbardziej zaawansowany stan wykazują moduły tapestry-core oraz tapestry-ioc. Tapestry-core Tapestry-core zapewnia interfejsy oraz adnotacje składające się na bibliotekę Tapestry 5. Podczas działania wykorzystuje moduł tapestry-ioc. Opisywany moduł wprowadza pojęcie adaptacyjnego API. Podczas programowania z wykorzystaniem tradycyjnego szkieletu programistycznego, użytkownik musi wpasować się niejako w struktury oferowane przez dany framework, poprzez dziedziczenie czy implementację określonej klasy bądź interfejsu. Tapestry wprowadza adaptacyjność poprzez wykorzystanie adnotacji języka Java sprawiając, iż programista może dowolnie nazywać tworzone metody bądź parametry. Listing 3.3 prezentuje przykład komponentu wykorzystywanego na stronie z logowaniem użytkownika. Dla przejrzystości kodu, zrezygnowano z metod ustawiających i modyfikujących. Używane strony oraz serwisy wstrzykiwane są za pomocą adnotacji Inject. Adnotacja OnEvent znaczy metodę która ma zostać wywołana w przypadku wysłania przez stronę zdarzenia o nazwie submit. W przypadku otrzymania wspomnianego zdarzenia, komponent sprawdza wprowadzony identyfikator i hasło, wykorzystując serwis 50

52 1 public class Login 2 { 4 private String userid; 5 private String password; 7 private Form form; 9 private Start startpage; 11 private LoginAuthenticator authenticator; private Object dologin() 15 { 16 if(authenticator.isvalidlogin(userid, password)) 17 return _startpage; 18 form.recorderror("niepoprawny login badz haslo"); 19 return null; 20 } 21 } Listing 3.3: Komponent logowania wykorzystujący bibliotekę Tapestry 5 authenticator. W przypadku poprawnych danych użytkownik zostaje przeniesiony do strony startowej, w przeciwnym przypadku następuje wyświetlenie komunikatu o wprowadzeniu niepoprawnych danych. Ważnym uwaga dotyczy separacji przetwarzanej akcji oraz renderowania strony, z wykorzystaniem osobnych żądań. Przykładowo wciśnięcie przez użytkownika przycisku wysyłającego formularz, powoduje przekierowanie użytkownika na nową stronę. Opisane zdarzenie redirect after post sprawia, iż adres w oknie przeglądarki ulega zmianie po dokonaniu akcji wysłania formularza. Poprawia to użyteczność strony, gdyż każda strona jest identyfikowana przez indywidualny adres URL. Konsekwencją użycia podwójnego żądania jest konieczność użycia adnotacji Persist, która sprawia iż oznaczona własność, jest składowana w sesji między żądaniami. Tapestry-core definiuje również zbiór gotowych do użycia komponentów. W obecnie zaimplementowanym zbiorze znajdują się komponenty związane z obsługą pól formularza, linków, raportowaniem błędów oraz wyświetlaniem obrazków. Z wykorzystaniem ostatnio dodanego komponentu grid można tworzyć stronicowane listy wraz z sortowaniem po kolumnach. Tapestry-ioc Wnętrze biblioteki Tapestry 5 bazuje na wzorcu odwróconego sterowania, pozwalającego na budowaniu aplikacji z niewielkich części posiadających ściśle określone zadania. Rozwiązanie takie sprawia iż poszczególne części aplikacji można łatwiej modyfikować bądź rozszerzać, poprzez zastępowanie bądź nadpisywanie dotychczas istniejących. Śledząc zmiany frameworka, począwszy od wersji 3, można zauważyć postępujące zmiany w stosowaniu wzorca odwróconego sterowania. Tapestry 3 praktycznie nie używało 51

53 opisywanego wzorca, kolejna wersja wprowadziła kontener HiveMind. Tapestry 5 zrezygnowało z wykorzystania biblioteki HiveMind na rzecz dedykowanego rozwiązania. Podczas gdy obecnie stosowane kontenery IoC, takie jak HiveMind czy Spring, używają konfiguracji wyrażającej zależność poszczególnych elementów z wykorzystaniem XML-a, Tapestry wykorzystuje w tym celu adnotacje użyte wprost w kodzie języka Java. Wprowadzenie do aplikacji wzorca odwróconego sterowania pozwala na wprowadzenie zasady podziału odpowiedzialności, rozdziału ról oraz ogranicza powiązania poszczególnych komponentów systemu. Podstawową jednostką wykorzystywaną w Tapestry IoC jest usługa (ang. service). Każdy z serwisów składa się z interfejsu oraz jego implementacji. Usługi są identyfikowane za pomocą unikalnych identyfikatorów (id), standardowo id usługi jest tożsame z niekwalifikowaną nazwą interfejsu usługi. Poszczególne serwisy są grupowane w moduły. Definicję modułów wprowadzają budowniczowie modułów (ang. module builders), którzy za pomocą metod statycznych i obiektu definiuję poszczególne serwisy, dekorują oraz wprowadzają do konfiguracji serwisów. Metody konfigurujące serwisy noszą nazwę service builder methods. Rejestr (ang. registry) stanowi magazyn modułów i serwisów. Za pomocą identyfikatora jest możliwość pobrania wybranego serwisu. Metody serwisów mogą być dekorowane, wprowadzając aspekty związane z logowaniem, bezpieczeństwem czy transakcyjnością. Istnieje możliwość dodatkowej konfiguracji serwisów, z wykorzystaniem map lub kolekcji. Serwisy są inicjalizowane w razie potrzeby, domyślnie są reprezentowane w postaci proxy, które implementuje wskazany interfejs serwisu. Podczas pierwszego wywołania, serwis jest tworzony i zwracany. Domyślnym cyklem życia dla serwisów jest singleton JavaServer Faces JavaServer Faces [22] stanowi framework, którego celem jest uproszczenie tworzenia interfejsu użytkownika na platformie JEE. Standardowo JSF używa stron JSP jako technologii widoku, jest jego rozwinięciem. Możliwa jest jednak integracja z inną technologią widoku np. XUL [63]. Szkielet obsługuje cykl życia aplikacji internetowej z wykorzystaniem technologii serwletów. JavaServer Faces w zamierzeniach autorów specyfikacji ma stać się odpowiednikiem Swinga dla systemów internetowych, umożliwiając tworzenie aplikacji z wykorzystaniem gotowych komponentów. Możliwe jest również wykorzystanie znaczników wchodzących w skład biblioteki JSTL. Najpopularniejszą implementacją specyfikacji JSF jest biblioteka MyFaces, implementująca specyfikację JSR 127. Bezpośrednią konkurencją dla JSF są aplikacje napisane w technologii.net Specyfikacja JavaServer Faces stanowi jedynie specyfikację, która jest implementowana przez poszczególnych dostawców. Najważniejsze warunki wymagające spełnienia, przedstawia poniższy spis: Szkielet aplikacji posiadający standardowe komponenty interfejsu użytkownika, z możliwością ich edycji w zewnętrznym programie. 52

54 Zbiór klas języka Java posiadających odzwierciedlenie w komponentach interfejsu użytkownika, ich stanów, czy zdarzeń generowanych przez użytkownika. Rolą obiektów wspomnianych klas jest zarządzanie cyklem życia komponentów. Zastosowanie obiektów JavaBean do przesyłania zdarzeń generowanych po stronie klienta a akcją po stronie serwera. Interfejs programistyczny umożliwiający walidację danych wejściowych. Wsparcie w zakresie internacjonalizacji aplikacji. Automatyczne generowanie stanu oraz wyglądu aplikacji w zależności od używanej przez klienta przeglądarki. Zachowanie zasad użyteczności oraz dostępności definiowanych przez WAI [61]. Specyfikacja JSF jest tworzona w ramach procesu Java Community Process oznaczonego sygnaturą JSR 127, definiującą wersję 1.0 oraz 1.1. Najnowszą wersję 1.2, wydaną w maju 2006 roku definiuje proces JSR Architektura Poniższa sekcja zawiera wyłącznie wprowadzenie do architektury aplikacji opartej o JavaServer Faces. Więcej szczegółów znajduje się w kolejnym rozdziale. Do najważniejszych zadań składowych elementów szkieletu JavaServer Faces należą: reprezentacja komponentów użytkownika oraz obsługa ich stanów, obsługa generowanych zdarzeń, zapewnienie walidacji po stronie klienta oraz serwera, konwersja typów pomiędzy formularzami a obiektami Javy, definiowanie nawigacji pomiędzy stronami, obsługa internacjonalizacji, wsparcie w zakresie rozszerzania możliwości aplikacji (nowe komponenty). JSF zawiera w sobie dwie biblioteki znaczników, służące tworzeniu komponentów umieszczonych na stronach JSP jak i służących powiązaniu stanu komponentów do obiektów po stronie serwera. Typowymi składowymi aplikacji opartej o szkielet JSF są komponenty interfejsu użytkownika, biblioteka znaczników pomocnych przy tworzeniu, obiektów przechwytujących zdarzenia bądź walidatorów, tzw. managed beans tworzące powiązanie pomiędzy obiektami aplikacji i interfejsu, obiekty konfiguracji aplikacji oraz pozostałe takie jak walidatory czy konwertery. W typowym scenariuszu obsługi żądania, żądanie po dotarciu do kontenera serwletów wywołuje odpowiednią akcję, która jest przetwarzana z wykorzystaniem odpowiednich komponentów strony, które wraz ze wspierającymi je obiektami Javy, zwracają odpowiedź. Standardowo zdefiniowane komponenty posiadają odpowiednik większości istotnych znaczników dostępnych w specyfikacji HTML. Możliwe jest również napisanie własnych komponentów, w celu realizacji skomplikowanego elementu interfejsu użytkownika. Komponenty JSF wykorzystują podczas działania kompozycję, przykładowo wybór dnia w postaci kalendarza składa się z trzech rozwijanych list, pozwalających wybrać kolejno dzień, miesiąc i roku Składowe Warstwa widoku oparta jest domyślnie na stronach JSP, do ich wyświetlania wymagany jest obiekt ViewHandler, którego implementacja jest dostarczana przez poszczególnych dostawców. Składowymi stron są komponenty. Do zadań domyślnie wyznaczonych komponentom należą: wyświetlanie siebie, obsługa otrzymywanych zdarzeń oraz walidacja wprowadzanych przez użytkownika danych. 53

55 Wiązanie obiektów z widokiem realizowane jest z wykorzystaniem języka wyrażeń (EL), którego zadaniem jest łączenie obiektów JavaBean z kodem strony JSP. Listing 3.4 przedstawia różne formy wiązania obiektów. 1 <!-- wiazanie wlasnosci obiektu --> 2 <h:inputtext value="#{user.name}" /> 3 4 <!-- wiazanie z metoda w polaczeniu z walidacja --> 5 <h:inputtext id="userid" value="#{user.id}" validator="#{user.validate}" /> 6 7 <!-- wiazanie nawigacji miedzy stronami --> 8 <h:commandlink action="#{nawigacja.naststrona}"> Listing 3.4: Wiązanie obiektów Javy z wykorzystaniem języka Unified Expression Language Obsługa zdarzeń możliwa jest na dwa sposoby. Jeden polega na implementacji interfejsu Listener oraz użyciu odpowiedniego znacznika. Drugi sposób polega na implementacji metody w obiekcie JavaBean i późniejszym odwołaniu się do niego przez własność komponentu. Definiowanie nawigacji między stronami odbywa się w pliku konfiguracyjnym z wykorzystaniem składni języka XML. Standardowo definiowana jest strona do wczytania w przypadku powodzenia przetworzenia żądania oraz strona wejściowa. Walidacja jest możliwa zarówno po stronie serwera jak i klienta, z użyciem standardowych walidatorów bądź zdefiniowanych przez użytkownika Implementacja wzorca MVC JavaServer Faces stosuje model komponentowy, wzbogacając tradycyjny Model 2. Opisywana biblioteka pozwala na zbudowanie abstrakcji nad żądaniami protokołu HTTP i oparciu aplikacji o komponenty i generowane z ich wykorzystaniem zdarzenia. JSF modyfikuje architekturę prezentowaną przez Model 2, pozwalając na łatwiejszą separację logiki biznesowej oraz prezentacji poza obręb kontrolera oraz wyodrębnieniu logiki biznesowej poza strony JSP. W implementacji wzorca MVC, stosowanej przez bibliotekę JSF, ziarna zarządzane (ang. managed beans) pośredniczą pomiędzy widokiem a modelem. Z tego powodu należy dbać o ograniczenie ich roli w zakresie implementacji logiki biznesowej aplikacji czy logiką związaną z utrwaleniem danych. Jedną z alternatyw jest przesunięcie logiki biznesowej do modelu aplikacji, w tym scenariuszu zarządzane ziarna są również odpowiedzialne za mapowanie obiektów modelu do widoku, gdzie mogą zostać wyświetlone. W odróżnieniu do technologii JSP, widok implementowany w postaci stron JSF jest stanowy, składa się z dwóch części: widoku korzenia oraz stron JSP. Korzeń składa się ze zbioru komponentów, zarządzających stanem interfejsu użytkownika, podobnie jak Swing czy AWT. Zadaniem strony JSP jest połączenie komponentów ze stronami JSP oraz stworzeniu możliwości interakcji pomiędzy polami komponentów a ziarnami wspierającymi (ang. backing beans). 54

56 4. Porównanie Spring MVC oraz JavaServer Faces Celem poniższego rozdziału jest analiza porównawcza funkcjonalności oferowanej przez wybrane szkielety programistyczne. W porównaniu zostały uwzględnione framework Spring MVC oraz standard platformy JEE, JavaServer Faces. Rozdział został podzielony na pięć części, w każdej został opisany osobny aspekt działania badanych szkieletów programistycznych. Pierwsza część zawiera charakterystykę architektury. W następnej opisano model programistyczny, czyli czynności wykonywane przez programistę tworzącego aplikację internetową, z uwzględnieniem sposobu definicji przejść między stronami. W kolejnej przedstawiono cykl życia nadchodzącego do aplikacji żądania oraz jego obsługę w ramach przedstawianych frameworków. W następnej kolejności opisano sposoby walidacji danych wprowadzanych przez użytkownika oraz ich konwersję na typy języka Java. Tematem ostatniej części jest internacjonalizacja i lokalizacja aplikacji Architektura Poniższa część skupia się na opisie elementów składowych opisywanych szkieletów programistycznych, interakcji jakie zachodzą między nimi oraz wyjaśnia ich przeznaczenia na tle całego systemu Spring MVC Warstwa prezentacji implementowana przez framework Spring MVC wpasowuje się w większy obraz aplikacji tworzonej z użyciem szkieletu Spring Framework [10]. Kontrolery odpowiedzialne za zarządzanie modelem aplikacji komunikują się z użyciem usług, nie mają bezpośredniego dostępu do modelu aplikacji. Rysunek 4.1 prezentuje architekturę szkieletu Spring MVC. Jak wspomniano we wcześniejszych rozdziałach, opisywany framework realizuje implementację Modelu 2, wykorzystując wzorzec projektowy MVC. Dostęp do modelu jest realizowany z wykorzystanim usług zdefiniowanych w warstwie biznesowej. Dostępem do widoku zajmują się obiekty zwane resolverami. Pozostałe elementy, takie jak walidatory czy elementy internacjonalizujące, uważane często za składowe szkieletów implementujących wzorzec MVC, zostały zdefiniowane w innym warstwach Springa. Typowa aplikacja realizowana z wykorzystaniem szkieletu Spring Framework składa się z pięciu warstw, zgrupowanych w trzy inne warstwy wyższego poziomu: interfejsu użytkownika, webowej, usług, obiektów domeny, utrwalania. 55

57 Rysunek 4.1: Architektura szkieletu Spring MVC Interfejs użytkownika wraz z warstwą webową należą do najwyższej warstwy wyższego poziomu. Warstwa usług i obiektów domeny mieszczą się w warstwie środkowej. Na samym dole znajduje się warstwa związana z utrwalaniem modelu aplikacji. Obiekty warstwy domeny jako jedyne są rozproszone po pozostałych warstwach. Separacja poszczególnych warstw sprzyja zwiększeniu elastyczności aplikacji oraz ułatwia ich testowanie. Najlepszą metodą jest zapewnienie aby poszczególne warstwy posiadały zależności wyłącznie w warstie znajdującej się bezpośrednio pod nią. Rolą warstwy interfejsu użytkownika jest prezentacja wizerunku aplikacji użytkownikowi końcowemu. Zwraca odpowiedź wygenerowaną przez warstwę niższą w formie żądanej przez użytkownika. Odpowiedź zwracana użytkownikowi telefonu komórkowego jest przedstawiana zwykle za pomocą języka WML, natomiast użytkownik komputera stacjonarnego oczekuje strony interpretowalnej za pomocą przeglądarki, najczęściej strony HTML. Warstwa interfejsu użytkownika sprawia, iż możliwa jest zamiana używanych technologii widoku, począwszy od wyboru stron JSP, szablonów Velocity a kończąc na transformacjach XSLT [21]. Innym ważnym aspektem jest odmienność narzędzi wykorzystywanych podczas tworzenia opisywanej warstwy, co wiąże się ze specjalizacją ról osób nad nią pracujących. Strona związana z warstwą interfejsu jest reprezentowana przez interfejs View, jest to element posiadający całkowice generyczny charakter, nie związany z żadną z technologii widoku. Spring standardowo dostarcza wsparcie dla stron w postaci: JSP, szablonów Velocity, FreeMaker, XSLT, JasperReports oraz plików PDF. Obiekt Resolver wprowadza użyteczną abstrakcję związaną z wyborem widoku dla serwowanej odpowiedzi. Głównym zadaniem warstwy webowej jest zapewnienie poprawnej nawigacji w aplikacji, poprzez wykorzystanie obiektu Handler, przedstawionego na rysunku 4.1. Drugim zadaniem opisywanej warstwy jest zapewnienie komunikacji pomiędzy warstwą usług a protokołem HTTP, reprezentowanym poprzez parametry żądania czy pliki ciasteczek (ang. cookies). Warstwa webowa jest implementowana przeważnie z użyciem serwletów, których rola polega na transformacji parametrów żądania do obiektów języka Java, zrozumiałych przez warstwę usług, jak również zamianie błędów warstw niższych na zrozumiałe dla użytkownika komunikaty. Interfejsem używanym w opisywanej warstwie dostarczanym wraz z Springiem jest Controller. Rolą wspomnianego interfejsu jest odbiór żądania i wygenerowanie na jego podstawie odpowiedzi. Odpowiedź jest prezentowana przez obiekt ModelAndView, za- 56

58 Rysunek 4.2: Architektura szkieletu JavaServer Faces wierający widok oraz mapę danych wykorzystywanych poprzez warstwę interfejsu przy formatowaniu odpowiedzi JavaServer Faces Rysunek 4.2 przedstawia poszczególne komponenty składające się na architekturę biblioteki JavaServer Faces. Trzon frameworka składa się z sześciu różnych warstw, o ściśle wyznaczonym przeznaczeniu. Głównym zadaniem warstwy komponentów interfejsu jest definicja funkcjonalności jakie oferują dostępne na stronie elementy. Składa się z obiektów JavaBean reprezentujących różne własności poszczególnych komponentów. Istniejąca klasa abstrakcyjna wspólna dla wszystkich elementów interfejsu definiuje zachowanie i stan, który jest przestrzegany przez każdy z komponentów potomnych. Każdy z komponentów posiada swój identyfikator, zmienne lokalne oraz pewien zbiór atrybutów generycznych. Ich zachowanie jest definiowane za pomocą zdarzeń, poprzez które zostają związane z modelem zdarzeń. Każdy z elementów interfejsu użytkownika może zostać dodatkowo powiązany z wymiennymi walidatorami, których zadaniem jest weryfikacja danych podanych przez użytkownika, przed wywołaniem właściwej logiki aplikacji. W skład komponentów użytkownika zdefiniowanych w specyfikacji JavaServerPages można znaleźć komponenty odpowiedzialne za generowanie zdarzeń, np. poprzez naciśnięcie przycisku wysyłającego dane formularza, komponenty związane z obsługą formularzy, wyświetlaniem rysunków, pobieraniem danych od użytkownika, wyświetlające dane czy formatujące wygląd strony. Model wyglądu definiuje sposób renderowania poszczególnych komponentów interfejsu użytkownika. Każdy z komponentów umieszczonych w aplikacji może posiadać inny wygląd w zależności od wykorzystywanych obiektów renderujących. Przykładowo element Submit wysyłający dane formularza, może zostać przedstawiony albo za pomocą przycisku albo z wykorzystaniem linka. Opisywane rozwiązanie wprowadza separację zachowania i funkcji komponentu od jego wyglądu. Możliwe jest przez podmianę obiektów renderujących wyświetlenie aplikacji zarówno na ekranie komputera, z użyciem języka HTML, jak i na ekranie telefonu komórkowego, posługując się językiem WML. Opisywane obiekty renderujące pełnią podobną funkcję co XSLT w przypadku dokumentów XML. 57

59 Model zdarzeń funkcjonujący w aplikacjach opartych o JavaServer Faces, jest podobny do tego oferowanego przez obiekty JavaBean. Definiuje zdarzenia oraz obiekty nasłuchujące, które są odpowiedzialne za odbiór zdarzenia wygenerowanego z użyciem pewnego komponentu interfejsu użytkownika. Obiekt zdarzenia posiada informację o komponencie, będącym źródłem zdarzenia oraz dane związane z samym zdarzeniem. Aby obiekt zainteresowany pewnym zdarzeniem mógł podjąć akcję w momencie jej wywołania, konieczne jest dokonanie jego rejestracji w obiekcie generującym zdarzenie. W momencie aktywacji zdarzenia, np. poprzez naciśnięcie przycisku, wszystkie zgłoszone metody nasłuchujące są wywoływane. Opisywany model jest kopią zachowania dostępnego w aplikacjach Swingowych i opiera się na wzorcu Obserwatora. Aplikacje wykorzystujące JavaServer Faces wspierają dwa typy zdarzeń. Do pierwszej grupy zaliczają się zdarzenia związane ze zmianą stanu elementów interfejsu, poprzez np. zaznaczenie chceckboxa i zmianie jego wartości z true na false. Drugą grupę zdarzeń stanowią akcje podejmowane przez użytkownika poprzez kliknięcie przycisku bądź linka. Szkielet walidacji dostarcza mechanizmów za pomocą których możliwe jest podpięcie walidatorów pod określone komponenty interfejsu użytkownika. Walidatory są zwykłymi obiektami implementującymi określony interfejs. Dodatkowo opisywany szkielet dostarcza rozwiązań pozwalających na wyświetlenie błędów związanych z walidacją. Istnieje możliwość definiowania własnych walidatorów jak i skorzystania z już gotowych. Domyślnie dostarczane walidatory umożliwiają określenie obowiązkowości wystąpienia wartości dla określonego komponentu, podania napisu o określonej długości czy liczby o wartości z zadanego zakresu. Szkielet nawigacji umożliwia definicję przejść pomiędzy poszczególnymi stronami aplikacji za pomocą składni języka XML. Przejścia definiowane są w obrębie określonych zasad nawigacyjnych (ang. navigation rules), posiadających standardowo wartości i powiązane z nimi strony JSP. Zaletą opisywanego rozwiązania jest separacja zagadnień związanych z nawigacją i procesem wyświetlania stron. Ostatnim z opisywanych elementów jest szkielet dostarczający wsparcia w zakresie internacjonalizacji stron, poprzez dostosowywanie interfejsu aplikacji do potrzeb użytkownika. Dostarczane informacje statyczne tłumaczone są z wykorzystaniem określonych kluczy, posiadających wartości w różnych językach. Internacjonalizacja treści dynamicznej jest zarządzana przez ziarna modelu. Elementy pomocnicze zaznaczone na rysunku 4.2 składają się w głównej mierze z obiektów wspomagających (ang. backing beans) oraz klas pomocniczych takich jak walidatory bądź konwertery, stanowiących implementację wspomnianych wcześniej warstw. Obiekty wspierające mają postać obiektów JavaBean, które pośredniczą w wymianie informacji pomiędzy warstwą interfejsu użytkownika a modelem biznesowym, poprzez wykorzystanie uniwersalnego języka wyrażeń (UEL). Możliwy jest dostęp do modelu aplikacji z poziomu obiektów wspomagających. W związku z tym, iż opisywane obiekty pełnią rolę pośrednika między widokiem a modelem, przypisuje się im funkcję kontrolerów, choć w zasadzie aplikacje oparte o JavaServer Faces są aplikacjami zorientowanymi na strony i nawigację pomiędzy nimi. Strona JavaServer Faces składa się z obiektów umieszczonych po stronie serwera oraz komponentów interfejsu użytkownika, zgrupowanych w strukturze drzewiastej. Informacja o stanie w jakim znajduje się aplikacja może być przechowywana zarówno po stronie klienta jak i serwera, w zależności od dokonanej konfiguracji. We wspomnianej strukturze drzewiastej, każdy z komponentów jest adresowany za pomocą unikalnego identyfikatora. 58

60 Podsumowanie Oba szkielety programistyczne posiadają podobną funkcjonalność, zaimplementowaną jednak w odmienny sposób. Podstawową różnicą jest typ zaimplementowanego modelu. Spring MVC jest typowym przedstawicielem frameworka realizującego Model 2, JavaServer Faces prezentuje model komponentowy. Spring MVC realizuje koncepcję aplikacji internetowej opartej o żądania i odpowiedź. Używa w tym celu kontrolerów operujących na modelu, z wykorzystaniem warstwy usług i zwracającym dane osadzone na wybranym widoku (najczęściej stronie JSP). W skład opisywanej biblioteki wchodzą wyłącznie elementy realizujące wzorzec MVC, pozostałe są zdefiniowane w innych warstwach szkieletu Spring Framework. Opisywana sytuacja wynika z faktu, iż Spring MVC jest jedynie częścią frameworka warstwy środkowej jakim jest Spring Framework. JavaServer Faces stanowi standard specyfikacji JEE, umożliwiający tworzenie aplikacji internetowych z naciskiem na interfejs użytkownika zbudowany w sposób komponentowy. JSF posiada w swojej ofercie wszystkie elementy potrzebne do budowy zaawansowanej aplikacji internetowej. Różnica w stosunku do Spring MVC polega na użyciu innego modelu, JSF jest szkieletem zorientowanym przede wszystkim na strony (ang. page-oriented). Budowa aplikacji opartej o architekturę zastosowaną w szkielecie JavaServer Faces dostarcza programiście wyższy poziom abstrakcji powodując, iż programista operuje pojęciami zdarzeń i komponentów, a nie jak w przypadku Spring MVC żądaniami i znacznikami JSP Model programistyczny Niniejsza część przedstawia model programistyczny stosowany w obu badanych bibliotekach. Prezentuje spojrzenie z punktu widzenia programisty pracującego z opisywaną biblioteką, pozwalając czytelnikowi na zorientowanie się w sposobie konfiguracji i rozmieszczenia poszczególnych części aplikacji. Dodatkowo uwzględniono aspekt związany z nawigacją między stronami aplikacji, jako nieodłączną część modelu programistycznego. Opisywane przypadki pochodzą z implementacji przykładowej aplikacji, która w dalszej części pracy posłuży do praktycznego porównania badanych bibliotek Spring MVC W przypadku tworzenia aplikacji opartej o Spring MVC zadanie biblioteki polega na odbiorze żądań użytkownika i kierowaniu ich w dalszej kolejności do obsłużenia przez wybrany kontroler, który w wyniku swojego działania zwraca model wraz z widokiem wykorzystanym do wyświetlenia danych modelu. Całość konfiguracji aplikacji opartej o Spring MVC mieści się w pliku o nazwie charakterystycznej dla aplikacji petclinic-servlet.xml. Zawiera on elementy niezbędne do prawidłowej pracy aplikacji wykorzystującej opisywaną bibliotekę. Najważniejszą częścią obsługującą żądania jest bean typu SimpleUrlHandlerMapping grupujący obsługę podobnych zadań w jeden kontroler. Mapowania nazw widoków zwracanych przez metodę obsługującą żądanie jest implementowane z użyciem elementu typu ResourceBundleViewResolver, który do realizacji powierzonego mu zadania wykorzystuje, edytowany przez programistę, plik properties. Ostatnim ważnym elementem głównego pliku konfiguracyjnego są beany typu PropertiesMethodNameResolver, które mapują adresy URL do konkretnych metod określonych kontrolerów. 59

61 Listing 4.1 prezentuje bean odpowiedzialny za grupowanie podobnych funkcjonalnie akacji w jeden kontroler typu MultiActionController. Każdy z wymienienionych w pliku konfiguracyjnym kontrolerów jest odpowiedzialny za obsługę innej encji. 1 <bean id="urlmapping" 2 class="org.springframework.web.servlet.handler.simpleurlhandlermapping"> 3 <property name="mappings"> 4 <props> 5 <prop key="/welcome.xhtml">petcliniccontroller</prop> 6 <prop key="/vets/*">vetscontroller</prop> 7 <prop key="/search/*">searchcontroller</prop> 8 <prop key="/visits/*">visitscontroller</prop> 9 <prop key="/owners/*">ownerscontroller</prop> 10 </props> 11 </property> 12 </bean> Listing 4.1: Bean Spring MVC mapujący adresy URL do kontrolerów Kontroler mogący podejmować wiele akcji, zmapowany na wiele adresów URL został przedstawiony na listingu 4.2. W definicji beana znajduje się referencja do beana usługi, związanej z obsługą weterynarzy. Usługa ta jest wykorzystywana podczas realizacji zapytania skierowanego przez użytkownika, np. o listę wszystkich weterynarzy leczących w klinice. 1 <bean id="vetscontroller" 2 class="org.panachida.webcream.web.springmvc.web.vetscontroller"> 3 <property name="vetservice" ref="vetservice" /> 4 <property name="methodnameresolver" ref="vetscontrollerresolver" /> 5 </bean> Listing 4.2: Bean Spring MVC opisujący kontroler Ostatnim z elementów pliku konfiguracyjnego, który został przedstawiony na listingu 4.3 jest resolver. Jego funkcja polega na mapowaniu adresów URL do metod kontrolera typu MultiActionController w celu obsłużenia żądania. W wyniku przedsta- 1 <bean id="vetscontrollerresolver" 2 class="org.springframework...mvc.multiaction.propertiesmethodnameresolver"> 3 <property name="mappings"> 4 <props> 5 <prop key="/vets/vets.xhtml">vetshandler</prop> 6 <prop key="/vets/vet-details.xhtml">vetdetailshandler</prop> 7 </props> 8 </property> 9 </bean> Listing 4.3: Bean Spring MVC mapujący żądania do metod kontrolera 60

62 wionej konfiguracji żądanie użytkownika skierowane pod adres zakończony ciągiem znaków /vets/vet-details.xhtml zostanie obsłużone przez metodę posiadającą nazwie vetdetailshandler znajdującą się w kontrolerze o nazwie vetscontroller. Wspomniana metoda vetdetailshandler została przedstawiona na listingu 4.4 (w celu zwiększenia przejrzystości kodu, pominięto zgłoszenie wygenerowanego wyjątku). Podczas 1 public ModelAndView vetdetailshandler(httpservletrequest request, 2 HttpServletResponse response) { 3 ModelAndView mav = new ModelAndView("vetDetailsView"); 4 Long vetid = ServletRequestUtils.getRequiredLongParameter(request, "vetid"); 5 Vet vet = vetservice.getbyid(vetid); 6 mav.addobject(vet); 7 List<Visit> scheduledvisits = vetservice.getscheduledvisits(vet); 8 mav.addobject(scheduledvisits); 9 return mav; 10 } Listing 4.4: Metoda szkieletu Spring MVC obsługująca żądanie tworzenia modelu wykorzystywany został widok o nazwie vetdetailsview, którego definicja znajduje się w pliku properties (listing 4.5). Fragment definiujący opisywaną nazwę widoku wskazuje na konkretny plik JSP wykorzystywany do przedstawienia danych modelu. 1 vetdetailsview.(class)=org.springframework.web.servlet.view.jstlview 2 vetdetailsview.url=/web-inf/pages/vets/vet-details.jsp Listing 4.5: Fragment pliku views.properties aplikacji Spring MVC JavaServer Faces W celu obsłużenia nadchodzących żądań specyfikacja JavaServer Faces wprowadziła dodatkowy poziom abstrakcji, próbujący upodobnić proces tworzenia aplikacji internetowych do procesu tworzenia aplikacji desktopowych. JSF pozwala na korzystanie z gotowych komponentów, potrafi wyświetlić informację użytkownikowi o włączonej blokadzie wyskakujących okien, w przypadku gdy mogłoby to zakłócić pracę z aplikacją, automatycznie generuje pliki JavaScript oraz kaskadowych arkuszy stylów dopasowane do języka użytkownika i wykorzystywanej przeglądarki. Domyślnie konfiguracja aplikacji opartej o JSF zawarta jest w pliku noszącym nazwę faces-config.xml. Zawiera przede wszystkim definicje beanów wykorzystywanych podczas działania aplikacji, mogących mieć opcjonalnie odzwierciedlenie w komponentach interfejsu użytkownika jak również definicję przejść między stronami aplikacji. Przykład beanu powiązanego z elementem interfejsu odpowiedzialnego za tabelaryczne przedstawienie weterynarzy kliniki znajduje się na listingu 4.6. Poprzez konstrukcję #{vetservicebean}, następuje powiązanie beana JSF z beanem zarządzanym przez Springa (wymagane jest użycie elementu DelegatingVariableResolver). Kolejnym elementem pliku konfiguracyjnego są definicje związane z nawigacją w aplikacji. Przykład elementu nawigacyjnego prezentuje listing

63 1 <managed-bean> 2 <managed-bean-name>vetstable</managed-bean-name> 3 <managed-bean-class> 4 org.panachida.webcream.web.jsf.tables.vetstablebean 5 </managed-bean-class> 6 <managed-bean-scope>session</managed-bean-scope> 7 <managed-property> 8 <property-name>vetservicebean</property-name> 9 <value>#{vetservicebean}</value> 10 </managed-property> 11 </managed-bean> Listing 4.6: Bean zarządzany JavaServer Faces 1 <navigation-case> 2 <from-outcome>vetdetails</from-outcome> 3 <to-view-id>/pages/vets/vet-details.jspx</to-view-id> 4 <redirect /> 5 </navigation-case> Listing 4.7: Element definiujący nawigację aplikacji JSF Tworzenie stron polega na korzystaniu z gotowych komponentów, które zostają wyrażone w kodzie strony poprzez odpowiednie znaczniki. Do ustawiania własności komponentów służą wartości atrybutów używanych znaczników. W przypadku tabeli mamy np. możliwość ustawienia liczby wierszy prezentowanych na jednym ekranie. Jeżeli liczba obiektów jest większa niż ustalona wielkość, komponent JavaServer Faces dodaje elementy nawigacyjne ułatwiające przemieszczanie się po wyświetlanym zbiorze danych. Komponenty stron są ograniczone do korzystania wyłącznie z beanów zdefiniowanych w pliku faces-config.xml. Komponent reprezentujący tabelę odpytuje beana o zbiór weterynarzy, który później zostaje zwrócony jako odpowiedź. Praktycznie każdy używany w aplikacji komponent posiada wspierającego go beana (ang. backing bean) Podsumowanie Oba z przedstawionych szkieletów programistycznych charakteryzują się odmiennym modelem programistycznym. Model oparty o Spring MVC jest bardziej zbliżony do tradycyjnego modelu, prezentowanego np. przez framework Struts. JavaServer Faces prezentuje model oparty o tworzenie komponentów oraz obsługi zdarzeń generowanych z jego pomocą. W aplikacji opartej o Spring MVC, użytkownik definiuje mapowania żądań do nadzorujących aplikację kontrolerów. Kontroler po wykonaniu operacji na modelu, zwraca pobrane z niego dane wraz z wybranym widokiem. Użytkownik tworzący aplikację widzi bezpośrednio zależność od wzorca MVC. Aplikacja wykorzystująca JavaServer Faces, skupia się na szablonach, tworzonych z komponentów, umożliwiając podejmowanie akcji użytkownikowi poprzez zainicjowanie przez niego określonych zdarzeń, z wykorzystaniem wspomnianych komponentów. Nie ma jasno wydzielonego kontrolera, są tylko metody, których zadaniem jest reakcja na otrzymane zdarzenia. 62

64 Rysunek 4.3: Procedura obsługi żądania szkieletu Spring MVC 4.3. Cykl życia żądania Celem niniejszej sekcji jest przedstawienie opisu cyklu życia żądania kierowanego przez użytkownika aplikacji. W przypadku szkieletu opartego o komponenty, żądania zostały zamienione na zdarzenia generowane z użyciem poszczególnych komponentów umieszczonych na stronie Spring MVC Obsługa nadchodzącego żądania została przedstawiona na rysunku 4.3. Centralnym elementem zarządzającym obsługą otrzymanego żądania jest obiekt DispatcherServlet, który koordynuje pracę całego cyklu żądania. Jego konfiguracja odbywa się w standardowym deskryptorze aplikacji internetowej, pliku web.xml. Obiekt implementujący interfejs HandlerMapping wskazuje obiektowi nadzorującemu, który kontroler należy wywołać w celu obsłużenia otrzymanego żądania. Spring dostarcza wielu implementacji wspomnianego interfejsu, pozwalając mapować kontrolery po nazwach beanów ich reprezentujących bądź w zależności od potrzeb za pomocą plików properties. Krok trzeci obsługi żądania polega na wywołaniu wybranego kontrolera. Zadaniem kontrolera jest przetworzenie otrzymanego żądania oraz przeprowadzenie wymaganych procesów biznesowych. Kontroler stanowi obiekt implementujący interfejs Controller lub jeden z interfejsów pochodnych. Zwraca obiekt ModelAndView oznaczony na rysunku słowem Model. Wspomniany obiekt zawiera dane pomocnicze, które zostały uzyskane z warstwy usług w celu zaspokojenia żądania oraz obiekt widoku będący wskazaniem na określony zasób bądź implementujący interfejs View. Rolą obiektu implementującego interfejs ViewResolver jest zamiana logicznej nazwy zwracanego przez kontroler widoku na fizyczny plik zawierający szablon strony internetowej. Tak jak w poprzednich przypadkach Spring dostarcza wielu implementacji wspomnianego interfejsu, pozwalając definiować mapowania logicznych nazw widoków za pomocą określonych przedrostków i przyrostków jak i z wykorzystaniem pliku properties. Ostatnim elementem obsługi żądania, zaznaczony na rysunku w kroku szóstym, jest widok reprezentowany przez interfejs View. Jego rola polega na sformatowaniu odpowiedzi na podstawie otrzymanych danych pomocniczych. Domyślnie Spring posiada wsparcie dla widoków będących stronami JSP, transformacjami XSLT, szablonami Velocity bądź Fre- 63

65 Rysunek 4.4: Procedura obsługi żądania szkieletu JavaServer Faces emaker, jak również arkuszami Excela, raportami JasperReports, czy plikami w formacie PDF JavaServer Faces Cykl życia żądania aplikacji JavaServer Faces składa się z sześciu ściśle określonych faz przedstawionych na rysunku 4.4. W swojej istocie są zbliżone do przetwarzania zdarzeń znanych z aplikacji desktopowych. Możliwa jest zmiana kolejności wykonywania poszczególnych faz jak również pominięcie niektórych z nich. Jednakże logika i konsekwencja jaką kierowali się autorzy opisywanej biblioteki sprawia iż w większości przypadków standardowe ustawienie faz jest wystarczające. Poszczególne fazy obsługi żądania można przyporządkować do dwóch odmiennych poziomów. Faza pierwsza i ostatnia, zajmujące się utworzeniem widoku oraz odpowiedzi należą do poziomu systemowego. Pozostałe cztery mieszczą się w poziomie zwanym poziomem aplikacji. W fazie pierwszej obejmującej utworzenie widoku, następuje odebranie żądania przez obiekt kontrolera FacesServlet. Kontroler przetwarza otrzymane żądanie oraz pobiera identyfikator widoku, który jest wyznaczany na podstawie żądanej strony JSP. Posiadany identyfikator służy do wyboru komponentów składających się na wybrany widok. Jeżeli żądany widok istnieje, wówczas zostaje pobrany do dalszego przetwarzania, w przeciwnym przypadku jest tworzony nowy widok. Cykl życia jest związany z trzema różnymi instancjami widoku: nowym, inicjującym bądź ponownie wczytanym (ang. postback). W przypadku widoku określanego mianem nowy, kontroler JSF tworzy widok z komponentów podłączając do nich metody nasłuchujące oraz walidatory, po czym składuje w obiekcie FacesContext. Wspomniany obiekt posiada wszystkie informacje związane z zarządzaniem stanami komponentów interfejsu użytkownika podczas przetwarzania żądania przechowywanych w strukturze drzewiastej. W przypadku widoku inicjującego, podczas pierwszego wczytania strony, kontroler tworzy pusty widok, który jest zapełniany podczas akcji podejmowanych przez użytkownika. Ostatni z instancji widoków jest używany podczas ponownego wczytania widoku, ponieważ widok już wcześniej był używany wymagane jest jedynie odnowienie strony (ang. restore). Przeznaczeniem drugiej fazy życia żądania jest pobranie stanu aktualnie wybranych komponentów. W celu skorzystania z komponentów muszą one zostać najpierw pobrane lub utworzone przy pomocy obiektu FacesContext. Standardowo pobranie komponentów odbywa się na podstawie parmetrów żądania, jego nagłówków bądź sesji. 64

66 Jeżeli natychmiastowe wychwycenie zdarzeń jest wyłączone, poszczególne parametry żądania zostają przekonwertowane do odpowiadającym im obiektom języka Java. W razie wystąpienia błędu generowana jest informacja umieszczana w obiekcie FacesContext, która zostanie wyświetlona w ostatniej fazie obsługi żądania wraz z innymi błędami. W przypadku włączenia natychmiastowego wychwycenia zdarzeń, parametr jest poddawany walidacji. W przypadku wystąpienia błędu, następuje wygenerowanie odpowiedniego komunikatu. Rolą kolejnej fazy jest walidacja wartości związanych z poszczególnymi komponentami. Część z reguł walidujących jest predefiniowana, istnieje również możliwość stworzenia własnych walidatorów. W przypadku niespełnienienia przez komponent przypisanych mu zasad walidujących, komponent zaznaczany jest jako niepoprawny i wyświetlony w odpowiedni sposób podczas fazy tworzenia widoku. Jeżeli wszystkie z komponentów przeszły poprawnie przez fazę walidacji następuje faza związana z aktualizacją modelu. Następuje powiązanie nowych wartości z własnościami odpowiednich beanów wspomagających. Wiedząc iż faza walidacji przeszła poprawnie, możemy mieć pewność iż operujemy na poprawnych wartościach. W przedostatniej fazie związanej z obsługą żądania następuje wykonanie określonej akcji. Wykonanie opisywanej fazy wiąże się ściśle z wykonaniem logiki biznesowej systemu oraz zdefiniowaniu prezentowanego użytkownikowi widoku. Mapowania logicznych nazw widoków na zasoby szablonów definiowane są w pliku faces-config.xml. Ostatnią z opisywanych faz jest wygenerowanie odpowiedzi, czyli wyświetlenie widoku uwzględniającego aktualny stan komponentów Podsumowanie Celem obu zaprezentowanych rozwiązań jest przetworzenie żądania użytkownika i zwrócenie wyniku. Spring MVC w szablonowy sposób stosuje do obsługi żądania model oparty o wzorzec MVC z podziałem na widok, model i kontroler. Obsługa żądania jest wspierana przez obiekty pomocnicze wspierające obiekt nadzorujący w prawidłowym doborze kontrolera oraz mapowaniu logicznej nazwy widoku ja jego rzeczywistą postać. Dodatkowo możliwe jest użycie obiektów pełniących rolę konwerterów bądź walidatorów. W aplikacjach opartych o technologię JavaServer Faces, obsługa żądania jest ściśle powiązana z komponentami tworzącymi stronę aplikacji. W przypadku aplikacji opartych o model komponentowy żądanie często jest nazywane zdarzeniem, które inicjuje klient z użyciem wybranego komponentu. Poszczególne fazy obsługi zdarzenia są dobrze zdefiniowane i korzystają z wszystkich możliwości opisywanej biblioteki zaczynając od konwersji, walidacji a kończąc na wyświetleniu odpowiedzi Walidacja i konwersja typów Z zagadnieniami związanymi z walidacją i konwersją typu programista spotyka się najczęściej podczas pracy z formularzami. Poprawnie skonstruowana aplikacja nie pozwoli na zapisanie do modelu niepoprawnych bądź błędnych danych. Ponadto korzystając z biblioteki możnemy poinformować użytkownika o miejscu wystąpienia błędu a następnie umożliwić wprowadzenie poprawnych danych. Konwersja typów dotyczy zamiany danych modelu składowanych w obiektach języka Java na postać tekstową dostępną poprzez pola formularza oraz w drugą stronę, z obiektu do postaci tekstowej. 65

67 Spring MVC Zagadnienia związane z walidacją autorzy biblioteki Spring umieścili w warstwie logiki biznesowej. Konsekwencją dokonanego wyboru jest z formalnego punktu widzenia brak obiektów walidujących w warstwie widoku implementowanego przez Spring MVC. Do walidacji służą obiekty implementujące interfejs Validator, który wymaga implementacji metod supports oraz validate. Pierwsza z metod określa czy dany walidator nadaje się do walidacji obiektu podanego jako argument zwracając wartość logiczną. Druga metoda przeprowadza proces walidacji. Błędy związane z niepoprawną walidacją są zwracane w postaci obiektu Errors, który jest przekazywany jako jeden z parametrów. Podczas implementacji logiki walidacji przydatne może być skorzystanie z klasy pomocniczej zwanej ValidationUtils, która zawiera metody badające między innymi zawartość określonego pola względem wartości pustej. Informacje na temat popełnionych błędów podczas wypełniania formularza użytkownik dostaje poprzez wykorzystanie specjalnego znacznika <spring:bind /> wyświetlającego w sformatowany sposób zawartość obiektu Errors. Konwersja typów odbywa się z wykorzystaniem tzw. edytorów własności (ang. PropertyEditors). Rola edytorów polega na zamianie własności obiektów języka Java na ich reprezentację czytelną dla użytkownika. Jednym z przykładów takiej własności może być obiekt Date, który standardowo zawiera bardzo szczegółowe informacje, co może być nieprzydatne w momencie użycia go w polu przyjmującym wyłącznie datę. W celu użycia własnego edytora należy go wcześniej zarejestrować, czyli powiadomić system o sposobie konwersji określonej własności. Spring domyślnie dostarcza ponad dziesięć różnych edytorów pomocnych w przypadkach wymagających konwersji napisów do typów numerycznych takich jak Integer czy Float czy zamianie adresów URL na odpowiadające im obiekty JavaServer Faces W aplikacji opartej o JavaServer Faces proces walidacji i konwersji typów na swoje ścisłe miejsce w cyklu życia żądania. Proces walidacji odbywa się przez powiązanie wartości komponentu z beanem wspomagającym. Natomiast konwersja typów ma miejsce w drugiej fazie, przed czynnościami związanymi z walidacją. W przypadu komponentów posiadających ustawioną opcję natychmiastowego wychwycenia zdarzeń, walidacja oraz konwersja typów odbywa się wspólnie na wcześniejszym etapie pobrania stanu. Zadaniem konwersji typów jest zapewnienie iż podane dane są właściwego typu. W przypadku podania w polu wymagającym liczby zmiennoprzecinkowej, napisu nie będącego liczbą, obiekt dokonywujący konwersji powinien zgłosić błąd. Zadaniem walidacji natomiast jest sprawdzenie zasad biznesowych na obiekcie poprawnego typu. JavaServer Faces dostarcza szeregu domyślnych konwerterów począwszy od obiektów zajmujących się konwersją liczb i napisów po obiekty konwertujące daty. Możliwe jest również utworzenie własnych konwerterów poprzez implementację interfejsu Converter. Utworzenie własnych konwerterów jest potrzebne w momencie użycia w aplikacji obiektów specyficznych dla danego systemu, takich jak np. numer telefonu czy kod produktu. Obiekt konwertera musi implementować wspomniany interfejs, poprzez implementację dwóch metod zamieniających obiekt na napis i odwrotnie. Ponadto przed użyciem własnego konwertera jest wymagane zainstalowanie go w obiekcie FacesContext. 66

68 JavaServer Faces dostarcza czterech różnych form walidacji: dostępnych za pomocą standardowych komponentów, wbudowanych na poziomie aplikacji (ang. application-level validation), niestandardowych, stworzonych poprzez implementacje interfejsu Validator oraz metod walidujących znajdujących się w beanach wspomagających. Walidacja za pomocą standardowych komponentów odbywa się poprzez umieszczenie odpowiednich znaczników w kodzie strony szablonu. Walidatory standardowo dołączane do biblioteki JSF pozwalają na sprawdzenie poprawności podanego przedziału liczbowego czy długości napisu. Walidacja dostępna na poziomie aplikacji w rzeczywistości dotyczy walidacji zasad logiki biznesowej zawartej w kontrolerze aplikacji. Przykładem zastosowania opisywanego typu walidacji może być sprawdzenie zdolności kredytowej klienta, chcącego wybrać dodatkowe pieniądze. Jeżeli okaże się, iż klient nie posiada wystarczających środków, kontroler umieści stosowne informacje w kontekście aplikacji i przekieruje użytkownika do strony informującej o zaistniałej sytuacji. JavaServer Faces umożliwia tworzenie niestandardowych walidatorów, które można wykorzystać w zawartości szablonu. Przykładowe walidatory tego typu mogą walidować poprawność numeru telefonu, adresu czy kodu pocztowego. Po zarejestrowaniu zostaną udostępnione poprzez znacznik <f:validator />. Ostatni sposób walidacji polega na wykorzystaniu metody beana wspomagającego, którego sygnatura jest zgodna z metodą validate interfejsu Validator Podsumowanie Walidacja oraz konwersja typów stanowią ważny aspekt aplikacji internetowej pobierającej bądź wyświetlającej własności obiektów domeny. Obiekty walidujące dbają o poprawność składniową podawanych przez użytkownika danych. Obiekty konwertujące zapewniają zamianę obiektów języka Java na postać napisu oraz konwertują z powrotem pola formularza na obiekty. Spring MVC stosuje czysto obiektowe podejście do opisywanego zagadnienia. Wprowadza pojęcia interfejsów odpowiedzialnych za walidację oraz obiekty edytorów własności, które są rozszerzeniem standardowych obiektów konwertujących, mogących mieć zastosowanie w różnych warstwach aplikacji opartej o Spring Framework. Rozwiązanie oferowane przez JavaServer Faces spełnia swoje zadanie, oferuje odpowiednie interfejsy dla walidatorów i konwerterów oraz uwzględnia ich zastosowanie w procesie obsługi żądania. Oba omawiane zagadnienia pozwalają na definiowanie własnych obiektów oraz dostarczają własnych podstawowych obiektów walidujących i konwertujących. Informacje o zaistniałych błędach są wyświetlane w sposób czytelny, możliwy do modyfikacji Internacjonalizacja Celem internacjonalizacji aplikacji webowej [43] jest zlikwidowanie barier związanych z lokalizacją produktu. Obie biblioteki posiadają mechanizmy wspomagające ten proces Spring MVC Najważniejszymi komponentami służącymi do lokalizacji aplikacji tworzonej z użyciem Spring MVC są następujące komponenty o następujących nazwach: MessageSource, LocaleResolver, LocaleContextHolder oraz LocalChangeInterceptor. 67

69 Pierwszy z wymienionych komponentów służy do lokalizacji statycznych elementów stron. Jest częścią kontekstu nazywanego ApplicationContext. Wspomniany komponent dostarcza trzech przeładowanych metod getmessage, służących do wczytania napisów w zależności od danych użytkownika. Domyślnie Spring dostarcza dwóch implementacji komponentu MessageSource. Jedna z nich umożliwia programową obsługę wiadomości lokalizacyjnych. Druga znacznie częściej używana, składa się z serii plików properties, zawierających zlokalizowane wiadomości podzielone według ustawień regionalnych (ang. locale) [55]. Za pomocą wspomnianego komponentu możliwe jest określenie przedrostka plików zawierającego wiadomości. W przypadku podania przykładowej nazwy exceptions, wiadomości będą szukane w plikach posiadających nazwy zbliżone do podanych: exceptions_en_gb.properties bądź exceptions_pl_pl.properties, w zależności od ustawień przeglądarki użytkownika. Opisywany komponent służy również do lokalizacji komunikatów o błędach. Komponent LocaleResolver ma za zadanie rozpoznać ustawienia regionalne użytkownika aplikacji. Dostępne dwie wersje korzystają z atrybutu accept-language nagłówka żądania HTTP, zawartości ciasteczka lub atrybutu sesji. Deklaracja opisywanego komponentu sprowadza się do dokonania wpisu w pliku konfiguracyjnym. Pozostałe komponenty służą do składowania elementów lokalizacyjnych w sposób możliwy do uzyskania z dowolnego miejsca aplikacji JavaServer Faces Lokalizacja w aplikacjach opartych o JavaServer Faces opiera się o pliki wiadomości lokalizacyjnych [20] pobieranych z wnętrza aplikacji za pomocą odpowiednich kluczy. Format plików zawierających wiadomości lokalizacyjne jest formatem plików properties. Nazwa plików definiowana jest poprzez znacznik <message-bundle> umieszczony w pliku konfiguracyjnym JavaServer Faces. Poszczególne pliki wiadomości lokalizacyjnych posiadają przyrostek składający się z podkreślenia oraz nazwy ustawień regionalnych z rozszerzeniem properties. Przykładowy plik zawierający wiadomości w języku polskim może nosić nazwę komunikaty_pl.properties. W plikach stron JSP, programista chcący wyświetlić określony komunikat korzysta z odpowiedniego klucza, który posiada swój odpowiednik w pliku properties Podsumowanie Oba opisane powyżej rozwiązania opierają się na takich samych rozwiązaniach. Wykorzystują serię plików stosujących format properties, składających się z par klucz wartość. Obiekt przetwarzający plik szablonu w momencie natrafienia na odwołanie do klucza, korzysta z informacji przekazywanych w nagłówku żądania i szuka wiadomości lokalizacyjnej w pliku properties noszącym nazwę odwołującą się do pobranych ustawień regionalnych. 68

70 5. Aplikacja Peclinic Poniższy rozdział opisuje aplikację Petclinic zaimplementowaną w celu empirycznego porównania wybranych szkieletów programistycznych. Pierwsza z części zawiera ogólny opis i przeznaczenie aplikacji w kontekście przeprowadzanych eksperymentów. Następny rozdział opisuje poszczególne moduły składowe aplikacji. Ostatnia część rozdziału przedstawia zaimplementowaną funkcjonalność Opis aplikacji Aplikacja Petclinic została wzorowana na aplikacji dostarczanej standardowo ze szkieletem Spring Framework jako demonstracja jego możliwości [59]. Prezentowany system został napisany od podstaw wraz z wprowadzeniem dodatkowych elementów, które miały za zadanie zwiększenie stopnia jego złożoności. Kod źródłowy aplikacji umieszczono na połączonym do pracy nośniku. Elementami aplikacji Petclinic, które różnią ją od oryginału dostarczanego wraz ze Spring Framework są: dodanie encji lekarstwo, przepisane lekarstwo oraz grupa lekarstwa, dodanie i uzupełnienie funkcjonalności obsługującej dotychczasowe, i nowo dodane do aplikacji encje. Prezentowana aplikacja służy do wspomagania pracy niewielkiej przychodni weterynaryjnej. Jej funkcjonalność jednak nie jest pełna i system nie nadaje się do zastosowania w warunkach rzeczywistych. Zasadniczym celem systemu jest praktyczne zaprezentowanie działania mechanizmów dostarczanych przez badane szkielety programistyczne oraz umożliwienie porównania ich w sytuacji możliwie zbliżonej do rzeczywistej. System Petclinic składa się z szeregu stron na których użytkownik może zarządzać pracą kliniki. Wyróżniono trzy główne działy, które operują na obiektach klientów, weterynarzy i wizyt. Każdy z działów zawiera stronicowaną listę obiektów. Rysunki 5.1 oraz 5.2 przedstawiają listę klientów w aplikacji zaimplementowane odpowiednio za pomocą Spring MVC oraz JavaServer Faces. Rysunek 5.1: Lista planowanowanych wizyt w aplikacji Spring MVC 69

71 Rysunek 5.2: Lista klientów kliniki w aplikacji JavaServer Faces Podczas implementacji aplikacji skupiono się na rozwiązaniu najczęstszych problemów jakie napotyka programista podczas budowy aplikacji internetowej. Wspomniane problemy obejmują następujące elementy: stworzenie nawigacji pomiędzy stronami, walidacja wprowadzanych danych i ich konwersję na obiekty języka Java, lokalizacja aplikacji. We wszystkich wymienionych elementach programista otrzymuje wsparcie ze strony szkieletu programistycznego. Zaimplementowana aplikacja stara się zatem wprowadzić możliwie dużo sytuacji, w których wsparcie ramy projektowej okazuje się pożądane, jednocześnie ograniczając ich nadmiar w celu zachowania możliwej do utrzymania prostoty. Wprowadzona miejscami nadmiarowość polegająca na powielaniu elementów systemu pod kątem wykorzystania wsparcia funkcjonalności ramy projektowej, np. możliwość edycji więcej niż jednej encji, została wprowadzona w celu zwiększenia realizmu aplikacji oraz zbudowania wystarczającej podstawy dla testów wydajnościowych Wykorzystane technologie Podczas implementacji aplikacji zostały wykorzystane narzędzia i technologie opisane w rozdziale 2. W niniejszej części wyjaśniono sposób wykorzystania niektórych z nich w projekcie Petclinic. Cały kod projektu był składowany w repozytorium Subversion. Sytuacja taka pozwalała na wersjonowanie dokonywanych zmian oraz łatwe ich przenoszenie pomiędzy gałęziami kodu aplikacji stworzonymi do przeglądania i zarządzania obiektami kliniki. Dodatkową zaletą była łatwa możliwość udostępnienia zainteresowanym ciągłego wglądu do kodu. Przy zarządzaniu kodu użyto systemu Maven, który okazał się pomocny podczas rozwoju aplikacji. Został użyty bezpośrednio również podczas generowania raportów dotyczących metryk kodu. Hibernate został użyty do stworzenia mapowania pomiędzy obiektami domeny a tablicami relacyjnej bazy danych. W projekcie najpierw utworzono obiekty języka Java, następnie opatrzono je odpowiednimi adnotacjami. Pozwoliło to w rezultacie na wygenerowanie odpowiedniego schematu bazy danych, pozwalającego na utrwalenie obiektów domeny należących aplikacji. Podczas implementacji aplikacji skorzystano z bazy danych HSQLDB 8 do składowania stanu aplikacji. Do jej największych zalet należy niewielki rozmiar oraz szybkość startu, co znacząco wpływa na komfort wykonywania testów, w których jest wymagany wielokrotny start silnika bazy danych. W procesie implementacji uniknięto częstych 70

72 startów serwera bazodanowego poprzez wykorzystanie wspomnianej w rozdziale 2 klasy AbstractDependencyInjectionSpringContextTests z pakietu Spring Mock. Szkielet Spring Framework posłużył do złączenia poszczególnych warstw aplikacji. Znacznie uprościł użycie Hibernate a w aplikacji. Poprzez zastosowanie wzorca wstrzykiwania zależności uzyskano rozluźnienie połączeń pomiędzy poszczególnymi komponentami aplikacji. Poprzez użycie programowania aspektowego (ang. aspect-oriented programming) wprowadzono w wymagane miejsca aplikacji transakcyjność. Biblioteka EasyMock została wykorzystana przy testowaniu jednostkowym wybranych obiektów warstwy biznesowej. Do końcowych testów akceptacyjnych posłużyła biblioteka Selenium, którą wykorzystano do testowania poprawności zaimplementowania interfejsu użytkownika Encje bazy danych Aplikacja Petclinic służy do zarządzania niewielką przychodnią weterynaryjną. Poniższa część opisuje wykorzystane encje oraz ich powiązania między sobą. Prezentowany sposób implementacji rozszerzył zbiór oryginalnej aplikacji Petclinic o encje związane z lekarstwami, które lekarz weterynarii może przypisać pacjentowi. Poniżej umieszczono spis tabel używanych w bazie danych, które posłużyły do implementacji aplikacji: Medicines przechowuje informacje na temat leków dostępnych do przepisania w klinice. Zawiera informacje na temat nazwy leku oraz przynależności do jednej z grupy lekarstw. Medicines_groups wykorzystano do składowania nazw grup lekarstw. Owners utożsamia właścicieli leczonych zwierząt. Zawiera informacje na temat ich danych osobowych: imię, nazwisko, adres (ulica, miasto), numer telefonu, . Pets reprezentuje zwierzęta leczone w przychodni. Gromadzi dane odnośnie ich nazwy, daty urodzin. Posiada odniesienia do klucza głównego właściciela oraz typu zwierzęcia (encja pet_types). Prescribed_medicines składuje informacje na temat przypisanych lekarstw. Posiada odniesienia do lekarstwa, oraz informacje na temat dawki oraz wizyty, w czasie której przepisano lekarstwo. Vets przechowuje informacje na temat lekarzy leczących w klinice oraz ich danych osobowych. Vets_specialties przechowuje połączenie pomiędzy weterynarzami a ich specjalizacjami, wprowadzona w wyniku relacji n:m łączy obie wspomniane encje. Visits wykorzystano do składowania informacji odnośnie planowanych bądź odbywających się wizyt. Zawiera informacje odnośnie nazwy wizyty, jej daty oraz opis. Ponadto posiada odniesienia do zwierzęcia, które było leczone podczas wizyty oraz weterynarza leczącego wspomniane zwierzę. Powiązania pomiędzy tabelami bazy danych zawiera rysunek 5.3. Zdecydowana większość relacji jest typu 1:n, jedynie relacja specjalizacji z weterynarzami, które je posiadają jest typu n:m. 71

73 Rysunek 5.3: Tabele bazodanowe aplikacji Petclinic 5.2. Moduły aplikacji Każda z dwóch implementacji aplikacji Peclinic składa się z trzech wydzielonych modułów o jasno sprecyzowanych zadaniach. Opisywane jednostki są odpowiednikami części systemu zarządzanego przez Mavena. Dwa moduły implementujące warstwę dostępu do danych oraz logikę biznesową stanowią podstawę i są wspólne dla obu implementacji. Jedyna różnica występuje w warstwie najwyższej, implementującej interfejs użytkownika. W tych warstwach zostały wykorzystane rozdzielnie oba badane szkielety programistyczne, dając w rezultacie dwie osobne aplikacje Petclinic-data Moduł noszący nazwę petclinic-data jest warstwą dostępu do danych. Zawiera obiekty domeny na których operuje aplikacja takie jak owner, vet czy visit. Ponadto udostępnia dostęp do obiektów DAO (ang. Data Access Object), które oferują możliwość zarządzania obiektami domeny niezależnie od wykorzystywanego mechanizmu składowania danych. Obiekty domeny są to zwykłe obiekty języka Java, które zostały wzbogacone o odpowiednie adnotacje umożliwiające mapowanie ich na odpowiadające im tabele bazy danych. Przykład obiektu domeny utożsamianego ze zwierzęciem został przedstawiony na rysunku 2.5. Przedstawia on klasę Pet oraz jej relację względem właściciela. Warstwa obiektów DAO została zbudowana na typach generycznych, podstawowym interfejsem jest GenericDao, który udostępnia operacje zapisywania, usuwania oraz pobierania obiektów domeny. Jego specjalizacje w postaci interfejsów GenericNamedDao oraz GenericPersonDao służą do obsługi obiektów posiadających tylko nazwę czyli np. Pet czy Medicine bądź osób jak w przypadku obiektów Owner. Obiekty DAO zostały zaimplementowane wyłącznie dla głównych encji aplikacji, operacje na pozostałych encjach wykonywane są za ich pomocą Petclinic-core Opisywany moduł zawiera logikę biznesową aplikacji zaimplementowaną w postaci usług. Ta część aplikacji pełni funkcję abstrakcji dla wykonywanych w aplikacji zadań, podobnie jak warstwa DAO w przypadku operacji związanych z utrwaleniem obiektów. 72

74 Rysunek 5.4: Lista planowanowanych wizyt w aplikacji Spring MVC Rysunek 5.5: Lista planowanowanych wizyt w aplikacji JavaServer Faces Cechą charaktertyczą opisywanego modułu jest bezpośrednie użycie niższej warstwy zaimplementowanej w postaci modułu petclinic-data. Operacje biznesowe wymagają często podczas realizacji dostępu do wielu obiektów DAO, poszczególne metody biznesowe dają taką możliwość przy pojedynczym ich wywołaniu. Podobnie jak poprzednia warstwa korzysta z klas generycznych dla zwiększenia elastyczności oraz zmniejszenia powtórzeń w kodzie Petclinic-web Najwyższa warstwa zaimplementowana w postaci modułów petclinic-springmvc-web oraz petclinic-jsf-web implementuje interfejs użytkownika. Implementacja w postaci dwóch modułów wynika z użycia dwóch szkieletów programistycznych odpowiednio Spring MVC oraz JavaServer Faces. Eksperymenty opisane w kolejnym rozdziale bazują na najwyższej warstwie osobno dla każdej z aplikacji. Zadaniem opisywanej warstwy jest implementacja interfejsu użytkownika. Do podstawowych elementów należą: klasy edytorów i konwerterów mających za zadanie zamiany reprezentacji tekstowej na obiekty domeny, klasy operujące na formularzach i przetwarzające wprowadzane przez użytkownika dane, walidatory dbające o poprawność wprowadzanych danych. Do zadań prezentowanego modułu należą również zapewnienie nawigacji między stronami aplikacji oraz mapowania nadchodzących żądań do kontrolerów Zaimplementowana funkcjonalność Funkcjonalność aplikacji Petclinic została zaimplementowana osobno w dwóch wersjach aplikacji wykorzystującej różne szkielety programistyczne, Spring MVC oraz Java- Server Faces. 73

75 Rysunek 5.6: Walidacja formularza dodawania klienta w aplikacji Spring MVC Rysunek 5.7: Walidacja formularza dodawania klienta w aplikacji JavaServer Faces Poniższy wykaz funkcjonalności zawiera podział wprowadzony na etapie przeprowadzania eksperymentów z podziałem na przeglądanie obiektami aplikacji, zarządzanie nimi oraz lokalizację. W pierwszym etapie zaimplementowano możliwość przeglądania danych, do tego celu użyto między innymi stronicowanych list. Aplikacja umożliwia przeglądanie: Informacji o trzech najbliższych wizytach (tabela umieszczona na stronie głównej). Rysunki 5.4 oraz 5.5 przedstawiają odpowiednio listy stworzone w aplikacji opartej o Spring MVC oraz JavaServer Faces. Wyszukiwanie klientów po fragmencie nazwiska. Wyświetlanie klientów wraz z ich szczegółami dotyczącymi posiadanych zwierząt oraz ich wizyt. Wyświetlanie historii wszystkich wizyt kliniki wraz z ich szczegółami. Wyświetlanie listy weterynarzy pracujących w klinice wraz z ich szczegółami. Wspomniane szczegóły najczęściej dotyczą atrybutów obiektów takich jak nazwa czy imię i nazwisko w przypadku osób. Funkcjonalność zaimplementowana w drugim etapie pozwala na zarządzanie obiektami aplikacji, w szczególności umożliwia dodawanie, usuwanie i modyfikację klientów, zwierząt oraz wizyt. Walidację formularza służącego do dodawania klienta przedstawiają rysunki 5.6 oraz 5.7. W trzeciej fazie skupiono się na zlokalizowaniu aplikacji w dwóch językach polskim i angielskim. Lokalizacji zostały poddane: 74

76 komunikaty niepowodzenia walidacji danych formularza, treść stron. Ponadto dodano możliwość przełączania się między wersjami stron we wspomnianych wersjach językowych. 75

77 6. Eksperymenty z wykorzystaniem aplikacji Petclinic Poniższy rozdział przedstawia sposób przeprowadzenia oraz wyniki analizy eksperymentów [64, 11] dokonanych na aplikacji wspomagającej pracę przychodni weterynaryjnej o nazwie Petclinic. Pierwsza z części opisuje proces w jaki zgromadzono i przetworzono dane uzyskane w wyniku eksperymentów. Druga część rozdziału skupia się na opisie i analizie danych uzyskanych w wyniku przeprowadzonych eksperymentów Przebieg badania Zadaniem prezentowanego podrozdziału jest opis przebiegu implementacji aplikacji Petclinic oraz przedstawienie sposobu przeprowadzenia eksperymentów Fazy implementacji aplikacji Petclinic Implementacja przykładowej aplikacji została podzielona na trzy odrębne fazy. Aplikacja powstała w wyniku każdej z nich posiada ściśle określoną funkcjonalność. Po zakończeniu implementacji modułów petclinic-data oraz petclinic-core zawierających odpowiednio kod związany z dostępem do danych oraz logiką biznesową (szczegóły zawarte zostały w rozdziale 5.2) zaczęła się właściwa faza polegająca na implementacji modułów odpowiedzialnych za warstwę internetową aplikacji. Implementacja ostatniej z faz projektu została podzielona na trzy etapy związane z rozwojem każdej z dwóch wersji aplikacji Petclinic, opartej o framework Spring MVC oraz JavaServer Faces. Poszczególne etapy pracy wraz z zawartą w nich funkcjonalnością zostały opisane w rozdziale 5.3. Czas potrzebny na implementację każdego etapu obu wersji aplikacji okazał się zbliżony do siebie. Jednocześnie znaczna większość czasu została poświęcona na naukę i poszukiwanie rozwiązań problemów specyficznych dla danego frameworka. W rezultacie trudno było wyodrębnić czas poświęcony na rzeczywistą implementację aplikacji. Powyższa sytuacja spowodowała, iż w końcowej analizie czas implementacji nie został uwzględniony. Autor implementując aplikację dążył do osiągnięcia takiego samego poziomu końcowej funkcjonalności w obu systemach. Podczas pracy po zakończeniu pierwszej i drugiej fazy tworzono nową gałąź w repozytorium kodu, w ktorej umieszczano dotychczasowo napisany kod. W rezultacie aplikacja powstająca w każdym z etapów zawierała kod już istniejący oraz dodawała swój własny związany z zarządzaniem obiektów bądź lokalizacją. Końcowym efektem prac nad aplikacją Petclinic było powstanie czterech modułów: dostępu do danych, petclinic-data, logiki biznesowej, petclinic-core, warstwy aplikacji internetowej opartej o Spring MVC petclinic-springmvc-web, 76

78 Rysunek 6.1: Drzewo komponentów aplikacji JMeter warstwy aplikacji internetowej z wykorzystaniem JavaServer Faces petclinic-jsf-web. Każdy z dwóch ostatnich modułów posiada implementację bazującą na opisanych wcześniej trzech etapach budowy Badanie wydajności Wydajność stworzonych aplikacji zostanie zmierzona poprzez użycie narzędzia symulującego jednoczesną pracę wielu użytkowników. Do przeprowadzenia testów został wybrany JMeter [6], projekt fundacji Apache Software Foundation. Aplikacja pozwala na przeprowadzenie testów funkcjonalnych jak i wytrzymałościowych. Działa na zasadzie symulacji pracy określonych grup użytkowników. JMeter oprócz protokołu HTTP potrafi również badać aplikacje wykorzystujące FTP czy LDAP. Rysunek 6.1 przedstawia drzewo komponentów stworzone w celu testowania wydajności aplikacji podczas dodawania klientów. Komponent Add owner jest odpowiedzialny za wysyłanie określonej liczby żądań z wykorzystaniem elementów podrzędnych. Element próbkujący wysyła odpowiednie żądanie metodą POST dodając tym samym nowych klientów do bazy. Komponenty oznaczone przedrostkiem [CSV] odpowiadają za dostarczenie danych dodawanych klientów. Pozostałe gromadzą dane dane uzyskane z pomiarów. Plan pomiaru W celu przeprowadzenia eksperymentów wydajnościowych zostały przeprowadzone trzy grupy testów różniące się charakterystyką osób biorących w nich udział. Pierwszą grupę stanowiły osoby przeprowadzające wyłącznie operację odczytu danych, czyli nie podejmujących żądanych akcji mogących mieć wpływ na stan wewnętrzny aplikacji. W skład drugiej grupy testowej wchodziły wyłącznie osoby, które przeprowadzają operację mające odzwierciedlenie w stanie wewnętrznym aplikacji. Do operacji tego typu można zaliczyć operacje dodawania użytkowników, modyfikacji ich danych osobowych czy ciągu operacji związanych z obsługą wizyty użytkownika. Grupa użytkowników składającą się na trzeci eksperyment zawierała zarówno użytkowników z pierwszego testu jak i drugiego. Trzeci test miał za zadanie odzwierciedlenie rzeczywistej pracy użytkowników aplikacji. Większość z nich będzie przeprowadzać wyłącznie operację przeglądania i wyszukiwania danych, mniejszość operację modyfikujące stan aplikacji. 77

79 Sposób przeprowadzenia pomiaru Użyte narzędzie JMeter pozwala na zdefiniowanie żądanej w testach liczby użytkowników oraz całkowitego czasu potrzebnego na ich wystartowanie. W przypadku testów zastosowano serwer pośredniczący, który posłużył do nagrania planowanych żądań działań użytkowników. Podczas testów zostały wykorzystane dwa komputery połączone w ramach sieci lokalnej. Jeden z komputerów zawierał testowaną aplikację i przetwarzał żądania użytkowników. Druga maszyna zawierająca instancję JMetera była odpowiedzialna za wysyłanie strumienia żądań i gromadzenie wyników. Eksperymenty przeprowadzono w trzech opisanych seriach. Liczba jednocześnie pracujących osób została dobrana z uwzględnieniem charakterystyk połączenia sieciowego oraz mocy obliczeniowej komputerów biorących udział w teście. Ze względu na brak rzeczywistych danych odnośnie proporcji grup użytkowników, w teście trzecim została wybrana proporcja 4/1, użytkowników grupy pierwszej do użytkowników grupy drugiej. Dla każdej z badanej grupy zostały zmierzone dwie wartości: maksymalna liczba użytkowników mogących korzystać z systemu, przy zapewnieniu jego stabilnej pracy. maksymalna liczba użytkowników mogących jednocześnie korzystać z aplikacji przy zapewnieniu stabilnej pracy systemu (próg czasu reakcji), Stabilna praca systemu jest rozumiana jako praca bez błędów ze strony serwera. Podczas testów wydajnościowych najczęściej spotykana błędy związane są z przekroczeniem czasu połączenia Pomiar metryk kodu Metryki kodu [14, 13] są podstawowym miernikiem jego jakości. Podczas pomiaru jakości kodu projektu zostaną wykorzystane elementy raportujące narzędzia Maven JDepend [35] oraz wtyczki platformy Eclipse o nazwie Metrics [41]. Plan pomiaru Plan testów kodu projektu obejmuje zarówno kod języka Java modułu warstwy prezentacji projektu jak i kod szablonów. W celu uzyskania miarodajnego wyniku kody źródłowe obu aplikacji przed pomiarem został zweryfikowane przez aplikację PMD [45]. Rodzaje metryk zostały podzielone na dwa rodzaje: metryki proste, metryki złożone. Podczas badania jakości kodu zostały wykorzystane następujące metryki zaliczone do grupy metryk prostych: Liczba dzieci (ang. number of children) (NSC) czyli, całkowita liczba bezpośrednich dzieci (podklas) danej klasy. Klasy implementujące określony interfejs również zaliczane są do bezpośrednich jego dzieci. Głębokość drzewa dziedziczenia (ang. depth of inheritance tree) (DIT), czyli odległość (liczba rodziców) od klasy bazowej języka Java (klasy Object). Liczba przeciążonych metod (ang. number of overridden methods) (NORM), czyli całkowita liczba metod, posiadających określoną widoczność, które przeciążają odziedziczone metody przodków. Liczba metod (ang. number of methods) (NOM), czyli całkowita liczba metod klasy. Liczba pól (ang. number of attributes) (NOF), czyli całkowita liczba pól klasy. Liczba linii kodu (ang. lines of code), w tym: 78

80 TLOC, całkowita liczba niepustych linii kodu nie będących komentarzami na jednostkę kompilacji, MLOC, całkowita liczba niepustych linii kodu nie będących komentarzami wewnątrz ciała metod. Liczba klas (ang. number of classes) (NOC), czyli całkowita liczba konkretnych i abstrakcyjnych klas danego pakietu; miara wyznaczająca rozszerzalność danego pakietu. Liczba interfejsów (ang. number of interfaces) (NOI), czyli całkowita liczba interfejsów danego pakietu. Liczba pakietów (ang. number of packages)(nop). W grupie metryk złożonych uwzględniono następujące metryki wchodzące do oceny kodu aplikacji: Indeks specjalizacji (ang. specialization index) (SIX), czyli miara definiowana jako wynik NORM * DIT / NOM. Działa na poziomie klas, charakteryzuje miarę specjalizacji danej klasy. Skojarzenia dośrodkowe (ang. Afferent Couplings) (CA), czyli liczba innych pakietów, których klasy korzystają z klas danego pakietu. Im większa, tym większa odpowiedzialność pakietu. Skojarzenia odśrodkowe (ang. efferent couplings) (CE), czyli liczba innych pakietów, których klasy wykorzystywane są przez klasy danego pakietu. Im większa, tym większa zależność pakietu. Abstrakcyjność (ang. abstractness) (RMA), czyli stosunek liczby klas abstrakcyjnych do pozostałych w pakiecie. Metryka przyjmuje wartości od 0 do 1. A=0 oznacza pakiet całkowicie ukonkretniony, A=1 oznacza pakiet całkowicie abstrakcyjny. Niestabilność (ang. instability) (RMI), czyli stosunek skojarzeń odśrodkowych do wszystkich skojarzeń wyrażona równaniem I = CE / (CE + CA). Wskaźnik przyjmuje wartości od 0 do 1. I=0 oznacza pakiet całkowicie stabilny, I=1 oznacza pakiet całkowicie niestabilny. Znormalizowana odległość kategorii od ideału (ang. distance from the main sequence) (RMD), czyli odległość od prostej wyznaczonej przez równanie RMA + RMI = 1. Metryka jest wskaźnikiem wyważenia pakietu pomiędzy abstrakcyjnością i stabilnością. Pakiet którego wartość metryki znajduje się na linii ideału uznaje się za optymalnie zrównoważony względem abstrakcyjności i stabilności. Idealnie zrównoważony pakiet jest albo całkowicie abstrakcyjny i stabilny (x=0, y=1) albo całkowicie konkretny i niestabilny (x=1, y=0). Wskaźnik przyjmuje wartości z zakresu od 0 do 1. RMD=0 wskazuje na pakiet idealny, RMD=1 wskazuje na pakiet maksymalnie oddalony od ideału. W przypadku kodu szablonów zmierzono liczbę znaczników dynamicznej treści potrzebnych do zaimplementowania zadania związanego ze stworzeniem listy stronicowanej, widoku ze szczegółami obiektu, formularza modyfikacji obiektu, formularza dodawania wizyty czy prostej listy prezentującej najbliższe spotkania. Sposób przeprowadzenia pomiaru Pomiar metryk kodu został przeprowadzony z wykorzystaniem narzędzi o ogólnodostępnym kodzie źródłowym, wtyczki raportującej projektu Maven o nazwie JDepend oraz wtyczki środowiska Eclipse o nazwie Metrics. Proces pomiaru dotyczył głównie warstwy klienta, dla porównania zmierzono jednak również pozostałe warstwy: dostępu do danych i logiki bizesowej. 79

81 Zmierzone metryki kodu zawierają informacje odnośnie trzech etapów budowy warstwy klienta dla aplikacji Petclinic: umożliwiającym przegląd danych, umożliwiającym manipulację zarządzanymi danymi, posiadającym lokalizację dla języka polskiego i angielskiego. Ostatnim z elementów związanym z pomiarem metryk kodu było przedstawienie wpływu rozwoju projektu na ich zmiany Badanie łatwości wprowadzania zmian Model jakościowy zdefiniowany przez standard ISO/IEC :2001 [31] definiuje sześć charakterystyk, które mają za zadanie opisać wymagania pozafunkcjonalne systemu. Do wymienionych w standardzie charakterystyk zaliczają się: funkcjonalność, niezawodność, użyteczność, wydajność, łatwość konserwacji oraz przenośność. Łatwość konserwacji stanowi zbiór atrybutów opisujących nakład pracy niezbędny w celu wprowadzenia zmian w oprogramowaniu. Każda z charakterystyk składa się z szeregu tzw. atrybutów. Jeden z nich porusza kwestię łatwości wprowadzania zmian (ang. changeability). Łatwość wprowadzania zmian została zdefiniowana jako nakład pracy konieczny do implementacji nowej funkcjonalności, usunięcia istniejącego błędu bądź dostosowania aplikacji do nowych warunków zewnętrznych. Plan pomiaru Atrybut łatwości wprowadzania zmian w systemie został zmierzony poprzez obserwację zmian dokonywanych w projekcie podczas jego modyfikacji, w poszczególnych jego etapach wyróżnionych w rozdziale 5.3. Pierwszą z czynności poddanych ocenie łatwości wprowadzania zmian było stworzenie widoku listy obiektów, w postaci stronicowanej tabeli. Drugi badany przypadek dotyczył zbudowania formularza mającego za zadanie dodanie nowego obiektu do aplikacji. Ostatnie zadanie polegało na lokalizacji komunikatów i treści aplikacji. Sposób przeprowadzenia pomiaru Pomiar opisywanego atrybutu będzie zmierzony poprzez zliczenie liczby plików projektu, które w wyniku przeprowadzanego działania zostały dodane, zmodyfikowane bądź uzupełnione. Różnica między modyfikacją a uzupełnieniem polega na tym, iż podczas wprowadzania modyfikacji dotychczasowa treść pliku ulega częściowej lub całkowitej zmianie. Uzupełnienie polega natomiast wyłącznie na dodaniu nowej zawartości bez modyfikacji treści wcześniej istniejących. Do pomiaru łatwości wprowadzania zmian bazujących na etapie przeglądania danych wybrano tabelę stronicową służącą do prezentacji historii wizyt. Omawiana tabela składa się z sześciu kolumn opisujących dzień, godzinę, imię i nazwisko właściciela, nazwę zwierzęcia, nazwę wizyty oraz dodatkowej kolumny zawierającej spis operacji, możliwej do wykonania na każdej z wizyt takich jak pokazanie szczegółów, zmienienie danych czy usunięcie wizyty. Podczas tego etapu zostanie zmierzona praca włożona w: stworzenie odpowiednich mapowań pomiędzy adresami URL żądania a kontrolerami, stworzenie szablonu strony, modyfikacji plików konfiguracyjnych aplikacji. W drugim etapie została oceniona praca polegająca na stworzeniu formularza umożliwiającego dodanie nowego klienta, wraz z walidacją wprowadzanych danych. 80

82 Pomiar trzeciego etapu dokonano przy zadaniu polegającym na lokalizacji treści komunikatów o błędach oraz dodaniu możliwości przełączania się między wersjami językowymi aplikacji Badanie dostępności komponentów Triniad Dostępność jest nauką oraz zbiorem standardów definiujących wytyczne w zakresie tworzenia stron WWW w celu zwiększenia ich dostępności dla jak najszerszej grupy użytkowników, w tym również użytkowników niedosłyszących czy niedowidzących. Mianem WAI (ang. Web Accessibility Initiative) [61] określa się inicjatywę W3C [62], tworzącą między innymi zbiór standardów dotyczących dostępności dla aplikacji internetowych. W swoich wytycznych WAI odnosi się między innymi do spraw związanych z: formą prezentowania zawartości stron internetowych, aplikacjami służącymi do tworzenia stron internetowych, przeglądarkami internetowymi, aplikacjami internetowymi. Ze względu na charakter aplikacji w dalszej części opisu zostaną uwzględnione wytyczne związane z formą prezentacji. Badaniu dostępności została poddana aplikacja zaimplementowana z wykorzystaniem frameworka JavaServer Faces, gdyż wykorzystanie tej technologii powoduje, iż wiele elementów interfejsu jest tworzonych automatycznie bez możliwości ingerencji programisty. W przypadku wykorzystania Spring MVC, programista sam musi zadbać o zgodność aplikacji z wytycznymi dostępności. Automatyczne generowanie zawartości strony, na podstawie szablonu z wykorzystaniem JavaServer Faces wpływa na zmniejszoną kontrolą nad zawartości strony. Celem pomiaru badającego dostępność komponentów aplikacji opartej o JavaServer Faces było wykazanie poprawności automatycznie generowanych komponentów pod względem ich dostępności. Pomiar dostępności dotyczył wyłącznie elementów generowanych automatycznie przez badany szkielet. Plan i sposób przeprowadzenia pomiaru Podczas testów zostały zmierzone kwestie opisane w dokumencie Web Content Accessibility Guidelines [16], wersja 1.0, związane w szczególności z: poprawnością kodu strony, poprawnością w kontekście pracy w środowisku różnych przeglądarek internetowych. Wymienione elementy mieszczą się w części specyfikacji określonej mianem Core Techniques for WCAG 1.0 [15]. Poprawność walidacji kodu strony, która jest przetwarzana przez przeglądarkę użytkownika zostanie zmierzona względem deklaracji poprawności autorów komponentów, czyli specyfikacją HTML 4.01 Transitional [46]. W końcowym wyniku zostanie uwzględniona liczba ostrzeżeń oraz błędów zgłaszanych przez walidator. Poprawność działania komponentów zweryfikowano manualnie z użyciem przeglądarek Internet Explorer 6, Firefox 2 oraz Opera 9. Podczas badania możliwe było uzyskanie jednej z trzech wartości, przyporządkowanych w następujący sposób: 0, komponent nie jest wyświetlany poprawnie przez co uniemożliwia prawidłową pracę, 1, renderowanie komponentu nie przebiega prawidłowo jednak jest możliwe uzyskanie zamierzonego rezultatu, 2, komponent działa w pełni poprawnie. 81

83 Tabela 6.1: Komponenty Triniad poddane badaniu dostępności breadcrumbs chart choosecolor choosedate commandbutton commandlink commandnavigationitem gobutton golink inputcolor inputdata inputfile table inputlistofvalues inputnumberspinbox inputtext legend messages navigationpane navigationtree outputformatted outputlabel outputtext selectbooleancheckbox selectbooleanradio selectmanycheckbox selectmanylistbox selectmanyshuttle selectonechoice selectonelistbox selectoneradio selectordershuttle selectrangechoicebar showdetail showmanyaccordion showoneaccordion singlestepbuttonbar treetable Badaniu zostały poddane wyłącznie komponenty wizualne wymienione w tabeli 6.1. Stanowią one 55% wszystkich dostępnych komponentów. Reszta to elementy niewizualne grupujące elementy bądź formujące stronę w inny sposób Analiza wyników Niniejsza część przedstawia analizę wyników uzyskanych w wyniku przeprowadzonych eksperymentów z wykorzystaniem aplikacji Petclinic Wydajność Eksperymenty dotyczące wydajności zostały przeprowadzone na ostatecznych wersjach obu badanych aplikacji. W testach uczestniczyły opisane w części trzy grupy osób. Testy zostały przeprowadzone wielokrotnie dla każdego z przypadków. Prezentowane wartości stanowią wartość średnią uzyskanych wyników. Dla zwiększenia pewności wyników eksperymentu, czas trwania wszystkich testów ustalono na pół godziny. Tabela 6.2 przedstawia liczbę żądań uzyskaną dla każdej z grup. Przed znakiem ukośnika podano wartości dla aplikacji opartej o Spring MVC, po znaku podano wartość dla aplikacji wykorzystującej JSF. Pierwszy wiersz przedstawia maksymalną liczbę uzyskanych żądań, które zakończyły się powodzeniem. Drugi prezentuje liczbę żądań, która była możliwa do wykonania w ustalonym czasie 3 sekund na odpowiedź. W przypadku nie zwrócenia odpowiedzi w żądanym czasie bądź zwrócenia odpowiedzi błędnej test był kończony. W pierwszym teście składającym się z użytkowników pierwszej grupy widoczna jest znacząca różnica pomiędzy wartością maksymalną liczby żądań obsługiwanych jednocześnie przez serwer, różnica jest ponad dwukrotna. Wynika to bezpośrednio z faktu, iż aplikacje oparte o JavaServer Faces starają się upodobnić do aplikacji desktopowych. Wiąże się to jednak z obciążeniem wszystkich żądań danymi składowanymi w sesji. Każde żądanie kierowane do aplikacji wykorzystującej szkielet JavaServer Faces posiada ciasteczko o średnim rozmiarze 5 kb. Wpływa to znacząco na wydajność aplikacji, w analizowanych przypadku ponad dwukrotnie. Wysyłane dane przechowują stan często złożonych komponentów między poszczególnymi żądaniami HTTP. 82

84 Tabela 6.2: Liczba żądań w zależności od badanej grupy użytkowników Pomiar Grupa 1 Grupa 2 Grupa 3 Maks. liczba żądań 478/ / /184 Maks. liczba żądań w 3 sek. 54/38 52/35 37/26 Wielkość w liczniku dotyczy Spring MVC, w mianowniku JavaServer Faces Tabela 6.3: Średni czas odpowiedzi aplikacji w zależności od badanej grupy użytkowników Pomiar Grupa 1 Grupa 2 Grupa 3 Maks. liczba żądań 0,4/1,9 0,6/0,8 0,54/1,4 Maks. liczba żądań w 3 sek. 0,25/0,5 0,12/0,27 0,19/0,36 Wielkość w liczniku dotyczy Spring MVC, w mianowniku JavaServer Faces W drugiej z badanych grup uczestniczyły osoby modyfikujące wyłącznie dane aplikacji. W związku z wykonywaniem czynności mających odzwierciedlenie w bazie danych aplikacji, wydajność znacząco spadła. Żądania, które skutkują wykonaniem operacji modyfikujących na danych składowanych w bazie danych są znacznie bardziej kosztowne od standardowych żądań, które pobierają dane. O ile w przypadku aplikacji petclinic-springmvc spadek był znaczny to aplikacja petclinic-jsf zanotowała jedynie niewielki spadek ze 190 do 172 żądań. Ta sytuacja ma prawdopodobnie miejsce z powodu wielkości przesyłanego ciasteczka, które przy zwiększonej liczbie żądań zaczyna odgrywać znaczącą rolę. W trzeciej grupie składającej się z dwóch poprzednich w proporcji 4/1 uzyskane wyniku plasują się między wynikami opisywanych wcześniej grup. Liczba żądań aplikacji opartej o Spring MVC nie uległa spodziewanemu zwiększeniu i pomimo proporcji preferujących użytkowników przeglądających dane, wynik jest zbliżony badziej do liczby żądań w przypadku drugiej grupy. W drugim wierszu przedstawiono wartości średnie dla zmierzonej liczby żądań z ustalonym limitem czasowym na odpowiedź. Również podczas tego testu lepsza okazała się aplikacja wykorzystująca framework Spring MVC, charakteryzują ca się większą liczbę obsłużonych żądań. Na uwagę zasługuje stały we wszystkich grupach stosunek żądań aplikacji opartej o Spring MVC oraz JavaServer Faces wynoszący około 1,4. Kolejna tabela 6.3 przedstawia, w sekundach, wielkości średnie czasów odpowiedzi dla żądań z poprzedniej tabeli. Przed znakiem ukośnika podano wartości dla aplikacji opartej o Spring MVC, po znaku podano wartość dla aplikacji wykorzystującej JSF. Ponownie aplikacja wykorzystująca Spring MVC wypada korzystniej w prezentowanym porównaniu. Największa różnica średniego czasu odpowiedzi dotyczy testu mierzącego maksymalną możliwą do obsłużenia liczbę żądań z wykorzystaniem grupy 1. Pozostałe wielkości różnią się w większości przypadków o 50%. Najbardziej zbliżony czas odpowiedzi występuje w teście wykorzystującą grupę drugą. Świadczy to o tym, iż aplikacja oparta o szkielet JavaServer Faces o niewielkiej liczbie różnych żądań upodabnia się pod względem wydajnościowym do aplikacji wykorzystującej Spring MVC Metryki kodu Celem pomiaru metryk kodu było porównanie wielkości zaimplementowanych projektów jak również jakości powstałego kodu. Podczas eksperymentów uwzględniono kod 83

85 Tabela 6.4: Metryki kodu modułów aplikacji Metryka data core springmvc jsf Liczba linii kodu Liczba linii kodu metod Liczba klas Liczba interfejsów Liczba pakietów Liczba metod Liczba pól projektu w języku Java jak również kod stron, odpowiedzialny za wizualne przedstawienie danych. Obie grupy metryk zostaną przedstawione poniżej. Kod Javy Tabela 6.4 ma za zadanie pokazać wielkość zaimplementowanych projektów. Zmierzono liczbę linii kodu, artefaktów oraz elementów klas poszczególnych modułów projektu. W analizie uwzględniono moduł odpowiedzialny za dostęp do danych, logikę biznesową aplikacji jak również moduły implementujące warstwę aplikacji internetowej zaimplementowane z wykorzystaniem szkieletów Spring MVC oraz JavaServer Faces. W przypadku linii kodu zostały zmierzone dwie metryki. Pierwsza z nich jest związana z całkowitą liczbą linii kodu całej aplikacji, druga dotyczy wyłącznie kodu umieszczonego w metodach. Projekt oparty o Spring MVC zawiera więcej linii kodu niż projekt oparty o JavaServer Faces. Stosunek wielkości ulega jedynie nieznacznemu zmniejszeniu przy porównaniu metryki zliczającej liczbę linii kodu w metodach. Wartym zauważenia jest fakt, iż najmniejszy z modułów dotyczy logiki biznesowej. Jest on ponad czterokrotnie mniejszy od modułów warstwy aplikacji internetowej. Zauważona różnica świadczy o charakterze aplikacji służącej do zarządzania danymi (aplikacja typu CRUD [54]), w której nie ma potrzeby istnienia rozwiniętej logiki biznesowej. Liczba artefaktów projektu tzn. liczba klas, interfejsów bądź pakietów w porównywanych warstwach aplikacji internetowej jest w przybliżeniu taka sama, z wyjątkiem liczby klas, która jest większa w projekcie wykorzystującym Spring MVC. Ponownie moduł logiki biznesowej (kolumna core) zawiera najmniejszą ilość elementów. Na uwagę zasługuje interfejs wykorzystany w aplikacji opartej o JavaServer Faces, który posłużył jako klasa narzędziowa gromadząca nazwy beanów, potrzebne w celu późniejszego odwołania się do nich z aplikacji. Ostatnim elementem wskazującym na wielkości modułów jest liczba pól i metod. Są to jedyne metryki, w których Spring MVC posiada niższe wartości w porównaniu z JavaServer Faces. Wynika to, ze sposobu tworzenia aplikacji z wykorzystaniem JavaServer Faces, która opiera się na zastosowaniu komponentów. Tworzone komponenty są zwykłymi obiektami Javy (POJO), które udostępniają swój wewnętrzny stan poprzez metody dostępowe. Wspomniane metody wykorzystywane są głównie z poziomu kodu szablonów, poprzez odpowiednie ich wywołania. Zastosowanie modelu komponentowego powoduje zwiększenie liczby pól w klasach oraz metod dostępowych. Kolejne porównanie dotyczy metryk kodu z podziałem funkcjonalnym pakietów według pełnionych funkcji. Wprowadzono podział na kod walidacji (VAL), kontrolerów (WEB), 84

86 Tabela 6.5: Metryki kodu pakietów według pełnionych funkcji Metryka VAL WEB UT CON LST FORM Liczba linii kodu 59/ 233/109 67/ /63 93/ /300 Liczba linii kodu metod 34/ 91/31 30/68 64/28 32/ /121 Liczba klas 2/ 6/4 2/3 3/2 7/6 9/5 Liczba interfejsów 0/ 0/0 0/1 0/0 0/0 0/0 Liczba metod 4/ 22/22 0/3 20/4 0/54 60/45 Liczba pól 0/ 7/4 0/1 7/0 7/17 15/19 Wielkość w liczniku dotyczy Spring MVC, w mianowniku JavaServer Faces narzędziowy (UT), konwersji (CON), wyświetlania listy obiektów (LST) oraz związany z obsługą formularzy (FORM). Tebela 6.5 przedstawia wielkości odpowiednich metryk. Przed ukośnikiem podano wartość metryki dla aplikacji opartej o Spring MVC, po dla aplikacji wykorzystującej JavaServer Faces. Aplikacja oparta o JavaServer Faces nie posiadała w kodzie aplikacji logiki związanej z walidacją wprowadzanych danych. Wszystkie aspekty weryfikacji wprowadzanych danych udało się zaimplementować z wykorzystaniem tagów biblioteki Trinidad w kodzie szablonów. W przypadku kodu narzędziowego zawierającego klasy pomocnicze aplikacji, porównanie wypada na korzyść aplikacji wykorzystującej Spring MVC. Wymagana liczba linii kodu jest dwukrotnie mniejsza. W przypadku JavaServer Faces konieczna była implementacja klas pomocniczych związanych z dostępem do zarządzanych beanów z poziomu aplikacji jak również klas przechowujących informacje potrzebne do lokalizacji. Czynność związana z konwersją wprowadzanych danych na obiekty języka Java, była łatwiejsza do zaimplementowania z wykorzystaniem szkieletu JSF. Na ponad dwukrotnej różnicy w liczbie linii kodu zaważył brak konieczności implementacji konwertera wyświetlającego listę leków. Porównanie dalszych funkcjonalności jest utrudnione ze względu na zastosowanie zróżnicowanego modelu, wynikającego z natury użytych szkieletów programistycznych. Moduł kontrolerów (WEB) w przypadku aplikacji opartej o Spring MVC stanowi klasyczny zbiór kontrolerów odbierających żądania od użytkownika. W przypadku aplikacji JavaServer Faces rolę kontrolerów w znacznej części pełnią komponenty, których kod został uwzględniony w kolumnie LST. Kontrolery aplikacji opartej o szkielet JSF pełnią rolę fasady logiki biznesowej, używanych pomocniczo przez klasy komponentów. Ostatnim opisywanym elementem jest kod związany z obsługą formularzy (FORM). Podejście zastosowane w JavaServer Faces, które jest bardziej podobne do tworzenia aplikacji desktopowych skutkuje prawie dwukrotnie mniejszą liczbą linii kodu. W rzeczywistości część logiki znajduje się również w kodzie związanym z wyświetleniem listy obiektów. Wyniki pozostałych metryk prostych (nie zostały przedstawione w tabeli) tj. liczba dzieci, głębokość drzewa dziedziczenia czy liczba przeciążonych metod wskazują na charakterystyczne elementy poszczególnych projektów. W projekcie opartym o Spring MVC elementem wyróżniającym się są klasy formularzy, które mają największą wartość głębokości drzewa dziedziczenia, średnio równą 8,78 oraz posiadają najwięcej przeciążonych metod, średnio 3,11. W przypadku projektu wykorzystującego JavaServer Faces średnia głębokość drzewa dziedziczenia wynosi 1. Podobne wartości wskazują metryki liczby 85

87 Tabela 6.6: Metryki złożone aplikacji opartej o Spring MVC oraz JavaServer Faces Metryka Spring MVC JavaServer Faces Indeks specjalizacji 1,862 0 Skojarzenia dośrodkowe 0,857 2,429 Skojarzenia odśrodkowe 4,143 2,714 Abstrakcyjność 0,016 0,036 Niestabilność 0,829 0,664 Znormalizowana odległość 0,187 0,3 przeciążonych metod oraz liczby dzieci, które wynoszą 0. Ma to ścisły związek z brakiem konieczności dziedziczenia po klasach frameworka JSF, skutkujący mniejszą inwazyjnością szkieletu. Wynik pomiaru metryk złożonych przedstawia tabela 6.6. Przedstawiono wartości średnie obliczone na podstawie metryk pakietów każdej z aplikacji. Indeks specjalizacji bazuje na stosunku ilorazu liczby przeciążonych metod oraz głębokości drzewa dziedziczenia do liczby metod w klasie. W związku z tym, iż aplikacja oparta o JavaServer Faces nie posiada przeciążonych metod wynik ilorazu wynosi 0. Metryka skojarzenia dośrodkowego wskazuje na średnią wartość odpowiedzialności dla pakietów (ang. package s responsibility). W przypadku Spring MVC jest ona ponad dwukrotnie mniejsza, co oznacza iż pakiety tej aplikacji posiadają mniejszą odpowiedzialność w porównaniu z aplikacją korzystającą z JavaServer Faces. W aplikacji opartej o Spring MVC największą odpowiedzialność posiadają pakiety narzędziowe oraz pakiety konwerterów, w aplikacji wykorzystującej szkielet JSF pakiety narzędziowe oraz pakiety kontrolerów. Metryka skojarzenia odśrodkowego wskazuje średnią wartość zależności od innych pakietów. W przypadku aplikacji wykorzystującej Spring MVC najbardziej zależne są pakiety formularzy, kontrolerów oraz list obiektów. Dla aplikacji opartej o JSF największe wartości opisywanej metryki posiadają pakiety kontrolerów oraz listy obiektów. Stosunek skojarzenia odśrodkowego oraz skojarzenia dośrodkowego w przypadku obu analizowanych projektów jest różny. Dla projektu petclinic-springmvc wynosi prawie 5 a dla petclinic-jsf nieco ponad 1. Prowadzi to do wniosku, iż w aplikacji opartej o Spring MVC znaczna liczba klas umieszczonych we wspomnianych pakietach zależy od niewielkiej liczby innych klas. W przypadku aplikacji wykorzystującej JavaServer Faces mniej więcej podobna liczba klas zgrupowanych w pakiety korzysta i udostępnia swoje usługi. Abstrakcyjność obu projektów jest na podobnie niskim poziomie, zdiagnozo wano znacznie większą liczbę klas konkretnych w porównaniu do liczby klas abstrakcyjnych bądź interfejsów. Niestabilność będąca ilorazem skojarzeń odśrodkowych do sumy wszystkich skojarzeń jest większa w przypadku aplikacji petclinic-springmvc. Jest to konsekwencja wartości opisywanych wcześniej skojarzeń. W przypadku aplikacji petclinic-springmvc jak i petclinic-jsf najbardziej niestabilnymi są pakiety narzędziowe. Ostatnią z metryk złożonych jest metryka dotycząca znormalizowanej odległości kategorii od ideału wskazującą na wyważenie pakietu pomiędzy abstrakcyjnością a jego stabilnością. W tym przypadku lepiej wypada projekt oparty o Spring MVC, gdyż wartość metryki jest bliższa zeru. Wynika to z większej niestabilności projektu przy niewielkiej abstrakcyjności. 86

88 Rysunek 6.2: Zmiana wartości metryk podczas kolejnych etapów implementacji aplikacji Ostatnim elementem bazującym na metrykach kodu projektów jest przedstawienie zmian wartości metryk kodu na przykładzie artefaktów projektu, podczas implementacji kolejnych etapów projektu. Zmiany prezentuje rysunek 6.2. Wyróżniono trzy etapy implementacji związane z przeglądaniem danych (browsing), zarządzaniem danymi (managing) oraz lokalizacją aplikacji (web). Teoretycznie proces lokalizacji aplikacji powinien przebiegać niezależnie od procesu implementacji aplikacji. Rysunek 6.2 wskazuje, iż w obu badanych aplikacjach procesowi lokalizacji towarzyszył nieznaczny wzrost liczby artefaktów. Dowodzi to poprawności obu rozwiązań w zakresie internacjonalizacji. Kod szablonów Badaniu metryk kodu został również poddany kod szablonów formatujących wyświetlane dane. Wprowadzono podział na następujące typy widoków: lista stronicowana, szczegóły obiektu, formularz modyfikacji, formularz dodawania wizyty, prosta lista posiadająca ustaloną liczbę wierszy. Pierwszy z przeprowadzonych eksperymentów dotyczył liczby znaczników, generujących treść w dynamiczny sposób potrzebnych do zaimplementowania widoku o określonym charakterze. Rysunek 6.3 przedstawia średnią liczbę znaczników wyliczoną na podstawie widoków obu aplikacji. Z wykresu bezpośrednio wynika, iż liczba znaczników potrzebna do wyświetlenia dynamicznej treści jest większa w przypadku aplikacji wykorzystującej JavaServer Faces. Największa różnica występuje w przypadku prostej listy, która w aplikacji petclinic-jsf została zaimplementowana na bazie listy stronicowanej. Narzut takiego rozwiązania, pod względem liczby znaczników, wydaje się duży, jednak biblioteka Trinidad nie posiada prostszego komponentu przeznaczonego do tego celu. Podobnie duża różnica istnieje w przypadku listy stronicowanej jednak tutaj wynikowa lista jest bardziej złożona od analogicznej listy w aplikacji petclinic-springmvc. Najmniejszą różnica dotyczy formularza modyfikacji 87

89 Rysunek 6.3: Liczba znaczników wg rodzaju widoków Rysunek 6.4: Wielkość wygenerowanej strony HTML obiektu. Biorąc pod uwagę dodatkowy narzut w postaci znaczników walidujących w aplikacji opartej o szkielet JSF sumarycznie mierzona złożoność jest porównywalna. Rysunek 6.4 przedstawia wielkość wygenerowanej strony HTML. Wielkość wszystkich zmierzonych stron szablonów z obu aplikacji była podobna i mieściła się w granicach 7 kb. Dopiero zamienienie dynamicznych znaczników na statyczną treść wprowadziło kilku krotną różnicę na niekorzyść stron utworzonych z wykorzystaniem biblioteki Trinidad. Największa różnica występuje w przypadku list, jest to uzasadnione po części stopniem złożoności wygenerowanej listy stronicowanej. Różnica w wielkości powstałych stron wynika w głównej mierze z dodanych elementów języka JavaScript Dostępność komponentów Trinidad Kolejny z przeprowadzonych eksperymentów dotyczył pomiaru dostępności komponentów Trinidad wykorzystywanych w aplikacji opartej o JavaServer Faces. W pierwszym z testów zmierzono poprawność komponentów według przedstawionej 88

90 Tabela 6.7: Poprawność działania komponentów Triniadad Przeglądarka internetowa Liczba punktów Internet Explorer 6.0 SP2 62 Internet Explorer Firefox Opera wcześniej trójstopniowej skali, w zależności od użytej przeglądarki internetowej. Wyniki przedstawia tabela 6.7 Rysunek 6.5 prezentuje udział komponentów według poprawności działania w wybranych przeglądarkach internetowych. Rysunek 6.5: Poprawność działania komponentów wg przeglądarek internetowych W wyniku przeprowadzonego testu okazało się, iż komponenty działają bezbłędnie jedynie w przeglądarkach Internet Explorer w wersji 6 oraz 7. Nieznacznie gorzej wypadły komponenty podczas pracy z przeglądarką Firefox 2.0. Jedynie trzy elementy interfejsu użytkownika (choosedate, inputdata oraz inputlistofvaluesnie) działały we właściwy sposób. Podczas wyświetlania okna modalnego możliwa była modyfikacja zawartości poprzednio wyświetlanego okna, usterka ta jednak nie miała wpływu na pracę z aplikacją. Najgorzej wypadły komponenty podczas pracy z przeglądarką Opera w wersji Trzy komponenty (choosedate, inputdata oraz selectbooleancheckbox) pracowały niewłaściwie zwracając kod wewnętrznego błędu serwera. Dwa kolejne (navigationtree oraz inputnumberspinbox) nie działały w pełni poprawnie posiadały nieprawidłowy wygląd. Kolejny test dotyczył walidacji komponentów Triniad z wykorzystaniem oficjalnego walidatora organizacji W3C dla specyfikacji HTML 4.01 Transitional. Podczas testów walidacja części z komponentów kończyła się komunikatem o wewnętrznym błędzie serwera o następującej treści the server encountered an internal error() that prevented it from fulfilling this request. Ograniczyło to badaną grupę komponentów o sześć elementów. Dodatkowo komponent selectonechoice podczas pracy zgłaszał komunikat błędu o treści javax.faces.facesexception: SelectItem with no value co również wykluczyło go z badanej puli komponentów. Ostatecznie w testach walidacyjnych wzięło udział 31 komponentów. 89

91 Rysunek 6.6: Udział błędów określonego typu w komponentach Trinidad W wyniku przeprowadzonych testów okazało się, iż znalezione błędy w ponad 95% należą do jednej z czterech grup. Rysunek 6.6 przedstawia procentowy udział błędów w badanych komponentach. Do najczęściej spotykanych błędów należała niepoprawna wartość atrybutu id znaczników, które zaczynały się od znaku dolara bądź podkreślenia. Braku atrybuty type w znaczniku script. Niepoprawnym umieszczeniu znacznika, najczęściej dotyczyło to znacznika tr. Braku odpowiadającego znacznika zamykającego, najczęściej dla znaczników caption oraz table. Ponad 1/3 ze zbadanych komponentów nie posiadała błędów, 13% posiadało jeden błąd a 20% dwa błędy. Komponenty z liczbą błędów mieszczącą się między trzy a siedem stanowiły około 1/4 wszystkich komponentów. Ponad 6% elementów interfejsu użytkownika posiadało ponad siedem błędów. Średnia liczba błędów przypadająca na komponent wyniosła 2,81. Walidator nie stwierdził w żadnym z badanych komponentów treści generującej ostrzeżenia. Do komponentów o największej liczbie błędów należą w kolejności inputcolor z 19 błędami, choosecolor z 13 błędami oraz selectmanycheckbox z 7 błędami. Należy zauważyć, iż wychwycone błędy można łatwo usunąć poprzez poprawnienie metody generującej identyfikatory dla znaczników id, aby nie umieszczały na początku niedozwolonych znaków, dodanie odpowiednich znaczników zamykających czy uzupełnienie wybranych znaczników o wymagane atrybuty Łatwość wprowadzania zmian Pomiar łatwości wprowadzania zmian w aplikacji bazuje na liczbie plików które należy zmodyfikować, uzupełnić lub dodać w celu wykonania określonego zadania. Definicje akcji wraz z opisem zadań zostały zamieszczone w części Tabela 6.8 przedstawia wynik eksperymentu mierzącego łatwość wprowadzania zmian na podstawie liczby plików, w których należy dokonać zmian. Wartość przed ukośnikiem odnosi się do aplikacji opartej o Spring MVC, wartość po do aplikacji wykorzystującej JavaServer Faces. Zmierzone czynności dotyczą dodania do aplikacji listy stronicowanej, formularza oraz lokalizacji aplikacji. Podczas dodania kolejnej listy stronicowanej w aplikacji opartej o Spring MVC należy zmodyfikować plik petclinic-servlet.xml, dodać nowe mapowanie do kontrolera oraz zdefiniować metodę odpowiedzialną za obsługę żądania wyświetlenia listy wizyt. Wspomniane operacje mają charakter uzupełnienia wspomnianego pliku konfiguracyjnego. Ko- 90

Web frameworks do budowy aplikacji zgodnych z J2EE

Web frameworks do budowy aplikacji zgodnych z J2EE Web frameworks do budowy aplikacji zgodnych z J2EE Jacek Panachida promotor: dr Dariusz Król Przypomnienie Celem pracy jest porównanie wybranych szkieletów programistycznych o otwartym kodzie źródłowym

Bardziej szczegółowo

Web frameworks do budowy aplikacji zgodnych z J2EE. Jacek Panachida

Web frameworks do budowy aplikacji zgodnych z J2EE. Jacek Panachida Web frameworks do budowy aplikacji zgodnych z J2EE Jacek Panachida Cel pracy Analiza wybranych ram projektowych dostępnych dla platformy Java Warunki selekcji napisany z wykorzystaniem języka Java oraz

Bardziej szczegółowo

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych PAŃSTWOWA WYŻSZA SZKOŁA ZAWODOWA W ELBLĄGU INSTYTUT INFORMATYKI STOSOWANEJ Sprawozdanie z Seminarium Dyplomowego Temat: Ułatwienia wynikające z zastosowania Frameworku CakePHP podczas budowania stron internetowych

Bardziej szczegółowo

1 Wprowadzenie do J2EE

1 Wprowadzenie do J2EE Wprowadzenie do J2EE 1 Plan prezentacji 2 Wprowadzenie do Java 2 Enterprise Edition Aplikacje J2EE Serwer aplikacji J2EE Główne cele V Szkoły PLOUG - nowe podejścia do konstrukcji aplikacji J2EE Java 2

Bardziej szczegółowo

Wstęp Budowa Serwlety JSP Podsumowanie. Tomcat. Kotwasiński. 1 grudnia 2008

Wstęp Budowa Serwlety JSP Podsumowanie. Tomcat. Kotwasiński. 1 grudnia 2008 Adam 1 grudnia 2008 Wstęp Opis Historia Apache kontener serwletów rozwijany w ramach projektu Apache jeden z bardziej popularnych kontenerów Web open source, Apache Software License rozwijany przez ASF

Bardziej szczegółowo

Wzorce prezentacji internetowych

Wzorce prezentacji internetowych Wzorce prezentacji internetowych 1. Model kontrolera widoku (Model View Controller). 2. Kontroler strony (Page Controller). 3. Kontroler fasady (Front Controller). 4. Szablon widoku (Template View). 5.

Bardziej szczegółowo

Uniwersytet Łódzki Wydział Matematyki i Informatyki, Katedra Analizy Nieliniowej. Wstęp. Programowanie w Javie 2. mgr inż.

Uniwersytet Łódzki Wydział Matematyki i Informatyki, Katedra Analizy Nieliniowej. Wstęp. Programowanie w Javie 2. mgr inż. Uniwersytet Łódzki Wydział Matematyki i Informatyki, Katedra Analizy Nieliniowej Wstęp Programowanie w Javie 2 mgr inż. Michał Misiak Agenda Założenia do wykładu Zasady zaliczeń Ramowy program wykładu

Bardziej szczegółowo

Szkolenie wycofane z oferty

Szkolenie wycofane z oferty Szkolenie wycofane z oferty Program szkolenia: Java Server Faces 2 Informacje: Nazwa: Java Server Faces 2 Kod: Java-EE-JSF 2 Kategoria: Java EE Grupa docelowa: developerzy Czas trwania: 3 dni Forma: 50%

Bardziej szczegółowo

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki Dariusz Brzeziński Politechnika Poznańska, Instytut Informatyki Język programowania prosty bezpieczny zorientowany obiektowo wielowątkowy rozproszony przenaszalny interpretowany dynamiczny wydajny Platforma

Bardziej szczegółowo

Warstwa prezentacji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe.

Warstwa prezentacji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe. Warstwa prezentacji wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe. 1. Definicja warstwy prezentacji - pięciowarstwowy model logicznego rozdzielania zadań 2. Podstawowe przypadki - analiza

Bardziej szczegółowo

Warstwa integracji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe.

Warstwa integracji. wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe. Warstwa integracji wg. D.Alur, J.Crupi, D. Malks, Core J2EE. Wzorce projektowe. 1. Ukrycie logiki dostępu do danych w osobnej warstwie 2. Oddzielenie mechanizmów trwałości od modelu obiektowego Pięciowarstwowy

Bardziej szczegółowo

Forum Client - Spring in Swing

Forum Client - Spring in Swing Forum Client - Spring in Swing Paweł Charkowski. 0. Cel projektu Celem projektu jest próba integracji Spring Framework z różnymi technologiami realizacji interfejsu użytkownika, oraz jej ocena. Niniejszy

Bardziej szczegółowo

Czym jest Java? Rozumiana jako środowisko do uruchamiania programów Platforma software owa

Czym jest Java? Rozumiana jako środowisko do uruchamiania programów Platforma software owa 1 Java Wprowadzenie 2 Czym jest Java? Język programowania prosty zorientowany obiektowo rozproszony interpretowany wydajny Platforma bezpieczny wielowątkowy przenaszalny dynamiczny Rozumiana jako środowisko

Bardziej szczegółowo

Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC

Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC Akademia MetaPack Uniwersytet Zielonogórski Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC Krzysztof Blacha Microsoft Certified Professional Budowa aplikacji ASP.NET z wykorzystaniem wzorca MVC Agenda:

Bardziej szczegółowo

Grzegorz Ruciński. Warszawska Wyższa Szkoła Informatyki 2011. Promotor dr inż. Paweł Figat

Grzegorz Ruciński. Warszawska Wyższa Szkoła Informatyki 2011. Promotor dr inż. Paweł Figat Grzegorz Ruciński Warszawska Wyższa Szkoła Informatyki 2011 Promotor dr inż. Paweł Figat Cel i hipoteza pracy Wprowadzenie do tematu Przedstawienie porównywanych rozwiązań Przedstawienie zalet i wad porównywanych

Bardziej szczegółowo

Programowanie w Javie 2. Płock, 26 luty 2014 r.

Programowanie w Javie 2. Płock, 26 luty 2014 r. Programowanie w Javie 2 Płock, 26 luty 2014 r. Zaliczenie wykładu i ćwiczeń Zaliczenie ćwiczeń (projekt na zaliczenie, 3 prace domowe) Zaliczenie wykładu (referat na 1h) Ocena ćwiczeń: 70% projekt + 30%

Bardziej szczegółowo

Wybrane działy Informatyki Stosowanej

Wybrane działy Informatyki Stosowanej Wybrane działy Informatyki Stosowanej Java Enterprise Edition WebServices Serwer aplikacji GlassFish Dr hab. inż. Andrzej Czerepicki a.czerepicki@wt.pw.edu.pl http://www2.wt.pw.edu.pl/~a.czerepicki Aplikacje

Bardziej szczegółowo

Serwery aplikacji. mgr Radosław Matusik. Wydział Matematyki i Informatyki Uniwersytetu Łódzkiego www.math.uni.lodz.pl/ radmat radmat@math.uni.lodz.

Serwery aplikacji. mgr Radosław Matusik. Wydział Matematyki i Informatyki Uniwersytetu Łódzkiego www.math.uni.lodz.pl/ radmat radmat@math.uni.lodz. Wydział Matematyki i Informatyki Uniwersytetu Łódzkiego www.math.uni.lodz.pl/ radmat radmat@math.uni.lodz.pl Serwer aplikacji Serwer aplikacji to: Serwer wchodzący w skład sieci komputerowej, przeznaczony

Bardziej szczegółowo

1 90 min. Aplikacje WWW Harmonogram spotkań, semestr zimowy (studia stacjonarne)

1 90 min. Aplikacje WWW Harmonogram spotkań, semestr zimowy (studia stacjonarne) 1 90 min. Aplikacje WWW Harmonogram ń, semestr zimowy -2017 (studia stacjonarne) 6 października Wprowadzenie do aplikacji WWW Rys historyczny Składniki architektury WWW o klient HTTP o serwer HTTP o protokół

Bardziej szczegółowo

ASP.NET MVC. Grzegorz Caban grzegorz.caban@gmail.com. 20 stycznia 2009

ASP.NET MVC. Grzegorz Caban grzegorz.caban@gmail.com. 20 stycznia 2009 ASP.NET MVC Grzegorz Caban grzegorz.caban@gmail.com 20 stycznia 2009 Agenda Przyczyna powstania Co to jest ASP.NET MVC Architektura Hello World w ASP.NET MVC ASP.NET MVC vs ASP.NET WebForm Przyszłość framework'a

Bardziej szczegółowo

Przykłady tworzenia aplikacji komponentowych w technologii JavaServer Faces 2.1 na podstawie

Przykłady tworzenia aplikacji komponentowych w technologii JavaServer Faces 2.1 na podstawie Przykłady tworzenia aplikacji komponentowych w technologii JavaServer Faces 2.1 na podstawie http://docs.oracle.com/javaee/6/tutorial/doc/ Przykłady na podstawie zadań lab. z przedmiotu Technologie internetowe

Bardziej szczegółowo

Generated by Foxit PDF Creator Foxit Software http://www.foxitsoftware.com For evaluation only. System Szablonów

Generated by Foxit PDF Creator Foxit Software http://www.foxitsoftware.com For evaluation only. System Szablonów System Szablonów System szablonów System szablonów to biblioteka, która pozwala oddzielić warstwę prezentacji od warstwy logicznej. Aplikacja WWW najpierw pobiera wszystkie dane, przetwarza je i umieszcza

Bardziej szczegółowo

Dokument Detaliczny Projektu Temat: Księgarnia On-line Bukstor

Dokument Detaliczny Projektu Temat: Księgarnia On-line Bukstor Koszalin, 15.06.2012 r. Dokument Detaliczny Projektu Temat: Księgarnia On-line Bukstor Zespół projektowy: Daniel Czyczyn-Egird Wojciech Gołuchowski Michał Durkowski Kamil Gawroński Prowadzący: Dr inż.

Bardziej szczegółowo

Aplikacje internetowe i rozproszone - laboratorium

Aplikacje internetowe i rozproszone - laboratorium Aplikacje internetowe i rozproszone - laboratorium Enterprise JavaBeans (EJB) Celem tego zestawu ćwiczeń jest zapoznanie z technologią EJB w wersji 3.0, a w szczególności: implementacja komponentów sesyjnych,

Bardziej szczegółowo

prepared by: Programowanie WWW Servlety

prepared by: Programowanie WWW Servlety Programowanie WWW Servlety Przypomnienie problemu Aplikacja do liczenia kredytów Klasa Kredyt Formatka do wprowadzania danych (czysty HTML) Skrypt liczący ratę (JSP wykorzystujące klasę Kredyt) Klasa Kredyt

Bardziej szczegółowo

Aplikacje Internetowe, Servlety, JSP i JDBC

Aplikacje Internetowe, Servlety, JSP i JDBC Aplikacje Internetowe, Servlety, JSP i JDBC Opis Java 2 Enterprise Edition (JEE) jest potężną platformą do tworzenia aplikacji webowych. PLatforma JEE oferuje wszystkie zalety tworzenia w Javie plus wszechstronny

Bardziej szczegółowo

Tworzenie aplikacji Web Alicja Zwiewka. Page 1

Tworzenie aplikacji Web Alicja Zwiewka. Page 1 Tworzenie aplikacji Web Alicja Zwiewka Page 1 Co to są web-aplikacje? Aplikacja internetowa (ang. web application) program komputerowy, który pracuje na serwerze i komunikuje się poprzez sieć komputerową

Bardziej szczegółowo

Kurs ASP.NET ASP.NET CORE APLIKACJE WEBOWE

Kurs ASP.NET ASP.NET CORE APLIKACJE WEBOWE Kurs ASP.NET ASP.NET CORE APLIKACJE WEBOWE Cena szkolenia Cena szkolenia wynosi 100 zł za 60 min. Ilość godzin szkolenia jest zależna od postępów w nauce uczestnika kursu oraz ilości czasu, którą będzie

Bardziej szczegółowo

Wzorce architektoniczne

Wzorce architektoniczne Wzorce architektoniczne Architektura warstwowa, MVP, MVC, MVVM Wojciech Szymecki Wydział Fizyki, Astronomii i Informatyki Stosowanej Uniwersytet Mikołaja Kopernika 23 maja 2014 Architektura warstwowa W

Bardziej szczegółowo

Full Stack JavaScript z Angular i Nest. Dni: 5. Opis: Adresaci szkolenia

Full Stack JavaScript z Angular i Nest. Dni: 5. Opis: Adresaci szkolenia Kod szkolenia: Tytuł szkolenia: DED/FSJS Full Stack JavaScript z Angular i Nest Dni: 5 Opis: Adresaci szkolenia Kurs przeznaczony jest dla programistów posiadających podstawową wiedzę w zakresie JavaScript,

Bardziej szczegółowo

Konspekt pracy inżynierskiej

Konspekt pracy inżynierskiej Konspekt pracy inżynierskiej Wydział Elektryczny Informatyka, Semestr VI Promotor: dr inż. Tomasz Bilski 1. Proponowany tytuł pracy inżynierskiej: Komunikator Gandu na platformę mobilną Android. 2. Cel

Bardziej szczegółowo

Wykład 1 Inżynieria Oprogramowania

Wykład 1 Inżynieria Oprogramowania Wykład 1 Inżynieria Oprogramowania Wstęp do inżynierii oprogramowania. Cykle rozwoju oprogramowaniaiteracyjno-rozwojowy cykl oprogramowania Autor: Zofia Kruczkiewicz System Informacyjny =Techniczny SI

Bardziej szczegółowo

Wybrane działy Informatyki Stosowanej

Wybrane działy Informatyki Stosowanej Wybrane działy Informatyki Stosowanej JSP - Java Server Pages dr hab. inż. Andrzej Czerepicki a.czerepicki@wt.pw.edu.pl http://www2.wt.pw.edu.pl/~a.czerepicki 2019 Aplikacje i skrypty WWW klasyfikacja

Bardziej szczegółowo

Wybrane działy Informatyki Stosowanej

Wybrane działy Informatyki Stosowanej Wybrane działy Informatyki Stosowanej Java Enterprise Edition. WebServices. Język XML. Serwer aplikacji GlassFish. Dr inż. Andrzej Czerepicki a.czerepicki@wt.pw.edu.pl http://www2.wt.pw.edu.pl/~a.czerepicki

Bardziej szczegółowo

Aplikacje WWW Wprowadzenie

Aplikacje WWW Wprowadzenie Aplikacje WWW Wprowadzenie Beata Pańczyk na podstawie http://www.e-informatyka.edu.pl/ http://wazniak.mimuw.edu.pl/index.php?title=aplikacje_www Plan wykładu Składniki architektury WWW: klient HTTP, serwer

Bardziej szczegółowo

EJB 3.0 (Enterprise JavaBeans 3.0)

EJB 3.0 (Enterprise JavaBeans 3.0) EJB 3.0 (Enterprise JavaBeans 3.0) Adrian Dudek Wirtualne Przedsiębiorstwo 2 Wrocław, 1 czerwca 2010 Plan prezentacji 1 Wprowadzenie Cel prezentacji Czym jest EJB 3.0? Historia 2 3 Cel prezentacji Wprowadzenie

Bardziej szczegółowo

Początki Javy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 8

Początki Javy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java   1 / 8 Początki Javy Java została pierwotnie zaprojektowana dla telewizji interaktywnej, ale była to zbyt zaawansowaną technologią dla branży cyfrowej telewizji kablowej. James Gosling, Mike Sheridan i Patrick

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Laboratorium 1. Wstęp do programowania w języku Java. Narzędzia 1. Aby móc tworzyć programy w języku Java, potrzebny jest zestaw narzędzi Java Development Kit, który można ściągnąć

Bardziej szczegółowo

OpenLaszlo. OpenLaszlo

OpenLaszlo. OpenLaszlo OpenLaszlo Spis Treści 1 OpenLaszlo Co to jest? Historia Idea Architektura Jako Flash lub DHTML Jako servlet lub SOLO Jak to działa? Język LZX Struktura programu Skrypty Obiekty i klasy Atrybuty i metody

Bardziej szczegółowo

Analiza i projektowanie aplikacji Java

Analiza i projektowanie aplikacji Java Analiza i projektowanie aplikacji Java Modele analityczne a projektowe Modele analityczne (konceptualne) pokazują dziedzinę problemu. Modele projektowe (fizyczne) pokazują system informatyczny. Utrzymanie

Bardziej szczegółowo

Dokumentacja techniczna. Młodzieżowe Pośrednictwo Pracy

Dokumentacja techniczna. Młodzieżowe Pośrednictwo Pracy Dokumentacja techniczna Młodzieżowe Pośrednictwo Pracy Spis Treści 1. Widok ogólny architektury MPP... 3 2. Warstwy systemu... 5 3. Struktura systemu/komponentów... 7 3.1 Aplikacje... 7 3.2 Biblioteki...

Bardziej szczegółowo

Podyplomowe Studium Informatyki w Bizniesie Wydział Matematyki i Informatyki, Uniwersytet Łódzki specjalność: Tworzenie aplikacji w środowisku Oracle

Podyplomowe Studium Informatyki w Bizniesie Wydział Matematyki i Informatyki, Uniwersytet Łódzki specjalność: Tworzenie aplikacji w środowisku Oracle Podyplomowe Studium Informatyki w Bizniesie Wydział Matematyki i Informatyki, Uniwersytet Łódzki specjalność: Tworzenie aplikacji w środowisku Oracle EFEKTY KSZTAŁCENIA Wiedza Absolwent tej specjalności

Bardziej szczegółowo

Grupy pytań na egzamin magisterski na kierunku Informatyka (dla studentów niestacjonarnych studiów II stopnia)

Grupy pytań na egzamin magisterski na kierunku Informatyka (dla studentów niestacjonarnych studiów II stopnia) Grupy pytań na egzamin magisterski na kierunku Informatyka (dla studentów niestacjonarnych studiów II stopnia) WERSJA WSTĘPNA, BRAK PRZYKŁADOWYCH PYTAŃ DLA NIEKTÓRYCH PRZEDMIOTÓW Należy wybrać trzy dowolne

Bardziej szczegółowo

Materiały oryginalne: ZAWWW-2st1.2-l11.tresc-1.0kolor.pdf. Materiały poprawione

Materiały oryginalne: ZAWWW-2st1.2-l11.tresc-1.0kolor.pdf. Materiały poprawione Materiały oryginalne: ZAWWW-2st1.2-l11.tresc-1.0kolor.pdf Materiały poprawione Rozwiązanie zadania w NetBeans IDE 7.4: Jarosław Ksybek, Adam Miazio Celem ćwiczenia jest przygotowanie prostej aplikacji

Bardziej szczegółowo

SZKOLENIE TWORZENIE SYSTEMÓW

SZKOLENIE TWORZENIE SYSTEMÓW SZKOLENIE TWORZENIE SYSTEMÓW INFORMATYCZNYCH Z UŻYCIEM GROOVY I GRAILS KOD: JGR Strona 1 1 Opis Platforma Java EE to zbiór zaawansowanych narzędzi umożliwiających tworzenie systemów korporacyjnych. Jest

Bardziej szczegółowo

Grupy pytań na egzamin magisterski na kierunku Informatyka (dla studentów dziennych studiów II stopnia)

Grupy pytań na egzamin magisterski na kierunku Informatyka (dla studentów dziennych studiów II stopnia) Grupy pytań na egzamin magisterski na kierunku Informatyka (dla studentów dziennych studiów II stopnia) WERSJA WSTĘPNA, BRAK PRZYKŁADOWYCH PYTAŃ DLA NIEKTÓRYCH PRZEDMIOTÓW Należy wybrać trzy dowolne przedmioty.

Bardziej szczegółowo

REFERAT PRACY DYPLOMOWEJ

REFERAT PRACY DYPLOMOWEJ REFERAT PRACY DYPLOMOWEJ Temat pracy: Projekt i implementacja środowiska do automatyzacji przeprowadzania testów aplikacji internetowych w oparciu o metodykę Behavior Driven Development. Autor: Stepowany

Bardziej szczegółowo

Java jako język programowania

Java jako język programowania Java jako język programowania Interpretowany programy wykonują się na wirtualnej maszynie (JVM Java Virtual Machine) Składnia oparta o język C++ W pełni zorientowany obiektowo (wszystko jest obiektem)

Bardziej szczegółowo

Dokumentacja wstępna TIN. Rozproszone repozytorium oparte o WebDAV

Dokumentacja wstępna TIN. Rozproszone repozytorium oparte o WebDAV Piotr Jarosik, Kamil Jaworski, Dominik Olędzki, Anna Stępień Dokumentacja wstępna TIN Rozproszone repozytorium oparte o WebDAV 1. Wstęp Celem projektu jest zaimplementowanie rozproszonego repozytorium

Bardziej szczegółowo

Typy przetwarzania. Przetwarzanie zcentralizowane. Przetwarzanie rozproszone

Typy przetwarzania. Przetwarzanie zcentralizowane. Przetwarzanie rozproszone Typy przetwarzania Przetwarzanie zcentralizowane Systemy typu mainfame Przetwarzanie rozproszone Architektura klient serwer Architektura jednowarstwowa Architektura dwuwarstwowa Architektura trójwarstwowa

Bardziej szczegółowo

A Zasady współpracy. Ocena rozwiązań punktów punktów punktów punktów punktów

A Zasady współpracy. Ocena rozwiązań punktów punktów punktów punktów punktów A Zasady współpracy Ocena rozwiązań 3.0 25 40 punktów 3.5 41 65 punktów 4.0 66 80 punktów 4.5 81 100 punktów 5.0 101 130 punktów Warunki zaliczenia przedmiotu Student uzyska ocenę zaliczającą (3.0) o ile

Bardziej szczegółowo

REFERAT O PRACY DYPLOMOWEJ

REFERAT O PRACY DYPLOMOWEJ REFERAT O PRACY DYPLOMOWEJ Temat pracy: Projekt i budowa systemu zarządzania treścią opartego na własnej bibliotece MVC Autor: Kamil Kowalski W dzisiejszych czasach posiadanie strony internetowej to norma,

Bardziej szczegółowo

Przygotowanie do nowoczesnego programowania po stronie przeglądarki. (HTML5, CSS3, JS, wzorce, architektura, narzędzia)

Przygotowanie do nowoczesnego programowania po stronie przeglądarki. (HTML5, CSS3, JS, wzorce, architektura, narzędzia) Program szkolenia: Przygotowanie do nowoczesnego programowania po stronie przeglądarki (HTML5, CSS3, JS, wzorce, architektura, narzędzia) Informacje: Nazwa: Kod: Kategoria: Grupa docelowa: Czas trwania:

Bardziej szczegółowo

Tester oprogramowania 2014/15 Tematy prac dyplomowych

Tester oprogramowania 2014/15 Tematy prac dyplomowych Tester oprogramowania 2014/15 Tematy prac dyplomowych 1. Projekt i wykonanie automatycznych testów funkcjonalnych wg filozofii BDD za pomocą dowolnego narzędzia Jak w praktyce stosować Behaviour Driven

Bardziej szczegółowo

Modele danych walidacja widoki zorientowane na model

Modele danych walidacja widoki zorientowane na model Modele danych walidacja widoki zorientowane na model 1. Wprowadzenie Modele danych Modele danych w ASP.NET MVC to klasy znajdujące się w katalogu Models. Ich zadaniem jest mapowanie danych przesyłanych

Bardziej szczegółowo

Ewolucja projektowania aplikacji w PHP na bazie frameworka Symfony 2

Ewolucja projektowania aplikacji w PHP na bazie frameworka Symfony 2 Ewolucja projektowania aplikacji w PHP na bazie frameworka Symfony 2 Statyczne strony HTML Wczytanie statycznej strony HTML sprowadza się do odebrania żądania przez serwer, odnalezienia właściwego pliku

Bardziej szczegółowo

Plan. Aplikacja. Architektura aplikacji. Architektura aplikacji Tworzenie aplikacji Application Builder podstawy

Plan. Aplikacja. Architektura aplikacji. Architektura aplikacji Tworzenie aplikacji Application Builder podstawy Plan Podstawy narzędzia Application Builder, 2 budowa strony, kreatory Architektura Tworzenie Tworzenie formularza tabelarycznego Budowa strony 2 Architektura Aplikacja kolekcja stron połączonych ze sobą

Bardziej szczegółowo

OfficeObjects e-forms

OfficeObjects e-forms OfficeObjects e-forms Rodan Development Sp. z o.o. 02-820 Warszawa, ul. Wyczółki 89, tel.: (+48-22) 643 92 08, fax: (+48-22) 643 92 10, http://www.rodan.pl Spis treści Wstęp... 3 Łatwość tworzenia i publikacji

Bardziej szczegółowo

Aplikacje WWW - laboratorium

Aplikacje WWW - laboratorium Aplikacje WWW - laboratorium Serwlety Celem ćwiczenia jest przygotowanie kilku prostych serwletów ilustrujących możliwości tej technologii. Poszczególne ćwiczenia prezentują sposób przygotowania środowiska,

Bardziej szczegółowo

Informacje wstępne Autor Zofia Kruczkiewicz Wzorce oprogramowania 4

Informacje wstępne Autor Zofia Kruczkiewicz Wzorce oprogramowania 4 Utrwalanie danych zastosowanie obiektowego modelu danych warstwy biznesowej do generowania schematu relacyjnej bazy danych Informacje wstępne Autor Zofia Kruczkiewicz Wzorce oprogramowania 4 1. Relacyjne

Bardziej szczegółowo

EXSO-CORE - specyfikacja

EXSO-CORE - specyfikacja EXSO-CORE - specyfikacja System bazowy dla aplikacji EXSO. Elementy tego systemu występują we wszystkich programach EXSO. Może on ponadto stanowić podstawę do opracowania nowych, dedykowanych systemów.

Bardziej szczegółowo

Zaawansowane aplikacje internetowe - laboratorium Web Services (część 1).

Zaawansowane aplikacje internetowe - laboratorium Web Services (część 1). Zaawansowane aplikacje internetowe - laboratorium Web Services (część 1). Celem ćwiczenia jest przygotowanie prostej aplikacji internetowej wykorzystującej technologię usług sieciowych (ang. Web Services).

Bardziej szczegółowo

Zagadnienia projektowania aplikacji J2EE

Zagadnienia projektowania aplikacji J2EE 211 Zagadnienia projektowania aplikacji J2EE Maciej Zakrzewicz Maciej.Zakrzewicz@cs.put.poznan.pl http://www.cs.put.poznan.pl/mzakrzewicz/ Plan rozdziału 212 Wstęp Techniki projektowe: Wprowadzenie modułu

Bardziej szczegółowo

2) W wyświetlonym oknie należy zaznaczyć chęć utworzenia nowej aplikacji (wygląd okna może się różnić od powyższego); kliknąć OK

2) W wyświetlonym oknie należy zaznaczyć chęć utworzenia nowej aplikacji (wygląd okna może się różnić od powyższego); kliknąć OK Zaawansowane aplikacje internetowe EJB 2 Celem tego laboratorium jest pokazanie, w jaki sposób aplikacje stworzone w różnych technologiach mogą korzystać z funkcjonalności udostępnianej przez komponenty

Bardziej szczegółowo

Dotacje na innowacje. Inwestujemy w waszą przyszłość.

Dotacje na innowacje. Inwestujemy w waszą przyszłość. PROJEKT TECHNICZNY Implementacja Systemu B2B w firmie Lancelot i w przedsiębiorstwach partnerskich Przygotowane dla: Przygotowane przez: Lancelot Marek Cieśla Grzegorz Witkowski Constant Improvement Szkolenia

Bardziej szczegółowo

Spring Framework - wprowadzenie i zagadnienia zaawansowane

Spring Framework - wprowadzenie i zagadnienia zaawansowane Program szkolenia: Spring Framework - wprowadzenie i zagadnienia zaawansowane Informacje ogólne Nazwa: Kod: Kategoria: Grupa docelowa: Czas trwania: Forma: Spring Framework - wprowadzenie i zagadnienia

Bardziej szczegółowo

XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery

XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery http://xqtav.sourceforge.net XQTav - reprezentacja diagramów przepływu prac w formacie SCUFL przy pomocy XQuery dr hab. Jerzy Tyszkiewicz dr Andrzej Kierzek mgr Jacek Sroka Grzegorz Kaczor praca mgr pod

Bardziej szczegółowo

SOP System Obsługi Parkingów

SOP System Obsługi Parkingów SOP System Obsługi Parkingów JEE i Android Marcin Tatjewski Tomasz Traczyk Grzegorz Zieliński Paweł Borycki 5 listopada 2009 www.sopark.pl Plan prezentacji Java Platform, Enterprise Edition (JEE) Wstęp

Bardziej szczegółowo

Architektura nowoczesnych aplikacji internetowych

Architektura nowoczesnych aplikacji internetowych Architektura nowoczesnych aplikacji internetowych Lech Madeyski Michał Stochmiałek Wydziałowy Zakład Informatyki Wydział Informatyki i Zarządzania Politechnika Wrocławska Krajowa Konferencja Inżynierii

Bardziej szczegółowo

Facelets ViewHandler

Facelets ViewHandler JSF i Facelets Wprowadzenie JSP (JavaServer Pages) są natywną i najczęściej używaną technologią do tworzenia warstwy prezentacyjnej dla JSF (JavaServer Faces) Istnieją alternatywne technologie opisu wyglądu

Bardziej szczegółowo

Webowy generator wykresów wykorzystujący program gnuplot

Webowy generator wykresów wykorzystujący program gnuplot Uniwersytet Mikołaja Kopernika Wydział Fizyki, Astronomii i Informatyki Stosowanej Marcin Nowak nr albumu: 254118 Praca inżynierska na kierunku informatyka stosowana Webowy generator wykresów wykorzystujący

Bardziej szczegółowo

SOA Web Services in Java

SOA Web Services in Java Wydział Informatyki i Zarządzania Wrocław,16 marca 2009 Plan prezentacji SOA 1 SOA 2 Usługi Przykłady Jak zacząć SOA Wycinek rzeczywistości Problemy zintegrowanych serwisów : Wycinek Rzeczywistości Zacznijmy

Bardziej szczegółowo

Dokument Detaliczny Projektu

Dokument Detaliczny Projektu Dokument Detaliczny Projektu Dla Biblioteki miejskiej Wersja 1.0 Streszczenie Niniejszy dokument detaliczny projektu(ddp) przedstawia szczegóły pracy zespołu projektowego, nad stworzeniem aplikacji bazodanowej

Bardziej szczegółowo

REFERAT O PRACY DYPLOMOWEJ

REFERAT O PRACY DYPLOMOWEJ REFERAT O PRACY DYPLOMOWEJ Temat pracy: Projekt i realizacja elektronicznego dziennika ocen ucznia Autor: Grzegorz Dudek wykonanego w technologii ASP.NET We współczesnym modelu edukacji, coraz powszechniejsze

Bardziej szczegółowo

Wykład dla studentów Informatyki Stosowanej UJ 2012/2013

Wykład dla studentów Informatyki Stosowanej UJ 2012/2013 e-biznes Wykład dla studentów Informatyki Stosowanej UJ 2012/2013 Michał Cieśla pok. 440a, email: michal.ciesla@uj.edu.pl konsultacje: środy 10-12 http://users.uj.edu.pl/~ciesla/ 1 Literatura B. Burke,

Bardziej szczegółowo

Poznań Java User Group 2005. Java Server Faces. Wprowadzenie (Fakty i Mity)

Poznań Java User Group 2005. Java Server Faces. Wprowadzenie (Fakty i Mity) Poznań Java User Group 2005 Java Server Faces Wprowadzenie (Fakty i Mity) Plan prezentacji Ograniczenia szkieletów WWW Podstawowe elementy JSF JSF krok po kroku: Warstwa wizualna Obsługa zdarzeń Nawigacja

Bardziej szczegółowo

WPROWADZENIE DO JĘZYKA JAVA

WPROWADZENIE DO JĘZYKA JAVA WPROWADZENIE DO JĘZYKA JAVA programowanie obiektowe KRÓTKA HISTORIA JĘZYKA JAVA KRÓTKA HISTORIA JĘZYKA JAVA 1991 - narodziny języka java. Pierwsza nazwa Oak (dąb). KRÓTKA HISTORIA JĘZYKA JAVA 1991 - narodziny

Bardziej szczegółowo

Programowanie w Sieci Internet JSP ciąg dalszy. Kraków, 9 stycznia 2015 r. mgr Piotr Rytko Wydział Matematyki i Informatyki

Programowanie w Sieci Internet JSP ciąg dalszy. Kraków, 9 stycznia 2015 r. mgr Piotr Rytko Wydział Matematyki i Informatyki Programowanie w Sieci Internet JSP ciąg dalszy Kraków, 9 stycznia 2015 r. mgr Piotr Rytko Wydział Matematyki i Informatyki Co dziś będziemy robić JSP tags, Używanie tagów, Custom tags, JSP objests, Obiekty

Bardziej szczegółowo

Programowanie komponentowe 5

Programowanie komponentowe 5 Budowa warstwy klienta w architekturze typu klient-serwer zbudowanych z komponentów typu EE - klient desktopowy i internetowy. Zastosowanie komponentów opartych na technologii EJB 3.2. na podstawie https://docs.oracle.com/javaee/7/jeett.pdf

Bardziej szczegółowo

Java Enterprise Edition spotkanie nr 1. Sprawy organizacyjne, wprowadzenie

Java Enterprise Edition spotkanie nr 1. Sprawy organizacyjne, wprowadzenie Java Enterprise Edition spotkanie nr 1 Sprawy organizacyjne, wprowadzenie 1 Informacje organizacyjne Program: Co będzie na tym wykładzie, a czego nie będzie? apteka rolnictwo Java Enterprise Edition vs

Bardziej szczegółowo

Szkolenie wycofane z oferty. Program szkolenia: Enterprise Java Beans 3.0/3.1

Szkolenie wycofane z oferty. Program szkolenia: Enterprise Java Beans 3.0/3.1 Szkolenie wycofane z oferty Program szkolenia: Enterprise Java Beans 3.0/3.1 Informacje: Nazwa: Enterprise Java Beans 3.0/3.1 Kod: Java-EE-EJB Kategoria: Java EE Grupa docelowa: developerzy Czas trwania:

Bardziej szczegółowo

JBoss Seam: framework nowej generacji. Copyright Piotr Kochański & Erudis, www.erudis.pl

JBoss Seam: framework nowej generacji. Copyright Piotr Kochański & Erudis, www.erudis.pl JBoss Seam: framework nowej generacji Wstęp Agenda Wstęp Elementy JBoss Seam: JSF + EJB3 +...... brakujące ogniwo Możliwości JBoss Seam Przykład zastosowania uproszczenie aplikacji konteksty, konwersacje

Bardziej szczegółowo

Załącznik 2 utworzenie projektu

Załącznik 2 utworzenie projektu Załącznik 2 utworzenie projektu W poniższym załączniku przedstawione zostaną instrukcje utworzenia projektu w środowisku Eclipse, na bazie którego będzie rozbudowywana aplikacja. Przedstawiony zostanie

Bardziej szczegółowo

Programowanie obiektowe zastosowanie języka Java SE

Programowanie obiektowe zastosowanie języka Java SE Programowanie obiektowe zastosowanie języka Java SE Wstęp do programowania obiektowego w Javie Autor: dr inŝ. 1 Java? Java język programowania obiektowo zorientowany wysokiego poziomu platforma Javy z

Bardziej szczegółowo

Wzorce Strukturalne. Adapter: opis. Tomasz Borzyszkowski

Wzorce Strukturalne. Adapter: opis. Tomasz Borzyszkowski Adapter: opis Wzorce Strukturalne Tomasz Borzyszkowski Alternatywna nazwa: Wrapper (opakowanie) Rola obiektu Adapter: pełni wobec Klienta rolę otoczki, która umożliwia przetłumaczenie jego żądań na protokół

Bardziej szczegółowo

Wprowadzenie. Narzędzia i środowiska programistyczne. Laboratorium 1. Prowadzący: Kierunek: Semestr: Rok: Tomasz Gądek Informatyka Zimowy 2

Wprowadzenie. Narzędzia i środowiska programistyczne. Laboratorium 1. Prowadzący: Kierunek: Semestr: Rok: Tomasz Gądek Informatyka Zimowy 2 Państwowa Wyższa Szkoła Zawodowa w Tarnowie Zakład Informatyki Narzędzia i środowiska programistyczne Laboratorium 1 Wprowadzenie Prowadzący: Kierunek: Semestr: Rok: Informatyka Zimowy 2 O Sobie Od 2014

Bardziej szczegółowo

Java w Internecie - czy to ma sens? ;)

Java w Internecie - czy to ma sens? ;) Java w Internecie - czy to ma sens? ;) Piotr Dziubecki PCSS Agenda Wstęp Zastosowania Javy w polskim Internecie Do czego Java nam się nie przyda? Zaczynamy z Javą: - technologie, - trendy, - koszty. Podsumowanie

Bardziej szczegółowo

Serwery aplikacji. dr Radosław Matusik. radmat

Serwery aplikacji. dr Radosław Matusik.   radmat www.math.uni.lodz.pl/ radmat EL - Expression Language Załóżmy, że mamy klasę Pracownik, której atrybutem jest PESEL. Załóżmy dalej, że w atrybucie sesji zalogowany przechowujemy obiekt aktualnie zalogowanego

Bardziej szczegółowo

Zakres tematyczny dotyczący kursu PHP i MySQL - Podstawy pracy z dynamicznymi stronami internetowymi

Zakres tematyczny dotyczący kursu PHP i MySQL - Podstawy pracy z dynamicznymi stronami internetowymi Zakres tematyczny dotyczący kursu PHP i MySQL - Podstawy pracy z dynamicznymi stronami internetowymi 1 Rozdział 1 Wprowadzenie do PHP i MySQL Opis: W tym rozdziale kursanci poznają szczegółową charakterystykę

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Laboratorium 11 - przegląd wybranych wzorców mgr inż. Krzysztof Szwarc krzysztof@szwarc.net.pl Sosnowiec, 24 maja 2017 1 / 38 mgr inż. Krzysztof Szwarc Programowanie obiektowe Wzorce

Bardziej szczegółowo

5.14 JSP - Przykład z obiektami sesji... 83 5.15 Podsumowanie... 84 5.16 Słownik... 85 5.17 Zadanie... 86

5.14 JSP - Przykład z obiektami sesji... 83 5.15 Podsumowanie... 84 5.16 Słownik... 85 5.17 Zadanie... 86 Spis treści 1 Wprowadzenie - architektura, protokoły, system WWW... 1 1.1 Wstęp.................................................. 1 1.2 Ważniejsze daty......................................... 2 1.3 Protokoły

Bardziej szczegółowo

Technologie dla aplikacji klasy enterprise. Wprowadzenie. Marek Wojciechowski

Technologie dla aplikacji klasy enterprise. Wprowadzenie. Marek Wojciechowski Technologie dla aplikacji klasy enterprise Wprowadzenie Marek Wojciechowski Co oznacza enterprise-ready? Bezpieczeństwo Skalowalność Stabilność Kompatybilność wstecz Wsparcie Dokumentacja Łatwość integracji

Bardziej szczegółowo

Nowe mechanizmy w wersji 3 Java Card. Mateusz LESZEK (138775)

Nowe mechanizmy w wersji 3 Java Card. Mateusz LESZEK (138775) Nowe mechanizmy w wersji 3 Java Card Mateusz LESZEK (138775) Plan prezentacji 1. Java Card 3 2. Nowe mechanizmy w Java Card 3.X 3. Edycje Java Card 3.X Classic vs Connected Karty inteligentne wprowadzone

Bardziej szczegółowo

Spring Web MVC, Spring DI

Spring Web MVC, Spring DI Państwowa Wyższa Szkoła Zawodowa w Tarnowie Zakład Informatyki Laboratorium 5 Spring Web MVC, Spring DI Prowadzący: Kierunek: Semestr: Rok: Informatyka Zimowy 2 Technologie Technologie / narzędzia będące

Bardziej szczegółowo

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ),

PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH. KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ), PLAN WYNIKOWY PROGRAMOWANIE APLIKACJI INTERNETOWYCH KL IV TI 6 godziny tygodniowo (6x15 tygodni =90 godzin ), Program 351203 Opracowanie: Grzegorz Majda Tematyka zajęć 2. Przygotowanie środowiska pracy

Bardziej szczegółowo

INSTRUKCJA obsługi certyfikatów

INSTRUKCJA obsługi certyfikatów INSTRUKCJA obsługi certyfikatów dla użytkownika bankowości internetowej Pocztowy24 z wybraną metodą autoryzacji Certyfikat Spis treści 1. Wstęp... 3 1.1 Wymagania techniczne... 3 2. Certyfikat jako jedna

Bardziej szczegółowo

Wprowadzenie do programowania aplikacji mobilnych

Wprowadzenie do programowania aplikacji mobilnych Wprowadzenie do programowania aplikacji mobilnych dr Przemysław Juszczuk dr Przemysław Juszczuk Trochę historii Idea wzorców projektowych wywodzi się jeszcze z wczesnych lat osiemdziesiątych ubiegłego

Bardziej szczegółowo