Niniejszym wątkiem o prowokującym tytule otwieram cykl postów dotyczących Java Enterprise Edition w wersji 6 (JSR 316).
Po dłuższym namyśle postanowiłem nie zaczynać od przeglądu całej JEE6, ani też podejmować się jej subiektywnej oceny, a tym samym nie wpisywać się w polemikę w stylu: „czy lepszy czasem kulejący standard czy super przemyślany nie-standard”. Skupię się na faktach, nowościach, zmianach i co najwyżej subiektywnych odczuciach, dotyczących „trendów”.
To, co można powiedzieć bezsprzecznie, nie narażając się na bycie kontrowersyjnym, to to że w JEE6 trochę się zmieniło. Ci, którzy do tej pory tworzyli aplikacje w JEE5 i obserwowali pewne kłopotliwe braki w specyfikacjach – czasem duże, jak np. brak criteria API w JPA1, czy drobne: niemożność automatycznego startowania usług czasowych w EJB 3.0 – odczują prawdopodobnie poprawę komfortu pracy. Ci, którzy korzystali do tej pory ze szkieletów typu Seam z przyjemnością odkryją, że spora część Seam’a z jego kontekstami, wstrzykiwaniem zależności, zasięgiem konwersacji, czy rozgłaszaniem i konsumowaniem zdarzeń przez komponenty zostały wciągnięte do standardu mocą specyfikacji Context and Dependency Injection for Java EE (JSR 299) i Dependency Injection for Java (JSR 330). Optymizmem napawa również fakt, iż niektóre składowe specyfikacji trzymane dla zgodności z poprzednimi wersjami, zostały oznaczone jako możliwe do usunięcia w kolejnych wersjach – sama główna specyfikacja EJB 3.1 to ponad 600 stron opisująca nawet takie starocie jak EJB 1.1 Entity Bean – najwyższy czas już posprzątać.
Lekkie aplikacje w JEE i to bez dodatkowych szkieletów?
Na omawianie poszczególnych ”ficzerów” JEE6 przyjdzie pora przy omawianiu konkretnych specyfikacji, tu chciałbym rozważyć pewien kierunek zapoczątkowany przez JEE5 a mocno rozwinięty w JEE6, który powoli zrywa z konotacją JEE = „ciężka aplikacja”, w opozycji do np. „lekkich szkieletów”.
Historycznie aplikacja JEE wykorzystująca EJB kojarzyła się raczej z aplikacją posiadającą wydzieloną warstwę logiki biznesowej, w szczególności dostępnej zdalnie, w opozycji do podejścia opartego na wyłącznie komponentach webowych, z logiką umieszczoną w POJO (Plain Old Java Objects), czyli w zwyczajnych obiektach javowych. Zwykle też nie obyłoby się bez wsparcia wszelakich szkieletów umożliwiających Inversion of Controll/Dependency Injection jak np. Spring, czy SEAM, zwłaszcza gdy nie używamy EJB i nie mamy możliwości użycia transakcji zarządzanej przez kontener (CMT), deklaratywnego zabezpieczania zasobów etc.
Aktualna formuła Java EE 6 stara się objąć standardem tworzenie zarówno „ciężkich”, jak i „lekkich aplikacji”, w taki sposób, aby dało się je pisać bez konieczności korzystania z dodatkowych szkieletów spoza standardu.
Powyższe stwierdzenie opieram na następujących zmianach, które zaobserwowałem:
Wprowadzenie koncepcji Komponentu Zarządzanego (Managed Bean – dalej MB)
Wiele szkieletów reklamuje się jako opartych na POJO. Nie jest jednak to pojęcie zdefiniowane formalnie. Jeśli potraktujemy POJO dosłownie (Zwyczajny Obiekt Java), czyli interpretując jako obiekt, który nie jest zarządzany przez żaden kontener i nie posiada konfiguracji, wówczas ciężko jest przyznać rację wielu szkieletom które chwalą się, że oparte są na POJO, ale np. wymagają uprzedniego skonfigurowania w XMLu, czy anotacjach po to, ażeby działo wstrzeliwanie zależności, czy transakcje (patrz http://en.wikipedia.org/wiki/Plain_Old_Java_Object).
W takim kontekście POJO rozumiane było raczej jako nie-EJB, co prawdopodobnie zgodne jest z pierwotną intencją twórcy pojęcia, Martina Fowlera (http://www.martinfowler.com/bliki/POJO.html).
JEE 6 „definiuje” lub „zawłaszcza” (w zależności od poglądów) to pojęcie w specyfikacji Managed Beans 1.0, która jest wydzieloną częścią głównej specyfikacji JEE6. Cytując za specyfikacją:
„Komponent Zarządzany (Managed Bean) jest zarządzanym przez kontener obiektem, znanym jako skrót POJO, który spełnia minimalny zestaw wymogów.”
W telegraficznym skrócie: MB jest oznaczony specjalną anotacją, może posiadać nazwę widoczną w JNDI i określony cykl życia, który jest zarządzany przez kontener. Nie ma tu słowa o bardziej zaawansowanych elementach, które np. posiadają EJB.
Managed Bean jest pojęciem wspólnym, wykorzystywanym dalej przez inne specyfikacje (EJB, JSF) które mogą na te wymagania wpływać. Szczegóły wymagań dla MB poznamy w załączniku.
Wyodrębnienie specyfikacji Interceptors
Specyfikacja Interceptorów (Przechwytywaczy), została wyodrębniona w obrębie specyfikacji EJB i może być wykorzystywana ze wspomnianymi wcześniej Komponentami Zarządzanymi, dodając elementy aspektowości do programowania w JEE. Dla przypomnienia: Interceptor potrafi przechwycić wołanie metody komponentu, powodując wykonanie własnego kodu, który może np. zmodyfikować parametry wołania etc.
Wprowadzenie możliwości wstrzykiwania zależności (Dependency Injction)
W JEE5 pojawiły się pierwsze próby podejścia do problemu – w postaci anotacji @EJB, @Resource, @WebserviceRef, potrafiące wstrzyknąć zależność będącą komponentem EJB, zasobem JCA czy odwołaniem do usługi Webservice. Wstrzykiwanie było możliwe do ściśle określonych miejsc: komponentu EJB, servletu, komponentu zarządzanego JSF, etc.
Mocą specyfikacji Context and Dependency Injection for Java EE (JSR 299) większość klas Java, a w szczególności wszystkie Java Beans są komponentami zarządzanymi (MB), a do wszystkich komponentów zarządzanych stosują się mechanizmy wstrzykiwania zależności. Szczegóły poznamy w innych postach, warto tylko zauważyć że wstrzykiwanie zależności dostępne jest teraz niemal dla każdego możliwego obiektu.
Wprowadzenie kontekstów
Wymieniona wyżej specyfikacja JSR 299 umożliwia również umieszczanie komponentów w kontekstach, które determinują ich cykl życia. Do tej pory możliwość sterowania długością życia komponentów zarządzanych (JEE, Spring) był ograniczony: komponenty mogły być albo tworzone ad hoc dla każdego żądania, albo trwać w całej rozciągłości sesji lub też aplikacji. Seam wprowadził nowy zasięg konwersacji, którego długość życia określana jest przez programistę. Specyfikacja CDI wciela tę możliwość do JEE6, dając bardzo potężne narzędzie do żonglowania komponentami w obrębie aplikacji.
Gdyby na tym poprzestać to rysuje nam się widok aplikacji opartej na prawie zwyczajnych klasach, ze wsparciem dla wstrzykiwania zależności, kontekstowości i przechwytywania wołań. Ale pójdziemy jeszcze dalej, włączymy w to „lekkie EJB” (brzmi jak margaryna o smaku masła, ale mimo wszystko o dziwo smakuje)
Umożliwienie użycia EJB w „lżejszych” scenariuszach z zachowaniem podstawowych możliwości, poprzez
wprowadzenie lekkiej wersji EJB, pozwalającej jedynie na dostęp lokalny, pozbawionej MDB, czy usług czasowych (więcej w dodatku i innych postach)
wprowadzenie bezinterfejsowych EJB, które już coraz bardziej przypominają POJO
wprowadzenie kontenera „embeddable”, czyli lekkiego kontenera zagnieżdżanego w aplikacjach Java SE, pozwalającego na użycie tamże komponentów EJB
możliwość wdrażania EJB jako moduł war (czyli jako część aplikacji webowej
Tym sposobem podstawowe funkcjonalności EJB, takie jak deklaratywne zabezpieczanie zasobów, czy transakcje zarządzane przez kontener zasilają możliwości naszych Komponentów Zarządzanych, nie pociągając za sobą konieczności używania „całej armaty”, np. z dostępem zdalnym i innymi funkcjonalnościami, nie zawsze potrzebnymi w prostej aplikacji, a całą aplikację możemy zapakować w wara.
Całość przypieczętowuje pojęcie profilu
Wprowadzenie koncepcji profilu
Profil to, cytując za specyfikacją: „konfiguracja Platformy JEE, nakierowana na konkretną klasę aplikacji” (klasę w rozumieniu rodzaju). Do tej pory mówiliśmy o Serwerach aplikacji które musiały wspierać całą JEE oraz o Serwerach Webowych, które adresowały lekkie aplikacje webowe takich jak np. Tomcat. Serwery webowe wspierały pewien wybrany zbiór specyfikacji np. Servlet/JSP/JSF.. Pojęcie serwera webowego nie było jednak sprecyzowane w szczególności nie istniała lista specyfikacji którą powinien implementować serwer webowy. W JEE6 wprowadzony zostaje tzw. „Web Profile” czyli zestaw specyfikacji które powinien zawierać serwer webowy. W skład Web Profile w szczególności wchodzą specyfikacje Servlet, JSP, JSF, ale także EJB Lite i JTA. A więc komponenty EJB będą od teraz mogły działać na serwerach typu Web, a nie tylko pełnych serwerach aplikacji. Cały Web Profile opisany jest w dodatku.
Co dalej?
W kolejnych postach zechcę przybliżyć jedynie to, co w JEE6 nowe lub zmienione, nie zaś omawiać ją krok po kroku. Postaram się jednak żeby posty zrozumiałe były również dla początkujących w JEE6. Zacznę od omówienia zmian w specyfikacji EJB 3.1 i JPA 2.0. Postaram się także z bliska pokazać jak w praktyce udaje się tworzyć „lekkie” aplikacje oparte w całości na JEE6.
DODATEK 1 – Wymagania Specyfikacji Managed Beans.
Na podstawie dokumentu Managed Beans 1.0 Specification będącego częścią Java TM Platform, Enterprise Edition 6 (Java EE 6) Specification (JSR 316 )
Wymagania podstawowe:
o Definiowanie Komponentu Zarządzanego: jest to klasa konkretna, rozszerzalna (nie abstract, nie final), nie będąca wewnętrzną klasą statyczną; Komponent Zarządzany oznaczony jest anotacją javax.annotation.ManagedBean. W wersji podstawowej ziarno powinno posiadać konstruktor bezargumentowy
o Nazewnictwo: Komponent zarządzany może mieć nazwę podaną w anotacji @ManagedBean(“myName“), nawzwa musi być unikalna w obrębie modułu. Nazwanie Komponentu pociąga możliwość wyszukania go w przestrzeni nazw JNDI pod nazwami:
java:app/<module-name>/<bean-name> – dla przestzeni nazw aplikacji oraz
java:module/<bean-name> – dla przestrzeni nazw modułu
o Cykl życia i zasoby
Ziarna mogą korzystać z metod oznaczonych javax.annotation.PostConstruct i javax.annotation.PreDestroy do wskazania metod wołanych przez kontener po utworzeniu i przed zniszczeniem Ziarna.
Komponenty zarządzane w ogólności nie mają własnej przestrzeni nazw( tak jak np. EJB), zasoby z których korzystają powinny się znaleźć w przestrzeni modułu
o Wątki
Metoda ziarna wykonywana jest w tym samym wątku co wołający
o Interceptory
MB mogą używać interceptorów zdefiniowanych w specyfikacji Interceptors 1.1
Przykład Komponentu Zarządzanego:
@ManagedBean(“myName“),
public class MyClass{
@PostConstruct
public void init(){}
@PreDestroy
public void destroy(){};
//inne metody
}
Jest komponentem zarządzanym i widoczny w przestrzeni nazw JNDI dal modułu jako
java:module/myName
Komponent definiuje również metodę wołanych przy tworzeniu i niszczeniu Komponentu.
Rozszerzenie wymagań:
Wymagania podane w specyfikacji mogą być zmieniane w specyfikacjach bazujących na powyższej w następujący sposób
• Definiowanie Komponentu Zarządzanego: specyfikacja rozszerzająca może podać inne sposoby definiowania komponentu , w szczególności dołożyć wsparcie dla konstruktorów z argumentami, niwelując konieczność deklarowania konstruktora bezargumentowego
• nazewnictwo: specyfikacja rozszerzająca może podać inny sposób nazywania MB – np. poprzez dodatkowe anotacje, jednakże jeśli istnieje anotacja @ManagedBean(”…”) to ma ona zawsze pierwszeństwo. Spec. rozszerzająca może również wprowadzać dodatkowe przestrzenie nazw lub też nazwy alternatywne dla ziarna
• cykl życia i zasoby,
Spec Roz może definiować bardziej skomplikowany cykl życia a także wprowadzić przestrzeń nazw dla komponentu “java:comp”
• wątki : specyfikacja może anulować wymaganie na konieczność wołania w wątku wołającego
• Interceptory specyfikacja może udostępniać dodatkowy mechanizmy interceptorów niż podane w sepcyfikacji
DODATEK 2 – Lista specyfikacja wymagana dla serwera umożliwiającego udostępnianie aplikacji zgodnej z Web Profile
Na postawie Java™ Platform, Enterprise Edition 6 (Java EE 6) Web Profile Specification CHAPTER WP.2 Web Profile Definition będącego częścią JavaTM Platform, Enterprise Edition 6 (Java EE 6) Specification (JSR 316 )
o Servlet 3.0
o JavaServer Pages (JSP) 2.2
o Expression Language (EL) 2.2
o Debugging Support for Other Languages (JSR-45) 1.0
o Standard Tag Library for JavaServer Pages (JSTL) 1.2
o JavaServer Faces (JSF) 2.0
o Common Annotations for theJava Platform (JSR-250) 1.1
o Enterprise JavaBeans (EJB) 3.1 Lite
o Java Transaction API (JTA) 1.1
o Java Persistence API (JPA) 2.0
o Bean Validation 1.0
o Managed Beans 1.0
o Interceptors 1.1
o Contexts and Dependency Injection for the Java EE Platform 1.0
o Dependency Injection for Java 1.0
DODATEK 3 – EJB vs. EJB Light
Na podstawie dokumentu JSR 318: Enterprise JavaBeansTM,Version 3.1EJB Core Contracts and Requirements chapter 21.1 EJB 3.1 Lite
EJB Light
Pełne EJB
Komponenty sesyjne
TAK
TAK
Komponenty sterowane wiadomością
NIE
TAK
Komponenty Encyjne zgodne z EJB 2.x/1.x
NIE
TAK, oznaczone do usunięcia w przyszłych specyfikacjach
JPA 2.0
TAK
TAK
Dostęp lokalny i bez-interffejsowy
TAK
TAK
Dostęp zdalny zgodny z EJB 3.0
NIE
TAK
Dostęp zdalny zgodny z EJB 2.x
NIE
TAK
Dostep przez JAX-WS
NIE
TAK
Dostęp przez JAX-RPC
TAK
TAK, oznaczone do usunięcia w przyszłych specyfikacjach
Usługa czasowa (Timer Service)
NIE
TAK
Wołanie asynchroniczne komponentów sesyjnych
NIE
TAK
Interceptory
TAK
TAK
Zgodność z RMI-IIOP
NIE
TAK
Transakcje zarządzane przez kontener/komponent (CMT i BMT)
TAK
TAK
Deklaratywne i programistyczne zabezpieczanie komponentów
TAK
TAK
API kontenera zagnieżdżonego
TAK
TAK, ale jeśli serwer dostarcza pełnego EJB to API dla kontenera zagnieżdżonego może ograniczać się jedynie do zestawu Light
Lekkie aplikacje internetowe z wykorzystaniem Java Enterprise Edition w wersji 6
Jakub Koperwas
JEE 6 czas zacząć
Lekkie aplikacje w JEE i to bez dodatkowych szkieletów?
Wprowadzenie koncepcji Komponentu Zarządzanego (Managed Bean – dalej MB)
Wyodrębnienie specyfikacji Interceptors
Wprowadzenie możliwości wstrzykiwania zależności (Dependency Injction)
Wprowadzenie kontekstów
Umożliwienie użycia EJB w „lżejszych” scenariuszach z zachowaniem podstawowych możliwości, poprzez
Wprowadzenie koncepcji profilu
Co dalej?
DODATEK 1 – Wymagania Specyfikacji Managed Beans.
Wymagania podstawowe:
@ManagedBean(“myName“),
public class MyClass{
@PostConstruct
public void init(){}
@PreDestroy
public void destroy(){};
//inne metody
}
Rozszerzenie wymagań:
DODATEK 2 – Lista specyfikacja wymagana dla serwera umożliwiającego udostępnianie aplikacji zgodnej z Web Profile
DODATEK 3 – EJB vs. EJB Light