13 listopada 2008

W sprawie EJB 3.0 - Jak pakować komponenty w plik .jar?

Dostałem dzisiaj wiadomość, w której padło pytanie o sposób dystrybucji komponentów EJB.

Studiuje sobie ksiazke Enterprise JavaBeans wydawnictwa O'Reilly o komponentach, oczywiscie jeszcze jestem w powijakach ale juz sporo(wg mnie:-) ) rozumiem. Nurtuje mnie jednak pytanie jak pakowac komponenty w plik .jar ktory pozniej wdrozymy na serwer aplikacji. Tzn czy idea jest umiesczanie wszystkie komponentow w jednym pliku .jar jako calej aplikacji np sklep.jar(zapewne nie bo po co bylby .ear ale to tylko moj punkt widzenia malego czlowieczka raczkujacego w technologii EE) jako calej aplikacji czy tez kazdego komponentu oddzielnie, czy umieszczac wszystkie komponenty encyjne w jednym sesyjne w drugim itd, a moze komponenty spojne ze soba logicznie czyli np komponent sesyjny bezstanowy majacy w sobie funkcje odnoszace sie do komponentu sesyjnego. Troche chaotycznie to wszystko napisalem ale mam nadzieje Jacku ze mi wybaczysz moja niewiedze w tej technologii.

I już zacząłem moją krótką odpowiedź, aż przypomniałem sobie podobne pytanie od kogoś innego, więc padło na odpowiedź publiczną na moim blogu. Oto ona.

Każde ziarno EJB w EJB 3.0 to fizycznie dwa pliki class - interfejs (biznesowy w sensie EJB) oraz jego realizacja (implementacja). Klasy w javie umieszcza się w pakietach (zalecane jest, aby nie korzystać z pakietu domyślnego, tj. zadeklarowanego, gdy nie korzystamy ze słowa kluczowego package). Rozmieszczenie klas w pakietach nie ma żadnego wpływu na ich zarządzanie przez kontener EJB. Kontener jest w tym względzie neutralny. Mając interfejs oraz klasę w wybranych pakietach (dalej nazwijmy je artefaktami programistycznymi) przychodzi do ich organizacji w postaci ich umiejscowienia w odpowiadającym pakietowi katalogu lub plikowi jar. Zalecane jest, aby do dystrybucji naszej aplikacji stosować format jar. Ile i jakie ziarna EJB będą w pojedyńczym pliku jar nie ma kompletnie znaczenia. Może być tak, że dla każdej pary interfejs+implementacja stworzymy dedykowane im pliki jar. Może być też tak, że wszystkie pary będą umieszczone w pojedyńczym, obszernym pliku jar. Z punktu widzenia EJB 3.0 nie ma to żadnego znaczenia, poza faktem ich widoczności w ładowarce klas dla naszej aplikacji.

Każdy serwer aplikacyjny (w tym również kontener EJB) tworzy sieć (graf skierowany w postaci drzewa) ładowarek klas, gdzie dla pojedyńczego pliku jar mamy dedykowaną ładowarkę. Jeśli ta ładowarka klas obejmuje wszystkie klasy uczestniczące w pracy ziarna EJB, przynajmniej interfejs oraz klasa realizująca, wszystko będzie w należytym porządku. Istnieje "pojemniejszy" format organizacji artefaktów aplikacji korporacyjnych w Java EE 5 - plik ear. W nim możemy umieszczać pliki jar i inne (na chwilę obecną nieistotne). Plik ear tworzy przestrzeń widoczności (poprzez dedykowaną ładowarkę klas) dla wszystkich plików jar, które są w jego strukturze. Jeśli zdarzy się stworzyć plik sklep-interfejs.jar oraz sklep-implementacja1.jar to tylko w sytuacji dostępności pierwszego możemy oczekiwać poprawnej pracy ziarna EJB reprezentowanego przez drugi plik jar. Najczęściej jest to realizowane poprzez skorzystanie z pliku ear jako formatu dystrybucji naszych ziaren EJB.

Można zapytać, dlaczego warto zadać sobie trud, aby dzielić naszą aplikację, opartą o kilka ziaren EJB, na kilka plików jar, np. jeden per ziarno, potencjalnie z plikiem zawierającym interfejs jako osobny plik jar? Oczywiście zwiększa to modularność aplikacji. Jakkolwiek z punktu widzenia specyfikacji Java EE 5 nie jest to prawdziwe stwierdzenie, gdyż w "gołej" Javie reguły rządzące widocznością klas nie są zbyt wyrafinowane i czy jesteś w jednym pliku jar, czy w wielu, nie ma to znaczenia (zakładając ich widoczność w ładowarce klas), to już w środowiskach OSGi tak nie jest. Ma to znaczenie? Oczywiście nie dla...niekorzystających z OSGi. W samej korporacyjnej javie umieszczenie jarów na ścieżce klas (dosłownie, w systemie plików, lub wirtualnie poprzez umieszczenie ich w tej samej ładowarce klas) już wystarczy. Modularność w Java EE 5 mamy przez zastosowanie ziaren EJB, a ich fizyczne rozmieszczenie na jeden czy kilka jarów nie ma żadnego znaczenia. Muszą być po prostu dostępne i tyle. W bardziej restrykcyjnych środowiskach, jak OSGi, podział na większą liczbę plików jar pozwala na stworzenie aplikacji bardziej modularnie patrząc na jej fizyczną strukturę. W OSGi jar tożsamy jest z podstawowym bytem OSGi - pakunkiem. Dla OSGi plik jar jest pewnym bytem, podczas gdy dla EJB 3.0 jest niczym (jest to jedynie format dystrybucji dla języka Java, ale EJB 3.0 już nie wie, ile i czy w ogóle korzystaliśmy z pliku jar lub symulowaliśmy go strukturą podobną do pliku jar - "rozpakowany jar", czy po prostu umieściliśmy odpowiednio wiele na ścieżce klas). Możemy uruchomić jeden pakunek OSGi z interfejsem (=jeden plik jar), a drugi pakunek dostarczyć później i zmieniać ich widoczność dynamicznie, podczas działania aplikacji. W EJB 3.0 nie ma już takiej funkcjonalności, aczkolwiek sam serwer może to udostępniać, np. będąc oparty o OSGi lub inny mechanizm.

Miało być krótko i mimo, że zahaczyłem o OSGi sądzę, że było. Pytania?