Była okazja by poznać podstawy JSP oraz Strutsa. Lecz na tym nie koniec, bowiem świat Javy obfituje także w inne różne frameworki. Ciekawym wyborem może okazać się Tapestry, czyli framework rozwijany, podobnie jak Struts, pod skrzydłami fundacji Apache. Jednak w odróżnieniu od Strutsa, prezentuje on całkowicie odmienne podejście do tworzenia aplikacji internetowych.
Tapestry opiera się na komponentach osadzanych na stronach internetowch. Jest to więc podejście podobne do tego, jakie realizuje framework technologii .Net Microsoftu czy stworzony dla Javy JSF. Jest jednak rozwiązaniem znacznie od JSF prostszym.
Tapesty nie jest tak popularny jak Struts czy nawet stosunkowo młody JSF. Nie znaczy to jednak, że się nie sprawdził. W oparciu o Tapestry funkcjonuje wiele witryn, w tym między innymi znany chyba każdemu programiście Java wortal TheServerSide.com oraz poświęcony technologii .Net serwis TheServerSide.net.
Zaczynamy
Zakładam, że masz już zainstalowaną i skonfigurowaną
Jave (JDK). Dodatkowo potrzebny
będzie Tomcat, czyli kontener servletów. Możesz
go pobrać ze strony http://tomcat.apache.org.
Tomcat w wersji dla systemu Windows dostarczany
jest wraz z programem instalacyjnym, dzięki czemu
jego wstępna konfiguracja jest bardzo prosta. Po
uruchomieniu instalatora zobaczysz okno widoczne
na rysunku 3. Kliknij na przycisk Next.
W następnym oknie (rysunek 4) zapoznaj się
z warunkami licencji i kliknij przycisk I Agree w celu
jej zatwierdzenia. W kolejnym oknie (rysunek
5) możesz wybrać, które elementy Tomcata mają
zostać zainstalowane. Spokojnie możesz pozostawić
domyślne propozycje i zatwierdzić wybór
przyciskiem Next.
Teraz musisz wybrać katalog, w którym zostanie
zainstalowany Tomcat (rysunek 6). Najczęściej
domyślna instalacja w katalogu Program Files jest
poprawna, kliknij więc przycisk Next.
Przed rozpoczęciem kopiowania plików musisz
jeszcze ustalić port, na jakim ma nasłuchiwać Tomcat,
a także nazwę i hasło administratora (rysunek
7). Port pozostawiamy domyślny – 8080. Nazwę
i hasło administratora możesz zmienić wedłu
swojego uznania. Na końcu zatwierdź wprowadzone
zmiany przyciskiem Next.
Ostatnim krokiem przed przekopiowaniem plików jest wskazanie
miejsca, gdzie zainstalowano wirtualną maszynę
Java (JRE) – zobacz rysunek 8. Instalator najczęściej
sam poprawnie odnajduje jej położenie. Jeśli tak
się stało i w twoim przypadku, kliknij Install. Jeśli
nie, ręcznie wskaż instalatorowi położenie JRE na
swoim komputerze. Pamiętaj jednak, że problem
z odnalezieniem JRE przez instalator może sygnalizować
błędną instalację Javy.
W tym momencie nastąpi instalacja Tomcata
(rysunek 9). Po jej zakończeniu, w oknie z rysunku
10, kliknij przycisk Finish. Spowoduje to
uruchomienie Tomcata. Jeśli wszystko przebiegło
pomyślnie, ikonka Tomcata powinna pojawić się na
pasku Start, tuż obok zegara, tak jak pokazano na
rysunku 11.
Po zainstalowaniu Tomcata należy jeszcze zainstalować
Anta, czyli pracowitą mrówkę. Ant służy
między innymi do automatyzacji procesu kompilacji
i pakowania do archiwum {stala}jar/war/ear aplikacji{/stala}
pisanych w Javie. Anta możesz pobrać ze strony
domowej projektu http://ant.apache.org.
Po pobraniu archiwum rozpakuj je do katalogu,
w którym chcesz mieć zainstalowanego Anta.
Musisz teraz odpowiednio ustawić ścieżkę PATH
i zmienną środowiskową ANT_HOME (oczywiście
nie możesz zapomnieć o ustawieniu odpowiednich
ścieżek i zmiennych odpowiedzialnych za poprawne
działanie JDK, zakładam jednak, że JDK masz już
zainstalowane i poprawnie skonfigurowane).
Ścieżka PATH powinna wskazywać na podkatalog
bin, znajdujący się w katalogu głównym Anta.
Zmienna {stala}ANT_HOME{/stala} powinna natomiast zawierać
ścieżkę do katalogu głównego Anta.
A oto po kolei sposób ustawienia obu tych
parametrów w systemie Windows:
- przejdź do panelu sterowania,
- kliknij ikonę System,
- w oknie Właściwości systemu kliknij zakładkę Zaawansowane,
- w polu Zmienne systemowe odszukaj zmienną Path,
- kliknij przycisk Edytuj,
- na końcu linijki znajdującej się w polu Wartość zmiennej wpisz ścieżkę do katalogu bin, znajdującego się w katalogu głównym Anta, poprzedzając ją średnikiem (np. {stala}c:\\apache-ant-1.6.5\\bin{/stala}),
- zatwierdź wprowadzone zmiany, klikając na przycisku OK.
Do poprawnego działania Anta musisz jeszcze
ustawić zmienną {stala}ANT_PATH{/stala}. W tym celu w polu
Zmienne systemowe wykonaj następujące operacje:
- kliknij przycisk Nowa,
- spowoduje to otwarcie okna, w polu Nazwa zmiennej wpisz ANT_HOME,
- w polu Wartość zmiennej podaj ścieżkę do katalogu głównego, w którym znajduje się Ant(np. {stala}c:\\apache-ant-1.6.5{/stala}),
- Kliknij OK, aby zatwierdzić wprowadzoną zmienną.
Oba kroki (modyfikację zmiennej Path oraz
tworzenie zmiennej ANT_HOME) przedstawione
zostały na rysunkach 14 oraz 15.
Jeśli wszytko wykonałeś poprawnie, po
restarcie komputera wydaj z linii poleceń komendę
ant. W jej wyniku powinieneś ujrzeć komunikat
z rysunku 16. Będzie to oznaczało, że Ant działa
prawidłowo.
I na koniec przygotowań nasz dzisiejszy
bohater: Tapestry. Tapestry możesz pobrać z strony
domowej frameworka, znajdującej się pod adresem
http://tapestry.apache.org.
Tapestry udostępniane jest w postaci
archiwum zip. Tak jak poprzednio zrobiłeś to
w przypadku Anta, tak i teraz rozpakuj archiwum.
Zawiera ono katalog lib. W nim znajduje się
wszytko, co nas interesuje i będzie potrzebne do
budowania aplikacji.
Witaj świecie!
Zbudujmy teraz dwie wersje najbardziej znanej
wśród programistów aplikacji \”edukacyjnej\”, czyli
programu wyświetlającego napis \”Witaj świecie!\”
(Hello World!). Pierwsza wersja niech będzie
klasycznym Hello World. Zanim jednak zaczniemy,
zapoznaj się ze skryptem {stala}build.xml{/stala}, opisującym
zadania, jakie ma dla nas wypełniać Ant.
Oto on:
Jako że nie Ant jest bohaterem tego artykułu,
opiszemy jedynie pokrótce działanie skryptu. Dzięki
niemu, Ant zautomatyzuje takie zadania jak kompilacja
programu oraz tworzenie archiwum war wraz
ze wszystkimi niezbędnymi plikami (klasami, stronami
internetowymi, konfiguracją i bibliotekami).
Nie jest on zbyt skomplikowany i łatwo zrozumieć
zasadę jego działania. W razie potrzeby skorzystaj
z dokumentacji do Anta, opublikowanej na stronie
domowej projektu (http://ant.apache.org).
Czas ustalić drzewo katalogów naszych
projektów. Zawsze będzie ono podobne, a jego
wygląd jest ściśle powiązane ze skryptem {stala}build.xml{/stala}.
Oto, co będzie się znajdowało w powyższych
katalogach:
- nazwa projektu/src/java – pliki *.java (oczywiście w podkatalogach odwzorowujących pakiety),
- nazwa projektu/lib – biblioteki (w naszym przypadku cała zawartość katalogu lib z archiwum Tapestry),
- nazwa projektu/webapp/WEB-INF – pliki HTML oraz pliki konfiguracyjne aplikacji (web.xml,*.pages, *.html),
- nazwa projektu – skrypt Anta build.xml
Zacznijmy więc pisanie kodu. Całość aplikacji
w Tapestry rozpoczyna się od strony HTML. Nie
jest to tak, jak w przypadku Struts skrypt JSP,
lecz zwykła strona HTML z nieco zmodyfikowanymi
znacznikami (wzbogaconymi o nowe parametry).
Dzięki temu strona taka jest poprawnie wyświetlana
przez większość edytorów do wizualnej pracy
nad kodem HTML (tzw. edytorów WYSIWYG).
Kod naszej pierwszej wersji strony Hello World jest
zatem bardzo prosty:
Witaj!
Witaj Janie Kowalski
Myślisz sobie pewnie w tej chwili: \”Hej hej,
ale miało być Witaj świecie!, a jest Witaj Janie
Kowalski!\”. I tak, i nie. Sama strona podczas edycji
z poziomu programów WYSIWYG czy przy bezpośrednim
otworzeniu jej w przeglądarce rzeczywiście
wyświetli napis \”Witaj Janie Kowalski\”. Lecz już za chwilkę
zadbamy o jej poprawną treść.
W Tapestry do każdej strony (każdego widoku)
tworzy się specjalny plik z opisem klasy za nią
odpowiedzialnej oraz (jak zobaczysz w kolejnym
przykładzie) z jej komponentami. Plik taki ma
nazwę analogiczną do strony, której dotyczy, tyle
że z rozszerzeniem .page:
Jak widzisz, jest to plik XML, w tym przypadku
z jednym znacznikiem. Określa on klasę, która
jest odpowiedzialna za nasz widok – tutaj jest to
{stala}pl.staniszczak.tapestry.helloworld.Home{/stala}:
package pl.staniszczak.tapestry.helloworld;
import org.apache.tapestry.html.BasePage;
abstract public class Home extends BasePage {
public String getName() {
return \"Świecie!\";
}
}
Nasza klasa jest abstrakcyjna, dziedziczy po
BasePage oraz dostarcza jedną metodę {stala}getName(){/stala}.
To pierwsze nie powinno cię martwić. Tapestry zadba o stworzenie na jej bazie odpowiedniej, pełnowartościowej klasy. Jak się przekonasz, Tapestry może za programistę wygenerować bardzo wiele
kodu, i to bez dodatkowych ustawień konfiguracji. Wróćmy na chwilkę do poniższego fragmentu naszej strony HTML:
Witaj Janie Kowalski
Został tutaj użyty znacznik {html}{/html}. Jest to
co prawda standardowy znacznik języka HTML,
jednak w naszym przykładzie posiada on nietypowy
parametr jwcid (Java Web Component ID).
Parametr ten określa komponent Tapestry, w tym
przypadku komponent Insert, wypełniający znacznik
{html}{/html} zwartością określoną przez parametr
value. Wartość ta jest zapytaniem języka ognl,
służącego do przeszukiwania obiektów (więcej na
jego temat znajdziesz na stronie http://www.ognl.org):
ognl:name
Powyższe zapytanie name powoduje odczytanie
zmiennej name, a dokładniej wywołanie
gettera {stala}getName{/stala} z obiektu klasy danego widoku,
a więc naszej klasy Home.
Co jeszcze? Nic! To już cały program Hello
World! Potrzebny jest jeszcze plik {stala}web.xml{/stala}.
Jego kod prezentujemy poniżej. Nie będziemy tutaj zajmować się jego opisem, dla wszystkich
naszych przykładów z tego artykuły będzie on
identyczny:
Witaj Swiecie
redirect
org.apache.tapestry.RedirectFilter
redirect
/
hello
org.apache.tapestry.ApplicationServlet
0
hello
/app
5
Plik web.xml został dokładniej opisany w artykule
o JSP(http://serwis.magazynyinternetowe.pl/artykul/139,1,796,jsp_-_swiat_nie_konczy_sie_na_php.html). Tak więc
teraz pozostało już tylko skompilować aplikację,
utworzyć z niej archiwum war i wdrożyć ją w kontenerze
servletów. Dwa pierwsze kroki wykona
za nas Ant. Wystarczy, że z poziomu linii poleceń
przejdziesz do katalogu projektu, a następnie
wydasz polecenie ant – rysunek 17.
Skopiuj plik archiwum war z podkatalogu
target (w katalogu projektu) do katalogu webapps
Tomcata. Następnie zrestartuj go.
W następnej kolejności uruchom przeglądarkę
i wpisz adres {stala}http://localhost:8080/helloworld{/stala}. Po
chwili powinieneś zobaczyć stronę widoczną na
rysunku 18.
Hello… Jak Ci na imię?
A może by tak zamiast całego świata przywitać
użytkownika programu? Potrzebny więc będzie
formularz, w którym osobę odwiedzającą stronę zapytamy
o imię, a następnie wyświetlimy powitanie.
Skrypty {stala}build.xml{/stala} oraz {stala}web.xml{/stala} pozostawiamy
bez zmiany. Resztę piszemy od nowa. Nasza strona
{stala}Home.html{/stala} będzie tym razem zawierała prosty
formularz:
Witaj!
Zanim przejdziemy do jej omówienia, przenalizuj
jeszcze konfigurację z pliku Home.page:
Jak pamiętasz, parametr jwcid w znacznikach
HTML określa komponent. Tym razem komponenty
zostały skonfigurowane w pliku Home.page.
Komponent helloForm jest typu Form:
Oznacza to, że generujemy znacznik formularza.
Tapestry na swoje potrzeby wygeneruje tutaj odpowiedni
kod. Z formularzem wiążemy akcję (listenera
– nasłuchiwacza), która ma zostać wykonana
po wysłaniu formularza. W naszym przypadku jest
to metoda {stala}onOk(){/stala}.
Drugi komponent ma jwcid name:
Komponent ten generuje pole tekstowe ({html}
jest ze zmiennej name, czyli wywoływany jest
getter {stala}getName(){/stala}. Odszukaj teraz oba komponenty
w kodzie strony HTML i zobacz, w jaki sposób
zostały tam użyte.
A oto nowa klasa Home.java:
package pl.staniszczak.tapestry.helloworld;
import org.apache.tapestry.html.BasePage;
import org.apache.tapestry.IPage;
abstract public class Home extends BasePage {
private String name;
abstract public Result getResultPage();
public String getName() {
return \"Janie Kowalski\";
}
public void setName(String name) {
this.name = name;
}
public IPage onOk() {
Result resultPage = getResultPage();
resultPage.setName(name);
return resultPage;
}
}
Większość kodu jest bardzo prosta i wręcz
oczywista. Tapestry po wysłaniu formularza sam automatycznie
ustawia wartość odpowiednich zmiennych
za pomocą setterów – tu metodą {stala}setName(){/stala}.
Mimo to zastanawiasz się pewnie, co robi {stala}onOk(){/stala}
oraz co to za abstrakcyjna metoda {stala}getResultPage(){/stala}?
Przyjrzyjmy się stronie wyświetlającej powitanie
użytkownika naszej aplikacji, a wszystko szybko
stanie się jasne. Oto strona {stala}Result.html{/stala}:
Witaj!
Nazywasz się . Witaj!
Kod wygląda znajomo, prawda? Konfiguracja
{stala}Result.page{/stala} także jest niemal identyczna z tą
z pierwszego przykładu:
Kod {stala}Result.java{/stala} jest jednak już nieco inny.
Doszedł {stala}setter setName(){/stala}:
package pl.staniszczak.tapestry.helloworld;
import org.apache.tapestry.html.BasePage;
abstract public class Result extends BasePage {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Wróćmy teraz do klasy Home. W konfiguracji
strony Home.page znajdowała się linijka:
Oznaczała ona, że chcesz pod nazwą resultPage
w klasie Home mieć dostęp do obiektu widoku
Result. Tutaj o tworzenie odpowiedniego widoku
nie trzeba się martwić. Wystarczy w klasie Home
dostarczyć abstrakcyjną metodę {stala}getResultPage(){/stala}.
Tapestry sam już dostarczy odpowiednią jej
implementację, zwracającą obiekt naszego widoku
Result (a więc klasy Result).
Metoda {stala}onOk(){/stala} korzysta właśnie z tej metody:
public IPage onOk() {
Result resultPage = getResultPage();
resultPage.setName(name);
return resultPage;
}
Pobiera ona obiekt klasy Result, a następnie
korzystając z settera, ustawia wartość jej zmiennej
name (jak pamiętasz, wartość zmiennej name klasy
Home pochodzi z danych wpisanych w formularzu).
Na końcu zwraca obiekt Result, informując
Tapestry o tym, że ma wyświetlić widok Result.
I to tyle? Dwie strony HTML z przyporządkowanymi
do nich plikami *.page oraz kodem
Java. Skompiluj i utwórz na ich podstawie tak
jak poprzednio archiwum war oraz wdróż je
w Tomcacie. Po jego restarcie odśwież stronę
Hello World.
Kod wydaje się prosty, prawda? A co powiesz
na skrócenie go jeszcze bardziej? Niech Tapestry
sam zadba o wygenerowanie wszystkiego, co tylko
potrafi. A potrafi wygenerować za nas wszystkie
gettery i settery. Oto nowa klasa Home.class:
package pl.staniszczak.tapestry.helloworld;
import org.apache.tapestry.html.BasePage;
import org.apache.tapestry.IPage;
abstract public class Home extends BasePage {
abstract public Result getResultPage();
abstract public String getName();
public IPage onOk() {
Result resultPage = getResultPage();
resultPage.setName(getName());
return resultPage;
}
}
Jak widzisz, metoda {stala}setName(){/stala} została usunięta,
zaś metoda {stala}getName(){/stala} zamieniona na abstrakcyjną.
Dlaczego? Metodę {stala}setName(){/stala} Tapestry musi
wygenerować w celu zapamiętania danej name
przekazanej z formularza. Metoda {stala}getName(){/stala} nie
jest jednak potrzebna. Jeśli chcesz, aby była ona
wygenerowana, musisz utworzyć metodę abstrakcyjną
o odpowiedniej nazwie.
Zauważ też, że trzeba było delikatnie zmodyfikować
metodę {stala}onOk(){/stala}. Jako że nie mamy już
w klasie zmiennej o nazwie name, w linijce:
resultPage.setName(getName());
trzeba użyć wygenerowanego przez Tapestry
gettera.
Po obcięciach jeszcze prostsza staje się klasa
Result:
package pl.staniszczak.tapestry.helloworld;
import org.apache.tapestry.html.BasePage;
abstract public class Result extends BasePage {
abstract public void setName(String name);
}
Tworzymy tylko metodę abstrakcyjną {stala}setName(){/stala},
a na tej podstawie Tapestry stworzy za nas
także metodę {stala}getName(){/stala}.
Tak zmodyfikowany kod da się już skompilować
i uruchomić, stracimy jednak domyślną wartość
pola tekstowego \”Jan Kowalski\”. Dodaj jednak
w pliku konfiguracyjnym Home.page linijkę:
Ustawi ona domyślną wartość komponentu
name na napis (literal) Jan Kowalski.
I co dalej?
Mamy nadzieję, że nawet tak prosty przykład
jak Hello World zdołał zainteresować cię ciekawym
frameworkiem, jakim jest Tapestry. Ma on swoje
zalety i wady. Część zalet przeradza się w pewnych
sytuacjach w wady. Na przykład automatyczne
generowanie klas na podstawie klas abstrakcyjnych
bardzo ułatwia pracę, ale zarazem utrudnia,
a wręcz niejednokrotnie uniemożliwia ich testowane
za pomocą testów jednostkowych.
W Tapestry drzemią olbrzymie możliwości.
Framework wciąż się rozwija i jest używany
w praktyce. Szkoda, że nie zdobył takiej popularności
jak Struts, jednak skoro sprawdza się na
TheSerwerSide, którą odwiedza w każdej minucie
olbrzymia liczba internautów, sprawdzi się w większości
poważnych zastosowań.