Nowa era aplikacji serwerowych
Artykuł przedstawia możliwości najnowszej, szóstej, wersji technologii Java Enterprise Edition (Java EE). Wersja ta wprowadziła wiele poważnych przekształceń, dzięki którym Java EE zostało znacznie unowocześnione. Poprawiono funkcjonalność technice, kładąc jednocześnie duży nacisk na intuicyjność zastosowania, elastyczność.
Przyglądając się użyteczności JEE 6, będziemy śledzić proces budowy przykładowej aplikacji, która zademonstruje nowe interface’y programistyczne i rozwiązania architektoniczne.
Autor:Piotr Kochański
Źródło: sdjournal.org
Wprowadzenie Java EE w wersji pięć zaowocowało usunięciem najważniejszych problemów, z którymi borykali się programiści aplikacji serwerowych. Największy nacisk położono wówczas na dopracowanie najbardziej nielubianej technologii JEE – komponentów EJB.
Komponenty EJB są właśnie zwyczajnymi klasami Java (ang. Plain Old Java Objects
- POJO), a cała konfiguracja modułu EJB może być zrealizowana przy pomocy metadanych (ang. annotations), zamiast pliku konfiguracyjnego. Komponenty encyjne EJB, odpowiedzialne we wcześniejszych wersjach JEE za komunikację z bazą danych, nie zostały satysfakcjonującym rozstrzygnięciem i zastąpiła je nieporównywalnie lepsza technika: Java Persistence API.
Znaczącą innowacją było wprowadzenie wygodnego interfejsu programistycznego na potrzeby usług sieciowych. Technika JAX
Powinieneś wiedzieć:
• Czytelnik powinien znać podstawy języka Java oraz technice Java EE.
WS, korzystająca z dobrodziejstw konfiguracji przy pomocy metadanych, zastąpiła trudne w użyciu interfejsy SAAJ i JAX-RPC. Zadbano również tym razem o to, aby usługi sieciowe JAX-WS z powodzeniem komunikowały się z usługami pisanymi w innych technologiach, głównie .NET.
Java EE pięć była krokiem ewolucyjnym, nie rewolucyjnym. Poprawiono to, co tego wymagało, a te elementy technice, które specjalnie nikomu się nie naraziły, pozostawiono bez zmian. Charakterystyczny był priorytetowo brak niebagatelnych przeróbek w warstwie webowej technice Java EE.
Wprowadzenie Java EE 6 jest posunięciem znacznie radykalniejszym. Poza przemian typowo ewolucyjnych, ulepszających istniejące techniki – na przykład wprowadzenie Java Persistence API 2.0 – przedefiniowano zupełnie sposób patrzenia na tworzenie i wdrażanie aplikacji, projektowanie architektury czy wręcz na strukturę samego serwera aplikacyjnego.
Zmiany te nie wzięły się znikąd. Przede wszystkim w świecie IT jest bardzo wyraźny trend używania coraz powszechniej złożonych programów internetowych (ang. Rich Internet Applications), co stwarza, że webowy interfejs użytkownika odgrywa coraz większą rolę. W rezultacie potrzebna jest technologia, która maksymalnie ułatwia tworzenie takich aplikacji. A przy tym metodę budowania architektury programów, wzorce projektowe przeszły bardzo istotną ewolucję, która musiała odnaleźć odbicie po stronie Java EE.
Twórcy szóstej wersji Java EE, opracowując nową specyfikację, wzięli sobie do serca potrzeby programistów, uwzględnili doświadczenia najlepszych i najbardziej sprawdzonych istniejących rozwiązań, takich jak Spring Framework, JBoss Seam czy Google Guice. Zobaczmy teraz, jaki jest efekt ich wysiłków.
Przykładowa aplikacja
żeby dobrze poznać możliwości Java EE 6, utworzymy, wdrożymy i przetestujemy aplikację webową Todo, służącą do kontrolowania listą rzeczy do zrobienia. Umożliwia ona dodawać użytkowników , a oprócz tego przypisywać im zadania. Można też wyświetlić listę zadań i użytkowników.
Aplikacja jest dość prosta, ale pozwoli nam dobrze zrozumieć omawiane techniki, pokazując ich wykorzystanie w konkretnej sytuacji.
Kolejność omawiania technologii będzie odpowiadała ich miejscu w cyklu tworzenia aplikacji. Rozpoczniemy od modelu domenowego programów, który znajduje indywidualne odbicie w warstwie trwałego przechowywania danych, następnie przejdziemy do implementacji logiki biznesowej przy pomocy komponentów EJB, a na końcu zajmiemy się interfejsem użytkownika.
Java Persistence API 2.0
JPA 2.0 jest konsekwentnym krokiem w stronę zaprojektowania standardowego i funkcjonalnego mostu relacyjno-obiektowego dla aplikacji Java. Dodano do technologii parę drobnych udogodnień, między innymi:
• usuwanie osieroconych rekordów w bazie danych, w przypadku gdy został usunięty rekord pełniący rolę rodzica w relacji;
• ułatwiono modelowanie kolekcji obiektów – nie ma już potrzeby tworzenia dodatkowej, czasem zupełnie zbytecznej, encji JPA wraz z odpowiednią relacją;
• rozbudowano język zapytań Java Persistence Query Language (JPQL) o nowe użyteczne elementy.
Ukazały się też z dawna wyczekiwane poważniejsze zmiany, przede wszystkim interfejs zapytań Criteria, znany dobrze użytkownikom Hibernate.
Zapytania Criteria są konstruowane z obiektów Java, są dzięki temu silnie typo-wane, w odróżnieniu od zapytań JPQL, które są łańcuchami znaków. Znakomicie ułatwia to powstawanie złożonych, dynamicznie budowanych zapytań czy refaktoryzację aplikacji i, bez wątpienia, koryguje wydajność programów.
Drugą znaczącą zmianą jest możliwość pesymistycznego blokowania rekordów. JPA 1.0 pozwalał wyłącznie na optymistyczne blokowanie rekordów, stosując mechanizm wersjonowania rekordów. JPA 2.0 umożliwia także na stosowanie blokad pesymistycznych, czyli faktycznego zablokowania dostępu do rekordu w bazie danych.
Budowę programów Todo rozpoczniemy od modelu domenowego, opisującego najważniejsze jej szczegóły. Zadanie do zrobienia reprezentuje encja Task, użytkownika encja User. Co więcej możemy zadaniom przypisywać kategorie (encja Category) , a oprócz tego dodawać do nich załączniki, opisywane klasą Attachment.
Listing 1 przedstawiający encję Task. Ponieważ załączniki interesują nas wyłącznie jako część zadania, to nie posiada powodu wytworzyć dla nich encji i relacji między nią a Task. Wykorzystujemy więc uproszczony metodę definiowania pola typu kolekcja. W JPA 2.0 nie musimy wyprodukować, sztucznej w tym kontekście, relacji – wystarczy przy polu attachments dodać metadane @ElementCollection@CollectionTable(name = „task_attachments”), a mechanizm JPA będzie sam dbał o zapisywanie do bazy danych odpowiednich rekordów. Po stronie skryptu Java po prostu używamy obiektu typu Set.
Klasa Attachment (Listing 2) jest bardzo prosta i zawiera wyłącznie raport najmniejszych elementów dotyczących wyglądu pól w podstawie danych, w szczególności pole content jest zadeklarowane jako pole stylu BLOB o wielkości 512 kB.
Metadane @Entity, @Id, @GeneratedValue są standardowymi detalami konfiguracji JPA oznaczającymi, stosownie, że: ma-my do czynienia z encją JPA, pole taskId reprzekazuje klucz priorytetowy w tabeli odpowiadającej encji Task, a jego wartość będzie generowana domyślnym mechanizmem dla określonej bazy danych. Z kolei @Column i @Temporal uściślają wygląd schematu bazy danych.
Oprócz metadanych konfigurujących encję Task z punktu widzenia mechanizmu trwałości, znajduje się tam także wiele metadanych związanych z inną, zupełnie nową technologią.
Walidatory
Walidatory (ang. Bean Validation) dają nam ustandaryzowany sposób na sprawdzanie poprawności danych. Jest to w sumie dość proste rozwiązanie technologiczne, ale niezwykle pożyteczne.
Praktycznie największe dylematy z walidacją pojawiają się wówczas, gdy musi być ona przeprowadzana w kilku warstwach aplikacji. Wyobraźmy sobie, że ewidentne dane są wprowadzane w warstwie interfejsu użytkownika, następnie przetwarzane poprzez warstwę logiki biznesowej i wreszcie trwale zapisywane poprzez warstwę komunikacji z bazą danych. W zasadzie powinieneś walidować informacje we wszystkich trzech miejscach, co oczywiście może spowodować duplikowanie kodu lub, co gorsza, pojawienie się różnych reguł walidacji w każdej z warstw.
Walidatory Java EE pozwalają skonfigurować walidację w jednym miejscu. Odbywa się to poprzez dodanie odpowiednich metadanych przy wybranych polach klas.
Wybór miejsca centralnej konfiguracji walidacji jest dość naturalny: klasy reprezentujące dane – w naszym przypadku są to encje JPA. W którejkolwiek warstwie programów będziemy używać tych klas, to walidacja będzie za każdym razem przeprowadzana w ten sam sposób.
Do dyspozycji posiadamy szereg domyślnych walidatorów, między innymi @NotNull, @Size, @Min, których znaczenie jest dość oczywiste, prócz tego możemy spawdzać, czy pola typu Date albo Calendar reprezentują datę później (@Future), bądź w przeszłości (@Past). Niektóre metadane są zastosowane do encji Task (Listing 1).
Bardzo elastycznym walidatorem jest @Pa ttern(regexp=””), który kontroluje prawidłowość wartości pola względem podanego wyrażenia regularnego.
Można też generować swoje metadane walidujące, definiujące narzucane przez naszą firmę uwarunkowania poprawności danych. Łatwo można napisać, np, metadane @Pesel lub @Nip, sprawdzające poprawną wartość numeru PESEL lub NIP.
EJB 3.1
Posiadamy gotowy model domenowy aplikacji Todo, czas go ożywić, dodając warstwę wykonującą na nim różnego typu operacje – logikę biznesową. Java EE zakłada, że do tego celu będą wykorzystywane komponenty EJB. Kiedyś taki wybór był traktowany jako zło konieczne, w większości też całkowicie ignorowano tę technologię, przede wszystkim ze względu na niewygodną konfigurację, trudności przy testowaniu i produkowaniu efektywnego modelu obiektowego. Dodatkowo komponenty EJB musiały być wdrażane jako osobne archiwa, co stanowiło niepotrzebną komplikację w wypadku aplikacji webowych.
Część problemów związanych z tą technologią rozwiązało wprowadzenie wersji EJB 3.0; najnowsza odsłona specyfikacji stawia kropkę nad i, dając nam do ręki narzędzie o bardzo dużych możliwościach (deklaratywne zarządzanie transakcjami, klastrowalność, i tak dalej.), a równocześnie proste w użyciu i funkcjonalne.
Pierwszym ułatwieniem jest brak konieczności użycia interfejsów dla komponentów EJB o dostępie lokalnym (ang. No-interface view), wszelkie publiczne metody komponentu są samoczynnie dostępne dla mieszkanienych kontrahentów.
Pojawił się też nowy typ komponentów sesyjnych – Singleton. Wszyscy nabywcy aplikacji używają jedynie jednej instancji takiego komponentu, dzięki czemu łatwo produkować komponenty, które pełnią rolę schowków na informacje, przechowują ustawienia konfiguracyjne lub którekolwiek inne informacje, które powinny być współdzielone.
Singletony można konfigurować pod kątem zachowania w środowisku wielowątkowym. Domyślnie są one bezpieczne dla wątków, ale gdy upowszechniają one dane wyłącznie do odczytu, to można to zachowanie zmienić, z profitem dla wydajności aplikacji.
W komponentach EJB można produkować metody asynchroniczne, których wywołanie nie stwarza wstrzymania wątku kontrahenta. Metody takie mogą lub nie zwracać wartości, lub zwracać obiekt java.util.concurrent.Futu re, dzięki któremu można stwierdzić, czy jest już dostępny wynik działania metody i go ściągnąć. Dotychczas jedynym mechanizmem asynchronicznym w EJB zostały komponenty nakierowane na komunikaty (ang. Message Driven Beans).
Znaczącym ułatwieniem dla programistów tworzących programy WWW jest możliwość wdrażania komponentów EJB w archiwach WAR programów WWW (ang. war deployment).
Najnowsze komentarze