You are on page 1of 26

IDZ DO

PRZYKADOWY ROZDZIA
SPIS TRECI

KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG

TWJ KOSZYK
DODAJ DO KOSZYKA

CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK

CZYTELNIA
FRAGMENTY KSIEK ONLINE

Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl

Spring. Zapiski
programisty
Autorzy: Bruce A. Tate, Justin Gehtland
Tumaczenie: Piotr Rajca
ISBN: 83-246-0336-0
Tytu oryginau: Spring: A Developers Notebook
Format: B5, stron: 272

Przyspiesz tworzenie aplikacji w Javie


Upro okrelanie zalenoci pomidzy klasami
Zastosuj narzdzie Hibernate do usprawnienia komunikacji z bazami danych
Wykorzystaj moliwoci programowania aspektowego
Technologia J2EE miaa w zaoeniu by prosta i szybka w uytkowaniu. Praktyka
jednak okazaa si daleka od teorii. Mozolne tworzenie aplikacji wykorzystujcych
dziesitki interfejsw poczonych wzajemnymi zalenociami, setki deskryptorw
wdroenia oraz plikw pomocniczych spowodowao, e zaczto poszukiwa rozwiza
alternatywnych. Jednym z nich okaza si framework Spring, zyskujcy coraz wiksz
popularno wrd programistw Javy. Spring jest znacznie duo prostszy od wielu
alternatywnych rozwiza J2EE, znacznie uatwia testowanie aplikacji, i pozwala na
usuwanie zalenoci z kodu oraz oddzielanie ich od serwera aplikacji. Spring umoliwia
rwnie wykorzystanie programowania aspektowego.
Ksika Spring. Zapiski programisty to praktyczny przewodnik po moliwociach
tego rodowiska. Jeli wolisz poznawa nowe zagadnienia w sposb praktyczny, a nie
wertujc setki stron zapenionych teoretycznymi wywodami, to ta ksika jest wanie
dla Ciebie. Znajdziesz w niej omwienie zagadnie zwizanych z samym Springiem,
wsppracujcymi z nim narzdziami i sposobami wykorzystania ich w procesie
tworzenia aplikacji J2EE poczwszy do graficznego interfejsu uytkownika
i interfejsu sieciowego, a skoczywszy na dostpie do relacyjnych baz danych.
Tworzenie klas z zastosowaniem zalenoci
Budowanie interfejsu uytkownika
Integrowanie JSF z frameworkiem Spring
Dostp do baz danych za pomoc JDBC
Odwzorowanie baz danych na obiekty za pomoc Hibernaete
Obsuga i zabezpieczanie transakcji
Wysyanie i odbieranie wiadomoci e-mail
Jeli poszukujesz wydajniejszych metod tworzenia aplikacji J2EE, wykorzystaj
moliwoci frameworka Spring. Dziki tej ksice poznasz je wszystkie.

Spis treci

Przedmowa ............................................................................................ 5
Wstp .................................................................................................... 9
Rozdzia 1. Pocztki ............................................................................. 17
Tworzenie dwch klas przy wykorzystaniu zalenoci ....................... 18
Stosowanie wstrzykiwania zalenoci ................................................ 23
Automatyzacja przykadu ................................................................... 28
Wstrzykiwanie zalenoci przy wykorzystaniu frameworka Spring ... 32
Tworzenie testu ................................................................................... 35
Rozdzia 2. Tworzenie interfejsu uytkownika ..................................... 41
Konfiguracja Tomcata ......................................................................... 42
Tworzenie widoku przy wykorzystaniu Web MVC ............................. 46
Wzbogacanie aplikacji sieciowych ...................................................... 56
Testowanie .......................................................................................... 65
Rozdzia 3. Integracja innych klientw ................................................ 69
Tworzenie interfejsu uytkownika w oparciu o framework Struts ....... 70
Stosowanie JSF wraz z frameworkiem Spring ....................................... 83
Integracja JSF z frameworkiem Spring ............................................... 92
Rozdzia 4. Stosowanie JDBC ............................................................... 95
Konfiguracja bazy danych i utworzenie schematu .............................. 96
Stosowanie szablonw JDBC frameworka Spring .............................. 101
Wydzielanie czsto uywanego kodu ................................................ 108
Stosowanie obiektw dostpowych .................................................... 110
Wykonywanie testw przy uyciu szkieletu EasyMock .................... 116
3

Rozdzia 5. Odwzorowania obiektowo-relacyjne ................................ 121


Integracja frameworka iBATIS ..........................................................123
Stosowanie frameworka Spring z JDO ...............................................134
Stosowanie frameworkw Hibernate oraz Spring ..............................142
Testowanie ........................................................................................150
Rozdzia 6. Usugi i AOP ..................................................................... 151
Tworzenie usugi ...............................................................................152
Konfiguracja usugi ...........................................................................159
Stosowanie automatycznych obiektw poredniczcych ....................164
Porady operujce na wyjtkach .........................................................167
Testowanie usugi przy wykorzystaniu obiektw zastpczych ..........170
Testowanie usugi majcej efekty uboczne ........................................174
Rozdzia 7. Transakcje i bezpieczestwo ........................................... 177
Programowa obsuga transakcji ........................................................178
Konfiguracja prostych transakcji .......................................................182
Transakcje obejmujce kilka baz danych ..........................................184
Zabezpieczenie serwletw aplikacji ...................................................190
Zabezpieczanie metod aplikacji .........................................................200
Tworzenie obiektu przechwytujcego uatwiajcego testowanie ........206
Rozdzia 8. Obsuga wiadomoci i praca zdalna ................................ 211
Wysyanie wiadomoci poczty elektronicznej ....................................212
Praca zdalna .....................................................................................216
Stosowanie JMS .................................................................................219
Testowanie aplikacji JMS ..................................................................224
Rozdzia 9. Tworzenie grubych klientw ............................................ 229
Zaczynamy prac ..............................................................................229
Tworzenie widoku BikeNavigator ......................................................244
Tworzenie formularzy edytora rowerw ...........................................249
Skorowidz ......................................................................................... 259

Spis treci

ROZDZIA 1.

