Spring… i na wiosnę, i na lato – Część 1

Postaram się w dzisiejszym wpisie ogarnąć nieco temat framework’a Spring. Zacznijmy więc może od tego, czym on jest. Omnipotentna Wikipedia podpowiada nam, iż Spring jest narzędziem do tworzenia aplikacji (ang. application framework) w języku Java, zarówno dla platformy web, jak i stand-alone. Zatem spróbujemy dzisiaj stworzyć pierwszą aplikację webową w oparciu o Spring’a.

Przygotowanie środowiska

Zacznijmy więc przygodę od pobrania i rozpakowania narzędzia SpringSource Tool Suite. Jest to dostosowany do potrzeb Eclipse, więc obsługa nie powinna nastręczać żadnych problemów. Jako, że przy muzyce stanowczo milej się uczy, pracuje i czeka na ściągnięcie 350 megabajtowego archiwum, w tle pobrzękuje sobie Joe Bonamassa 🙂

Po pobraniu pliku, w moim przypadku springsource-tool-suite-2.9.2.RELEASE-e3.7.2-win32.zip, rozpakowujemy go sobie gdzieś na dysku i robimy na Pulpicie skrót do springsource\sts-2.9.2.RELEASE\STS.exe, który będzie wygodniejszy, od skakania po katalogach za każdym razem, gdy zachce się nam go odpalić.

Czy to już koniec? Cóż, jeśli chodzi o IDE i narzędzia to tak. Przygotujemy sobie jednak zawczasu prostą bazę danych.

Żeby nie było za prosto, jako serwer bazy danych wykorzystam maglowanego ostatnio w pracy Firebird’a. Ściągam więc go sobie i instaluje, ale to już chyba każdy zrobić potrafi, więc szczegóły pominę szczególnie, że możecie powalczyć z jakąś swoją ulubioną bazą danych.

Gdy już serwer stoi, tworzymy w nim prostą tabelę naszą testową, czy to z palca, czy z GUI, znaczenia nie ma najmniejszego.

Dodajemy generator:

Oraz dane testowe:

Pierwszy projekt

Zatem zakasamy rękawy i tworzymy nowy projekt, licząc na to, że Java 1.7 z której korzystam nie położy nam framework’a….

Wybieramy zatem Spring MVC Project z menu File -> New -> Spring Template Project

New Spring MVC Project

Wygląda na to, że coś się nam tam udało. Teraz trzeba zobaczyć, czy to cudo nam zadziała. Żeby to zrobić, w okienku Servers klikamy prawym na jedynym serwerze i wybieramy Add and Remove… po czym dodajemy nasz nowy projekt Example.

Add and Remove…

Cacy, pięknie, wciskamy na serwerze Play… i już na dzień dobry mamy babola:

Research u wujka Google podpowiada nam, że to może być problem z wersją biblioteki Log4j i należy podnieść domyślny numer wersji z 1.2.15 do 1.2.16. W związku z tym należy wyedytować pliczek pom.xml i upewnić się, że numer wersji będzie prawidłowy:

Zapisujemy zmiany i magiczny Maven robi za nas całą resztę. Wciskamy więc Play po raz wtóry i okazuje się, że serwer startuje już bez żadnych więcej błędów, a na dodatek, pod odpowiednim adresem mamy działający przykład.

http://localhost:8080/Example/

Czas na własny kontroler

Czy jest kontroler? Otóż adnotacja @Controller informuje Spring’a, że klasa, którą taką adnotacją oznaczyliśmy będzie zawiadywać sposobem przetwarzania i wyświetlania danych w naszym serwisie. Po szczegóły zapraszam do Spring’owego Bloga i artykułu GREEN BEANS: GETTING STARTED WITH SPRING MVC.

Stworzony przez kreatora HomeController zostawiamy sobie w spokoju, a obok niego dodajemy nasz własny CustomerController:

Oznaczamy klasę adnotacją @Controller i dodajemy metodę home(…). Nazwa metody może być dowolna, znaczenia mają tutaj natomiast: adnotacja @RequestMapping, która mówi kontenerowi jaką ścieżkę adresu metoda owa będzie obsługiwać; lista parametrów, której znaczenie możemy odnaleźć w czeluściach Spring’owego Blog’a; oraz zwracany przez ową metodę String. Nadmienię tylko, iż nie musi być to String, a na przykład instancja klasy ModelAndView… ale to temat nie a ten moment.

Cóż mówi kontenerowi ten zwracany przez nas „customer_list”? Mówi, jaki plik byśmy chcieli wyświetlić. Mogłaby być to ścieżka do pliku, jednak w pliku /Example/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml mamy domyślnie wygenerowaną konfigurację, która do zwracanego przez nas ciągu znaczków dokleja coś z przodu i coś z tyłu, i w efekcie powstaje nam z tego ścieżka, w której kontener będzie poszukiwał pliku widoku, do którego się odwołać chcemy.

W naszym wypadku będzie to /WEB-INF/views/customer_list.jsp, którego nie mamy, a który trzeba by stworzyć.