Pocztki

W tym rozdziale:
 Tworzenie dwch klas przy wykorzystaniu zalenoci
 Stosowanie wstrzykiwania zalenoci
 Automatyzacja przykadu
 Wstrzykiwanie zalenoci przy wykorzystaniu frameworka Spring
 Tworzenie testu
W weekendy z wielkim zapaem oddaj si sportom ekstremalnym. Wedug standardw waciwych dla osb przecitnych, robiem na rowerze
grskim naprawd zwariowane rzeczy, a oprcz tego uwielbiam kajakarstwo grskie. Tylko raz znalazem si w powanych kopotach. Spywaem na rzece o nazwie Piedra, na ktrej byem po raz pierwszy, w nowym
sprzcie i z gow naadowan nowymi technikami. W kajakarstwie
grskim przeycie zaley od zachowania prostoty i szybkoci, a ja byem
niepewny i wolny. Zamiast atakowa rzek, to ona zaatakowaa mnie;
przepynem przez trzy bystrza klasy IV i naprawd miaem szczcie,
e wyszedem z tego bez adnych obrae.
Szybko i prostota ma rwnie due znaczenie w przypadku tworzenia
oprogramowania. Spring Framework daje mi jedno i drugie. Kupie t
ksik, wic zapewne zgadzasz si z tym stwierdzeniem. Spring, cho
jest prosty, ma bardzo due moliwoci. Ogromne. Spring pozwoli Ci na pisanie aplikacji o architekturze warstwowej, w ktrej poszczeglne warstwy
17

bd wyranie od siebie oddzielone. Spring sprawia, e bdziesz mg


testowa tworzony kod w tak prosty i przejrzysty sposb, o jakim wczeniej nawet nie moge marzy. W niniejszym rozdziale stworzysz prost aplikacj, zautomatyzujesz proces jej kompilacji i przystosujesz j do
korzystania z frameworka Spring.
Spring jest najpopularniejszym produktem z nowej grupy
tak zwanych
lekkich kontenerw.
Jeli uwzgldnimy
wszystkie wchodzce w jego skad moduy, to si okae,
e Spring nie jest a
taki lekki, jednak
w tym przypadku
okrelenie to odnosi
si do tego wszystkiego, co zazwyczaj
trzeba dodawa do
kodu umieszczanego
i wykonywanego
w kontenerze.

Tworzenie dwch klas


przy wykorzystaniu zalenoci
Wielu nauczycieli i konsultantw pisze o zalenociach jako o czym, co
mona by porwna do majonezu zbyt dugo pozostawionego na socu.
Jednak jeli tworzona aplikacja ma robi cokolwiek interesujcego, to zalenoci musz si w niej pojawi. Caa sztuka polega na tym, by zidentyfikowa wane zalenoci i obsuy je w odpowiedni sposb. Sposb,
w jaki rozwiesz zalenoci, bdzie mie znaczcy wpyw na atwo
utrzymania aplikacji, jej rozbudowy oraz testowania. Podczas lektury
niniejszej ksiki napiszesz system rezerwacji rowerw grskich. Sklep
sportowy mgby korzysta z takiego systemu do rezerwacji i wypoyczania
rowerw. Zaczniemy od najprostszych rozwiza, w ktrych wszystkie
zalenoci bd okrelone na stae w kodzie; w ten sposb bdziemy mogli
si upewni, e uywana infrastruktura dziaa poprawnie. Nastpnie rozlunimy powizania za pomoc frameworka Spring i stopniowo bdziemy dodawa do naszej aplikacji trwao, warstw prezentacji sieciowej,
deklaratywne transakcje i kilka innych usug.
Dla mnie tworzenie przy wykorzystaniu frameworka Spring ma charakter
iteracyjny. Najbliszych kilka wicze jest powiconych powolnemu
przygotowywaniu infrastruktury. W pierwszym upewnimy si, e dysponujemy poprawnie skonfigurowanym oraz dziaajcym rodowiskiem
Javy i zaczniemy tworzy podstawowy model aplikacji. Kady z kilku
pierwszych przykadw jest powicony niewielkiemu fragmentowi rodowiska, co uatwi nam rozwizywanie ewentualnych problemw, gdyby
jakie si pojawiy.

18

Rozdzia 1: Pocztki

Jak to osign?
Zaczniemy od dwch klas umieszczonych w jednym katalogu. Pierwsza
z nich bdzie reprezentowa rower grski, a druga rejestr, w ktrym bd
przechowywane informacje o wszystkich rowerach. T drug klas nazwiemy fasad. Informacje o posiadanych rowerach bd podawane
w konstruktorze fasady, a nastpnie wywietlane przy wykorzystaniu
trzeciej, bardzo prostej klasy.
Klasa Bike, reprezentujca rower, zostaa przedstawiona na listingu 1.1.
Listing 1.1. Bike.java
public class Bike {
private String manufacturer;
private String model;
private int frame;
private String serialNo;
private double weight;
private String status;
public Bike() {}
public Bike(String manufacturer, String model, int frame, String
serialNo, double weight, String status) {
this.manufacturer = manufacturer;
this.model = model;
this.frame = frame;
this.serialNo = serialNo;
this.weight = weight;
this.status = status;
}
public String toString() {
return "Rower : " +
"producent -- " + manufacturer +
"\n: model -- " + model +
"\n: rama -- " + frame +
"\n: numer seryjny -- " + serialNo +
"\n: waga -- " + weight +
"\n: status -- " + status +
".\n"; }
public String getManufacturer() { return manufacturer; }
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}

Tworzenie dwch klas przy wykorzystaniu zalenoci

19

public String getModel() { return model; }


public void setModel(String model) { this.model = model; }
public int getFrame() { return frame; }
public void setFrame(int frame) { this.frame = frame; }
public String getSerialNo() { return serialNo; }
public void setSerialNo(String serialNo) { this.serialNo = serialNo; }
public double getWeight() { return weight; }
public void setWeight(double weight) { this.weight = weight; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}

Listing 1.2 przedstawia fasad.


Listing 1.2. RentABike.java
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public class RentABike {
private String storeName;
final List bikes = new ArrayList();
public RentABike(String storeName) {
this.storeName = storeName;
bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15,
"Dobry"));
bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12,
"Doskonay"));
bikes.add(new Bike("Trek","6000", 19, "33333", 12.4,
"Dobry"));
}
public String toString() { return "RentABike: " + storeName; }
public List getBikes() { return bikes; }
public Bike getBike(String serialNo) {
Iterator iter = bikes.iterator();
while(iter.hasNext()) {
Bike bike = (Bike)iter.next();
if(serialNo.equals(bike.getSerialNo())) return bike;

20

Rozdzia 1: Pocztki

}
return null;
}
}

I w kocu kod zamieszczony na listingu 1.3 przedstawia widok.


Listing 1.3. CommandLineView.java
import java.util.Iterator;
public class CommandLineView {
private RentABike rentaBike;
public CommandLineView() {rentaBike = new RentABike("Rowery Bruce'a");}
public void printAllBikes() {
System.out.println(rentaBike.toString());
Iterator iter = rentaBike.getBikes().iterator();
while(iter.hasNext()) {
Bike bike = (Bike)iter.next();
System.out.println(bike.toString());
}
}
public static void main(String[] args) {
CommandLineView clv = new CommandLineView();
clv.printAllBikes();
}
}

Klasa RentABike
jest zalenoci.
W przypadku stosowania takiego
stylu programowania zalenoci s
podawane na stae,
co zwiksza stopie
wzajemnego powizania fasady i widoku. Framework
Spring pomoe
nam wyeliminowa
zalenoci
takiego typu.

Teraz moesz ju skompilowa aplikacj, uywajc nastpujcego polecenia:


C:\PozyczRowerApp\src javac -d ..\out *.java

Katalog wynikowy bdzie teraz zawiera skompilowane pliki klas:


Katalog: C:\PozyczRowerApp\out
2005-12-27
2005-12-27
2005-12-27
2005-12-27
2005-12-27

08:17
08:17
08:17
08:17
08:17

<DIR>
<DIR>

.
..
1 753 Bike.class
1 442 RentABike.class
937 CommandLineView.class

Aplikacj moesz uruchomi w nastpujcy sposb:


C:\PozyczRowerApp\out> java CommandLineView
RentABike: Rowery Bruce'a
Rower : producent -- Shimano
: model -- Roadmaster
: rama -- 20
: numer seryjny -- 11111
: waga -- 15.0
: status -- Dobry.

Tworzenie dwch klas przy wykorzystaniu zalenoci

21

Rower : producent -- Cannondale


: model -- F2000 XTR
: rama -- 18
: numer seryjny -- 22222
: waga -- 12.0
: status -- Doskonay.
Rower : producent -- Trek
: model -- 6000
: rama -- 19
: numer seryjny -- 33333
: waga -- 12.4
: status -- Dobry.

Jak to dziaa?
Nic dobrego. Nasz aktualny projekt jest bardzo prosty, lecz jednoczenie
wszystkie powizania s okrelone na stae. Od razu mona wskaza kilka
wad takiego rozwizania:
Podstawowy
wzorzec projektowy
stosowany we
frameworku Spring
oraz innych lekkich
kontenerach, bazuje
na zmniejszeniu
stopnia powiza
pomidzy
zalenociami.

Warstwa fasady (RentABike) w statyczny sposb tworzy rowery dostpne w sklepie, a zatem, za kadym razem, gdy pojawi si jaki
nowy rower (ech!), bd te gdy uytkownik skasuje jaki rower
(co za pech!), konieczne bdzie wprowadzanie odpowiednich zmian
w kodzie.
Take przetestowanie modelu bdzie kopotliwe, gdy zbir rowerw
jest stay i niezmienny.
Interfejs uytkownika oraz fasada s ze sob cile powizane. Mona
wskaza podan na stae zaleno pomidzy warstw fasady i interfejsem uytkownika.
Kod rdowy nie jest w aden sposb zorganizowany, a proces kompilacji aplikacji nie jest zautomatyzowany.
Jednak teraz chcemy wprowadzi pewne uatwienia, by poprawi dziaanie rodowiska Javy, tworzc jednoczenie podwaliny naszej aplikacji.
W nastpnym przykadzie rozdzielimy poszczeglne warstwy aplikacji
i zautomatyzujemy proces jej kompilacji.

22

Rozdzia 1: Pocztki

A co z
przygotowaniem tego caego burrito raz a dobrze? Moesz zdecydowa, by jednoczenie zainstalowa Spring, Hiberanate, Jav, Ant oraz
JUtil. Jednak z wasnego dowiadczenia mog stwierdzi, e zajmujc si
kolejno kadym zagadnieniem z osobna, w rzeczywistoci oszczdzamy
czas; zwaszcza jeli tworzymy podstawy rodowiska pracy. Kiedy wszystkie narzdzia zostan ju zainstalowane i bd dziaa poprawnie, bdziesz
mg poczy kilka czynnoci.

Stosowanie wstrzykiwania zalenoci


Kiedy zaczynam tworzy aplikacj, zazwyczaj jej poszczeglne elementy
s ze sob cile powizane. Nie ma w tym nic zego. W kadej chwili
mog to zmieni w pniejszych etapach pracy. W niniejszym przykadzie zmieni struktur aplikacji w taki sposb, aby wsppracowaa
z frameworkiem Spring w przypadku, gdy zostanie on wykorzystany.
W tym celu dodam do warstwy fasady interfejs, aby moga ona implementowa kilka rnych strategii.
Pierwszym krokiem podczas poznawania frameworka Spring jest poznanie wzorca wstrzykiwania zalenoci (ang. dependency injection).
Nie jest on skomplikowany, cho ma kluczowe znaczenie. Jest on na tyle
odmienny od standardowo przyjtego sposobu kodowania, e zapewne
bdziesz chcia zanotowa sobie skrcone informacje na jego temat.
Rysunek 1.1 przedstawia klienta i serwer przygotowane do wykorzystania techniki wstrzykiwania zalenoci. Klient uywa innej klasy, ktr
bdziemy nazywali usug. Klient posiada waciwo, a w niej mona
zapisa referencj do usugi. Usuga jest z kolei reprezentowana przez
interfejs, co sprawia, e klient nie zna jej faktycznej implementacji.
Niemniej jednak taki kod nie cechuje si niskim stopniem powiza
wci w jaki sposb musimy utworzy usug. Dziki wstrzykiwaniu
zalenoci jakie dodatkowe narzdzie, nazywane asemblerem lub kontenerem, odpowiada za utworzenie zarwno klienta, jak i usugi, a nastpnie okrela warto waciwoci aService (bdcej referencj do
obiektu typu Service stanowicego implementacj usugi), speniajc tym
samym wymagane zalenoci.
Stosowanie wstrzykiwania zalenoci