Restart serwera, wejście na stronę i naszym oczom ukazuje się:

http://localhost:8080/Example/customer

Kolej na usługę

Wiemy już pi razy drzwi, jak działa kontroler. Teraz przydałoby się zejść nieco głębiej. Spring oferuje nam kilka adnotacji, które pozwalają nam odróżnić poszczególne poziomy funkcjonalności od siebie, a samemu kontenerowi dają też wskazówki, jak powinny one być przez niego traktowane. I tak oto wyróżniamy @Controler@Service@Repository@Component. Szczegóły wynikające z różnic pomiędzy nimi opisuje inny artykuł, jednakże pokrótce można podsumować je tak:

Dla uproszczenia stworzymy na początku usługę zwracającą zawsze ten sam obiekt.

Oraz nasze proste DTO w postaci klasy Customer:

Klasa ToStringBuilder znajduje się w bibliotece commons-lang i żeby ją dodać do projektu, znów musimy wyedytować plik pom.xml, aby dodać do niego nowy wpis:

Skoro mamy już usługę, która coś potrafi zwrócić, zmodyfikujmy nasz kontroler i plik widoku:

W ten sposób kontroler pobierze  listę wszystkich udostępnianych przez usługę klientów i przekaże ją do modelu, który z kolei udostępni ją nam w widoku do dalszej obróbki 😉 Również w tym miejscu Spring dostarcza nam kilku adnotacji, a dokładniej @Autowired oraz @Inject, obie opisane tutaj. Cała jednak różnica sprowadza się do tego, iż:

@Inject does not have a required property unlike Spring’s @Autowire annotation which has a required property to indicate if the value being injected is optional.”

I takim oto sposobem, po restarcie serwera otrzymujemy:

http://localhost:8080/Example/customer

Na deser repozytorium

Stworzymy sobie naprędce repozytorium, które z bazy danych wyciągnie nam dodaną zawczasu testową listę klientów.

Adnotacja @Autowired wstrzyknie nam do metody setDataSource(DataSource dataSource) źródło danych, które skonfigurujemy zaraz poniżej w pliku /Example/src/main/webapp/WEB-INF/spring/root-context.xml. Zadania wewnętrznej klasy CustomerMapper chyba nie muszę omawiać.

Do komunikacji z bazą będziemy używać JdbcTemplate, gdyż jest to nisko poziomowe, klasyczne Spring’owe podejście, a niuansów mieszania JTA, JDBC, Hibernate i transakcji nie chcę w tym wpisie poruszać, gdyż można o nich sobie poczytać tutaj. O samym JDBC zaś tutaj.

dataSource odpowiada za konfigurację źródła danych, czyli dostępu do naszej bazy. txManager określa menedżera transakcji, którego wykorzystamy w projekcie. Zaś <tx:annotation-driven… /> informuje kontener, iż sposób zarządzania transakcjami określać będziemy przy użyciu adnotacji, np: @Transactional(readOnly=true).

Żeby jednak taka konfiguracja nam zadziałała znów musimy dodać kilka zależności do projektu:

Aktualizujemy jeszcze tylko usługę…

…restart serwera i …Shazam!, mamy naszą testową listę klientów prosto z bazy danych.

http://localhost:8080/Example/customer

Fin

To tyle, na dzień dzisiejszy. Następnym razem pokażę, jak można coś do naszej bazy wrzucić i wyedytować. Dzięki za uwagę i do następnego!

2 komentarze

  1. Piotr Koper napisał(a):

    Tego, czego niemal zawsze brakuje mi w tego typu tutorialach to brak struktury plików w archiwum. Dodatkowo – przydałaby się zawartość web.xml – można byłoby coś więcej wywnioskować. Ogólnie będę śledził 🙂 poczynania. W szczególności byłbym zainteresowany publikacją usług sieciowych (WS/REST) w odrębnej aplikacji z takimi gadżetami jak obsługa starndardów (np. ws-addressing, ws-security), autoryzacja (zwłaszcza dla REST), obsługa przesyłania plików itd. 🙂 Da się?

    Pozdrawiam.

  2. Kamil Dybicz napisał(a):

    Struktury plików w archiwum nie mam jak pokazać, gdyż żadne archiwum nie jest generowane. Aplikacja wrzucana jest na serwer w ścieżce springsource\vfabric-tc-server-developer-2.7.0.RELEASE\spring-insight-instance\wtpwebapps\Example w postaci struktury podkatalogów i plików. Plik web.xml nie był przeze mnie w żaden sposób modyfikowany, więc nie umieszczałem go tutaj. Wygenerowany z szablonu będzie dokładnie taki sam jak mój. Co do WS i REST, to są one faktycznie tematem, którym chciałbym się zająć, ale nie wiem, czy będę wchodził w takie szczegóły, jak autoryzacja 🙂 Najpierw jednak chcę ogarnąć temat transakcji.
    Pozdrawiam

Leave a Reply