Wiele osb, gdy po


raz pierwszy styka
si z wstrzykiwaniem zalenoci,
dziwi si: O co tyle
haasu?. Jednak
kiedy zaczn uywa tej techniki,
po pewnym czasie
zrozumiej, i ta
prosta zmiana
moe w ogromnym
stopniu poprawi
tworzony kod
i uatwi utrzymanie
aplikacji.

23

Rysunek 1.1. Klient uywa usugi reprezentowanej przez interfejs

Prawdopodobnie ju zdarzao Ci si stosowa taki sposb kodowania.


Jednak dopiero teraz, kiedy wykorzystamy framework, ktry w spjny sposb uywa tego modelu programowego w obrbie caej aplikacji, przekonamy si, jak due moliwoci on zapewnia. Kod skadajcy si z luno
powizanych komponentw jest znacznie prostszy do testowania, utrzymania i zrozumienia.

Jak to zrobi?
Aby stosowa ten model projektowy, wcale nie trzeba korzysta z lekkich kontenerw. W celu rozdzielenia elementw programu przy wykorzystaniu wstrzykiwania zalenoci naley wykona trzy czynnoci:
1.

Stworzy interfejs, ktry bdzie reprezentowa usug.

2.

Doda do klienta waciwo odwoujc si do usugi.

3.

Przy wykorzystaniu dodatkowego frameworka lub wasnego kodu


stworzy usug i przypisa odpowiedni warto waciwoci klienta.

Pierwszym krokiem jest wydzielenie interfejsu. Teraz zmienimy nazw


pliku, definicji klasy oraz konstruktora RentABike na ArrayListRentABike
(listing 1.4) i stworzymy interfejs (listing 1.5).
Listing 1.4. ArrayListRentABike.java (wczeniej RentABike.java)
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListRentABike implements RentABike {
private String storeName;
final List bikes = new ArrayList();
public ArrayListRentABike(String storeName) {
this.storeName = storeName;
bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15,

24

Rozdzia 1: Pocztki

"Dobry"));
bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12,
"Doskonay"));
bikes.add(new Bike("Trek","6000", 19, "33333", 12.4,
"Dobry"));
}
public ArrayListRentABike() {
this("Rowery Bruce'a");
}
public void setStoreName(String storeName) { this.storeName =
storeName; }
public String getStoreName() { return this.storeName; }
public String toString() { return "RentABike: " + storeName; }
public List getBikes() { return bikes; }
public Bike getBike(String serialNo) {
Iterator iter = bikes.iterator();
while(iter.hasNext()) {
Bike bike = (Bike)iter.next();
if(serialNo.equals(bike.getSerialNo())) return bike;
}
return null;
}
}

Listing 1.5. RentABike.java


import java.util.*;
public interface RentABike {
List getBikes();
Bike getBike(String serialNo);
}

Kolejnym elementem programu jest widok, przedstawiony na listingu


1.6. Warto zauway, e wydzielilimy metody, ktre wywietlaj informacje o rowerze w wierszu polece. Dodalimy take do widoku waciwo, w ktrej mona zapisa obiekt typu RentABike.
Listing 1.6. CommandLineView.java
import java.util.*;

Teraz bdziemy
mogli zobaczy
usug RentABike
udostpnion
w formie waciwoci. Nieco pniej jej
warto zostanie
okrelona przez
framework Spring.

public class CommandLineView {


private RentABike rentaBike;
public CommandLineView() {}
public void setRentaBike(RentABike rentaBike) {

Stosowanie wstrzykiwania zalenoci

25

this.rentaBike = rentaBike;
}
public RentABike getRentaBike() { return this.rentaBike; }
public void printAllBikes() {
System.out.println(rentaBike.toString());
Iterator iter = rentaBike.getBikes().iterator();
while(iter.hasNext()) {
Bike bike = (Bike)iter.next();
System.out.println(bike.toString());
}
}
}
Tutaj moemy
zaobserwowa
dziaanie wstrzykiwania zalenoci.
Dodatkowy kod,
w tym przypadku
napisany przez nas,
tworzy oba obiekty
i wstrzykuje referencj typu RentABike
do obiektu widoku.

Ostatnim elementem aplikacji jest asembler, ktry tworzy wszystkie obiekty


i okrela warto waciwoci (listing 1.7).
Listing 1.7. RentABikeAssembler.java
public class RentABikeAssembler {
public static final void main(String[] args) {
CommandLineView clv = new CommandLineView();
RentABike rentaBike = new ArrayListRentABike("Rowery Bruce'a");
clv.setRentABike(rentaBike);
clv.printAllBikes();
}
}

Teraz mona skompilowa aplikacj, wykonujc nastpujce polecenie:


C:\PozyczRowerApp\src> javac -d ..\out *.java

Katalog wynikowy bdzie zawiera nastpujce, skompilowane pliki klas:


Katalog: C:\PozyczRowerApp\out
2005-12-31
2005-12-31
2006-01-02
2006-01-02
2006-01-02
2006-01-02
2006-01-02

15:28
15:28
15:02
15:02
15:02
14:58
14:58

<DIR>
<DIR>
1 737
1 477
186
944
496

.
..
Bike.class
ArrayListRentABike.class
RentABike.class
CommandLineView.class
RentABikeAssembler.class

Aplikacj mona uruchomi w nastpujcy sposb:


C:\PozyczRowerApp\out>java RentABikeAssembler
RentABike: Rowery Bruce'a
Rower : producent -- Shimano
: model -- Roadmaster
: rama -- 20
: numer seryjny -- 11111

26

Rozdzia 1: Pocztki

: waga -- 15.0
: status -- Dobry.
Rower : producent -- Cannondale
: model -- F2000 XTR
: rama -- 18
: numer seryjny -- 22222
: waga -- 12.0
: status -- Doskonay.
Rower : producent -- Trek
: model -- 6000
: rama -- 19
: numer seryjny -- 33333
: waga -- 12.4
: status -- Dobry.

Jak to dziaa?
Wanie zobaczye przykad wstrzykiwania zalenoci poza rodowiskiem lekkiego kontenera. Cho rodowiska twrcw i uytkownikw
lekkich kontenerw robi wiele haasu w zwizku z wstrzykiwaniem
zalenoci, to jednak pomysy lece u podstaw tego rozwizania s cakiem proste. Piszc programy, naley uywa interfejsw, a zalenoci
nie okrela samemu, lecz przy wykorzystaniu dodatkowego narzdzia.
W naszych przykadach, asemblery zastpimy w kocu frameworkiem
Spring. Kiedy to si stanie, framework bdzie samodzielnie wywoywa
konstruktory uywanych obiektw i okrela wystpujce pomidzy nimi
zalenoci. Niemniej jednak na razie musimy powici tej wersji aplikacji nieco wicej uwagi.

A co z
lokalizatorami usug lub obiektami fabrykujcymi? Oczywicie wstrzykiwanie zalenoci nie jest jedynym sposobem rozwizywania zalenoci
wystpujcych pomidzy obiektami. W rzeczywistoci nie jest to jedyny
dobry sposb rozwizywania tego problemu. Osoby korzystajce z technologii J2EE wykorzystuj zazwyczaj lokalizatory usug (ang. service
locators). Uywajc tego wzorca (przedstawionego na rysunku 1.2), mona
przedstawi zaleno w formie interfejsu, zarejestrowa j w sowniku,
a nastpnie odszuka przy wykorzystaniu dodatkowej klasy pomocniczej
nazywanej lokalizatorem (ang. locator). Nie jest to wcale ze rozwizanie.
Stosowanie wstrzykiwania zalenoci

27

Rysunek 1.2. Aplikacje J2EE zarzdzaj zalenociami przy wykorzystaniu


lokalizatorw usug

Strategia wstrzykiwania zalenoci pozwala na zastosowanie spjnego


rozwizania i cakowite oddzielenie zalenoci od tworzonej aplikacji.
W dalszej czci rozdziau przekonasz si, w jaki sposb rozwizanie to
moe pomc w testowaniu aplikacji i tworzeniu programw zapewniajcych du atwo utrzymania i konfiguracji.
W rzeczywistoci wczeniejsze lekkie kontenery, takie jak Avalon, wykorzystyway wanie to rozwizanie. Wikszo nowoczesnych kontenerw udostpnia mechanizmy suce do wyszukiwania zalenoci, cho
zazwyczaj preferowane s inne sposoby ich rozwizywania.

Automatyzacja przykadu
Najwyszy czas na mae porzdki. Aby mc pj dalej, konieczne jest
zastosowanie automatyzacji. Prawdopodobnie uywasz ju programu
Ant. Stanowi on standaryzowany sposb organizacji wszystkich zada,
jakie naley wykona w celu skompilowania i przygotowania aplikacji.
Jeli jeszcze nie uywasz tego programu, to bdziesz musia zacz.
Ant sta si wszechobecny. Aby mc posugiwa si narzdziami programistycznymi jzyka Java, konieczne bdzie postanie uywanego przez
nie jzyka. Nie mamy zamiaru zamieszcza w tym rozdziale uzasadnienia, dlaczego warto korzysta z programu Ant, gdy zapewnie i tak
ju wiele na ten temat czytae.

28

Rozdzia 1: Pocztki

Jak to zrobi?
Nie ma potrzeby pobierania pakietu instalacyjnego programu Ant
mona wykorzysta ten, ktry jest dostpny wraz z frameworkiem Spring
(http://springframework.org/). W celu wykonania wszystkich przykadw
zamieszczonych w tej ksice bdziesz potrzebowa frameworka Spring
w wersji 1.1 lub pniejszej. Podczas jego instalacji naley postpowa
zgodnie z zaleceniami dotyczcymi uywanego systemu operacyjnego.
Kolejnym krokiem po zainstalowaniu frameworka Spring bdzie zorganizowanie takiej struktury katalogw, ktra bdzie wygodna zarwno dla
frameworka Spring, jak i dla tworzonej aplikacji. Zalecamy zastosowanie takiej samej organizacji, jaka zostaa uyta w przykadowej aplikacji
dostarczanej wraz z frameworkiem Spring, dziki czemu zyskamy moliwo przeanalizowania gotowego, dziaajcego przykadu. Poniej przedstawilimy list katalogw, z ktrych bdziemy korzysta:

src
W tym katalogu przechowywane s wszystkie kody rdowe aplikacji. Jak zwykle struktura podkatalogw umieszczonych wewntrz
tego katalogu powinna odpowiada strukturze pakietw.

test
W tym katalogu przechowywane s wszystkie testy moduw. Wicej
informacji dotyczcych JUnit mona znale w ostatnim wiczeniu
zamieszczonym pod koniec tego rozdziau.

db
W tym katalogu umieszczane s wszelkie zasoby zwizane z bazami
danych skrypty, konfiguracje oraz kody. Niektre z nich bd plikami konfiguracyjnymi, inne plikami pomagajcymi stworzy baz
danych o odpowiedniej strukturze, a jeszcze inne pozwol na zapisanie w bazie informacji testowych. Jeli nasza aplikacja ma wsppracowa z kilkoma rnymi bazami danych, to dla kadej z tych baz
w katalogu db zostanie utworzony odrbny podkatalog.

Automatyzacja przykadu

29

war
Plik war jest typow jednostk wdraania aplikacji sieciowych. Jeli
uywasz kontenera J2EE lub kontenera serwletw, takiego jak Tomcat,
to w tym katalogu bdzie umieszczany plik konfiguracyjny web.xml.
W tym katalogu bd umieszczane take pliki konfiguracyjne uywane przez framework Spring. Informacje o plikach konfiguracyjnych
Springa zostay podane w wiczeniach zamieszczonych w dalszej
czci ksiki.
Na pocztek rozmie pliki wchodzce w skad naszej aplikacji w nastpujcy sposb:
Plik RentABike.java w katalogu src, w podkatalogach odpowiadajcych strukturze pakietw.
Plik ArrayListRentABike.java w katalogu src wraz z plikiem
RentABike.java.
Plik Bike.java w katalogu src wraz z plikiem RentABike.java.
Plik CommandLineView.java w katalogu src wraz z plikiem
RentABike.java.
W kocu bdzie Ci potrzebny skrypt programu Ant, ktry naley umieci w gwnym katalogu projektu. Listing 1.8 przedstawia skrypt od ktrego zaczniemy:
Listing 1.8. build.xml
To wanie w tym
pliku przekaesz
programowi Ant
informacje dotyczce pooenia plikw
klas wchodzcych
w skad aplikacji.
Mona je doczy
do pliku war aplikacji
lub wskaza bezporednio ich wersje
instalacyjne i poinformowa uytkownikw, jakie
pliki musz wdroy.

30

<?xml version="1.0"?>
<project name="RentABike" default="compile" basedir=".">
<property
<property
<property
<property

name="src.dir" value="src"/>
name="test.dir" value="test"/>
name="war.dir" value="war"/>
name="class.dir" value="${war.dir}/WEB-INF/classes"/>

<target name="init">
<mkdir dir="${class.dir}"/>
</target>
<target name="compile" depends="init"
description="Compiles all source code.">
<javac srcdir="${src.dir}" destdir="${class.dir}"/>
</target>

Rozdzia 1: Pocztki

<target name="clean" description="Erases contents of classes dir">


<delete dir="${class.dir}"/>
</target>
</project>

W celu wykonania powyszego skryptu programu Ant naley przej do


katalogu o nazwie C:\PozyczRowerApp i wyda nastpujce polecenie:
C:\PozyczRowerApp>ant
Buildfile: build.xml
init:
[mkdir] Created dir: C:\PozyczRowerApp\war\WEB-INF\classes
compile:
[javac] Compiling 5 source files to C:\PozyczRowerApp\war\
WEB-INF\classes
BUILD SUCCESSFUL
Total time: 2 seconds

Wanie to nazywam automatyzacj. Ograniczylimy


cakowit liczb
klawiszy, jakie naley nacisn w celu
skompilowania
i przygotowania
aplikacji w tym
momencie cay
proces wymaga
nacinicia dokadnie
czterech klawiszy.

Jak to dziaa?
Program Ant przygotowa aplikacj w jednym, zautomatyzowanym kroku.
Jak na razie nie jest to co prawda wielkim uatwieniem, jednak znaczenie tej automatyzacji bdzie stopniowo roso, wraz ze wzrostem stopnia
zoonoci poszczeglnych czynnoci wykonywanych w ramach kompilacji i przygotowywania aplikacji. Pniej bdziesz chcia, by system
samoczynnie wykonywa testy moduw, dodawa operacje zwizane
z prekompilacj, takie jak wzbogacenie kodw bajtowych przez JDO (patrz
rozdzia 5.) lub kopiowa pliki konfiguracyjne w odpowiednie miejsca.
Mona take wykonywa zadania specjalne w celu zainicjowania bazy
danych lub wdroenia pliku war na serwer aplikacji.

Kod bdzie rozmieszczony w katalogach o takiej samej strukturze


jak zastosowana przez nas, by nie pojawiy si adne problemy z pakietami.

Szczerze mwic,
budujemy t aplikacj w zintegrowanym rodowisku
programistycznym
o nazwie IDEA,
stworzonym przez
firm JetBrains.
Wedug nas dysponuje ono najlepszymi
dostpnymi moliwociami refaktoringu. Ale si nie
przejmuj kad
prezentowan wersj aplikacji testowalimy take
przy wykorzystaniu
skryptw
programu Ant.

Automatyzacja przykadu

31

A co z
faktem, e niektre zintegrowane rodowiska programistyczne w ogle
nie musz korzysta z programu Ant? Jeli chcesz uywa takich rodowisk programistycznych i nie przejmowa si programem Ant, to bdziesz musia upewni si, e:

Zintegrowane rodowisko programistyczne bdzie miao dostp do


wszystkich plikw .jar, z ktrych bdziemy korzysta.
W dalszych rozdziaach bdziesz musia znale sposb wdraania
i uruchamiania aplikacji sieciowej, oraz wykonywania testw JUnit.
Od tej chwili a do koca ksiki bdziemy informowa, kiedy konieczne
bdzie dodanie nowego katalogu, wykonanie aplikacji lub udostpnienie
nowej biblioteki. Nie bdziemy jednak opisywa, jak naley to zrobi, zakadajc, e bdziesz w stanie wykorzysta do tego celu moliwoci uywanego rodowiska programistycznego lub bdziesz wiedzie, jak to uczyni bezporednio w skrypcie programu Ant.

Wstrzykiwanie zalenoci
przy wykorzystaniu frameworka Spring
Ju niemal przygotowalimy nasz aplikacj do zastosowania frameworka Spring. Czas go pobra i uy. W tym wiczeniu zastpimy obiekt
RentABikeAssembler frameworkiem Spring.
Kiedy zaczem uywa Springa zamiast J2EE, moje ycie si odmienio.
Staem si znacznie bardziej produktywny. Okazao si, e pisanie kodu
atwiej stao si dla mnie atwiejsze, a tworzony przeze mnie kod jest
atwiejszy do zrozumienia dla moich klientw. Z kolei uproszczenie kodu
niejednokrotnie pozwalao na jego szybsze dziaanie. Poza tym wprowadzanie jakichkolwiek zmian w kodzie stao si nieporwnanie atwiejsze.
W rzeczywistoci napisaem ksik o znaczeniu i zaletach lekkich frameworkw takich jak Spring; nosi ona nazw Better, Faster, Lighter Java
i zostaa wydana przez wydawnictwo OReilly.

Jak to zrobi?
W pierwszej kolejnoci naley pobra pakiet instalacyjny frameworka
Spring. Mona go znale na witrynie http://springframework.org/. Stamtd
naley przej na witryn Sourceforge, na ktrej mona znale wersj
frameworka dostosowan do uywanego systemu operacyjnego (podczas
pisania niniejszej ksiki uywalimy wersji Spring 1.1). Nastpnie trzeba
32

Rozdzia 1: Pocztki

doda do projektu nowy katalog war\WEB-INF\lib i umieci w nim


biblioteki frameworka Spring (ca zawarto katalogu dist dostpnego
w pakiecie instalacyjnym frameworka Spring).
Modyfikacja poprawnie zaprojektowanej aplikacji bazujcej na zwyczajnych, starych obiektach Javy w skrcie POJO (ang. Plain Old Java
Objects) i przystosowanie jej do korzystania z frameworka Spring nie
przysparza najmniejszych problemw. Wszystko sprowadza si do wykonania poniszych czynnoci:
Zmodyfikowania kodu tak, aby korzysta ze wstrzykiwania zalenoci.
Obiekty modelu s komponentami, a usugi aspektami. Zazwyczaj jednak bdziesz uywa jedynie komponentw.
Usunicia kodu, ktry tworzy obiekty i rozwizuje zalenoci.
Napisania pliku konfiguracyjnego opisujcego uywane komponenty
i aspekty.
Odwoania si do napisanego kodu za porednictwem frameworka
Spring.
Poniewa poszczeglne elementy naszej aplikacji s ju przygotowane
do wykorzystania wstrzykiwania zalenoci, zatem zastosowanie frameworka Spring bdzie atwym wiczeniem. Po prostu zastpimy nasz
asembler wersj korzystajc z frameworka i stworzymy plik konfiguracyjny, ktry zostanie umieszczony w katalogu \war\WEB-INF.
Plik konfiguracyjny zosta przedstawiony na listingu 1.9.
Listing 1.9. RentABike-context.xml
<?xml version="1.0"?>
<!DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="rentaBike" class="com.springbook.ArrayListRentABike">
<property name="storeName"><value>Rowery Bruce'a</value></property>
</bean>
<bean id="commandLineView" class="com.springbook.CommandLineView">
<property name="rentaBike"><ref bean="rentaBike"/></property>
</bean>
</beans>

Wstrzykiwanie zalenoci przy wykorzystaniu frameworka Spring

33

Aby uruchomi skrypt przygotowujcy aplikacj, naley przej do katalogu PozyczRowerApp i wyda nastpujce polecenie:
C:\PozyczRowerApp\ant
Buildfile: build.xml
init:
[mkdir] Created dir: C:\PozyczRowerApp\war\WEB-INF\classes
compile:
[javac] Compiling 5 source files to C:\PozyczRowerApp\war\WEBINF\classes
BUILD SUCCESSFUL
Total time: 2 seconds

Na listingu 1.10 zosta przedstawiony nowy asembler, ktry zastpi


wczeniejsz klas RentABikeAssembler.
Listing 1.10. RentABikeAssembler.java
package com.springbook;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RentABikeAssembler {
public static final void main(String[] args) {
ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("RentABike-context.xml");
CommandLineView clv =
(CommandLineView)ctx.getBean("commandLineView");
clv.printAllBikes();
}
}

Jak to dziaa?
By moe drapiesz si po gowie i zastanawiasz, co w tym wszystkim
jest takiego niezwykego. Jednak te niewielkie zmiany architektury bd
miay znaczcy wpyw na cykl ycia aplikacji. Korzyci wynikajce z ich
wprowadzenia mona zauway niemal od razu. Nie bd Ci zanudza
i opisywa ich dokadnie. Zamiast tego napisz o tym, co si dzieje w ukryciu w sposb niezauwaalny dla programisty.

34

Rozdzia 1: Pocztki

A co z
Pico, Hive Mind oraz Avalonem? To wszystko s lekkie kontenery.
Kady z nich ma swoje silne i sabe punkty. Ani Avalon, ani Hive Mind
nie uzyskay na tyle duej masy krytycznej, aby chcia myle o ich
zastosowaniu, zwaszcza jeli chcesz uywa usug, ktre s w stanie
wspdziaa ze sob. Obecnie najwiksze udziay w rynku maj frameworki Spring oraz Pico. Programici poszukujcy samodzielnego kontenera zazwyczaj decyduj si na wykorzystanie Pico, jednak Spring posiada najbardziej rozbudowane i kompletne usugi dodatkowe, takie jak
deklaratywne transakcje i bogate strategie zapewniania trwaoci.

Tworzenie testu
Kady z rozdziaw niniejszej ksiki zostanie zakoczony stworzeniem
testu. Prawd mwic, jeli jeste programist, ktry gboko wierzy w pisanie programw w oparciu o testy, to testy moduw powiniene tworzy
w pierwszej kolejnoci. Wielu z Was kupio t ksik, gdy Spring jest
w stanie poprawi atwo testowania aplikacji. W zasadzie poprawa
moliwoci testowania od samego pocztku stanowia jedno z podstawowych zaoe architektury frameworka Spring.
Automatyzacja testw da Ci wiksz pewno co do tego, e Twj kod
dziaa poprawnie, a co wicej, e bdzie dziaa poprawnie take po
wprowadzeniu zmian. W rzeczywistoci wszyscy Twoi szefowie czytaj
te same ksiki, ktre informuj, e utrzymywanie duych zespow testujcych jest kosztowne. My musimy przej t paeczk. Nie ma adnego
efektywnego sposobu testowania, ktry by nie korzysta z automatyzacji.
Niemniej jednak istnieje pewnie powany problem. Wiele spord obecnie
stosowanych architektur, takich jak EJB oraz Struts, raczej nie uatwiaj
testowania. Ich czas adowania jest dugi, a tworzenie obiektw zastpczych (ang. mock objects) jest trudne.
Jednak Spring diametralnie zmienia t sytuacj. Kady obiekt moe by
wykorzystany poza rodowiskiem kontenera. Co wicej, ze wzgldy na
to, e kontener jest taki lekki, koszty zwizane z jego uruchamianiem

Tworzenie testu

35

s pomijalnie mae. To niezwykle dua zaleta, zwaszcza jeli musimy


testowa tworzony kod. W kocu Spring zachca i wspiera model programowania o bardzo sabych powizaniach pomidzy komponentami.

Jak to zrobi?
Test moduu (test jednostkowy, ang. unit test) mona sobie wyobrazi
jako kolejnego klienta aplikacji. Testy przyjmuj pewne zaoenia odnonie warunkw, jakie powinny by spenione w przypadku, gdy aplikacja bdzie dziaa poprawnie. Na przykad, jeli dodajesz obiekt do listy,
to jej wielko powinna si zwikszy o jeden. Nastpnie test mona
wykona samodzielnie podczas dodawania do kodu kolejnej funkcji,
bd te, podczas testowania starego kodu. Testy mona take wykonywa
jako jeden z elementw caego procesu kompilacji i przygotowywania
aplikacji. W takim przypadku, jeli zaoenia przyjte w testach nie zostan spenione, to cay proces przygotowywania aplikacji zakoczy si
niepowodzeniem.
Kady test moduu jest klas dziedziczc po klasie TestCase. Listing
1.11 przedstawia test stanowicy klienta fasady.
Listing 1.11. RentABikeTest.java
import java.util.List;
import junit.framework.TestCase;
public class RentABikeTest extends TestCase {
private RentABike rentaBike;
public void setUp() {
rentaBike = new ArrayListRentABike("Rowery Bruce'a");
}
public void testGetName() {
assertEquals("Rowery Bruce'a", rentaBike.getStoreName());
}
public void testGetBike() {
Bike bike = rentaBike.getBike("11111");
assertNotNull(bike);
assertEquals("Shimano", bike.getManufacturer());
}
public void testGetBikes() {
List bikes = rentaBike.getBikes();

36

Rozdzia 1: Pocztki

assertNotNull(bikes);
assertEquals(3, bikes.size());
}
}

Nastpnie, aby uruchomi test, konieczne bdzie zmodyfikowanie skryptu


programu Ant. Listing 1.12 przedstawia zmienione zadania inicjalizacji
i kompilacji oraz dodatkowe zadanie odpowiadajce za kompilacj testu
(trzeba zauway, i wyraenia CIEKA_DO_SPRING i CIEKA_DO_JUNIT
naley zastpi faktycznymi ciekami).
Listing 1.12. build.xml
<property name="test.class.dir" value="${test.dir}/classes"/>
<property name="spring.dir" value="CIEKA_DO_SPRING"/>
<path id="bikestore.class.path">
<fileset dir="${spring.dir}/dist">
<include name="*.jar" />
</fileset>
<pathelement location="${spring.dir}/lib/jakarta-commons/commonslogging.jar"/>
<pathelement location="${spring.dir}/lib/log4j/log4j-1.2.8.jar"/>
<pathelement location="${spring.dir}/lib/j2ee/servlet.jar"/>1
<dirset dir="${basedir}"/>
<dirset dir="${class.dir}"/>
</path>
<path id="run.class.path">
<path refid="bikestore.class.path"/>
<dirset dir="${class.dir}"/>
</path>
<path id="junit.class.path">
<path refid="run.class.path"/>
<pathelement location="CIEKA_DO_JUNIT"/>
</path>
<target name="init">
<mkdir dir="${class.dir}" />
<mkdir dir="${test.class.dir}" />
</target>
<target name="compile" depends="init"

W najnowszej wersji frameworka Spring dostpnej w chwili przygotowywania polskiego wydania niniejszej ksiki (1.2.6) zamiast servlet.jar powinno by servlet-api.jar

przyp. red.
Tworzenie testu

37

description="Compiles all source code.">


<javac srcdir="${src.dir}"
destdir="${test.class.dir}"
classpathref="bikestore.class.path"/>
</target>
<target name="compile.test" depends="init" description="Compiles all unit
test source">
<javac srcdir="${test.dir}"
destdir="${test.class.dir}"
classpathref="junit.class.path"/>
</target>

Listing 1.13 przedstawia zadanie odpowiadajce za wykonanie testu.


<target name="test" depends="compile, compile.test"
description="Runs the unit tests">
<junit printsummary="withOutAndErr" haltonfailure="no"
haltonerror="no" fork="yes">
<classpath refid="junit.class.path"/>
<formatter type="xml" usefile="true" />
<batchtest todir="${test.dir}">
<fileset dir="${test.class.dir}">
<include name="*Test.*"/>
</fileset>
</batchtest>
</junit>
</target>

A oto wyniki testu:


Buildfile: build.xml
init:
compile:
compile.test:
test:
[junit] Running RentABikeTest
[junit] Test run: 3, Failures: 0, Errors: 0; Time elapsed: 0.36 sec
BUILD SUCCESSFUL
Total time: 2 seconds

Jak to dziaa?
Ant wanie przygotowa ca aplikacj, w tym take test. Nastpnie testy zostay wykonane. Wszystko zakoczyo si powodzeniem. Gdyby
testw nie udao si przeprowadzi pomylnie, to aby cay proces przygotowywania aplikacji mg si poprawnie zakoczy, konieczne byoby
38

Rozdzia 1: Pocztki

takie poprawienie jej kodu, by warunki okrelane w testach zostay spenione. W ten sposb mona wychwytywa i poprawia niewielkie bdy,
zanim przerodz si one w due problemy.
W nastpnym rozdziale zaczniemy na powanie korzysta z frameworka
Spring. Stworzymy prawdziwy interfejs uytkownika dla naszej aplikacji,
wykorzystujc do tego celu szkielet Web MVC wchodzcy w skad Springa.
Pokaemy take, w jaki sposb mona zintegrowa ze Springiem istniejce komponenty interfejsu uytkownika.

Tworzenie testu

39

You might also like