01 czerwca 2007

Mój prezent z okazji święta - Aplikacja korporacyjna z JPA w trybie JTA z GlassFish i PostgreSQL

A co! Każdemu należy się prezent z okazji święta Dnia Dziecka bez względu na wiek, więc moim prezentem jest spisanie moich przemyśleń nt. tworzeniu aplikacji korporacyjnej z JPA w trybie JTA z GlassFish i PostgreSQL w postaci artykułu Aplikacja korporacyjna z JPA w trybie JTA z GlassFish i PostgreSQL. Jest tam również użycie mechanizmu DataModel wspierającego działanie h:dataTable w JSF, więc dużo dobrego do analizy.

Po powrocie z Ukrainy, gdzie miałem możliwość spotkać się z wykładowcami Kijowskiej Politechniki i w wolnych chwilach podczas przelotów naczytałem się i postanowiłem popróbować się z konfiguracją JPA z transaction-type="JTA" oraz PostgreSQL. W zasadzie to zależało mi na utworzeniu aplikacji, która byłaby przyczółkiem dla utworzenia bardziej zaawansowanej aplikacji korporacyjnej, dzięki której będę mógł rozpocząć poznawać szczegóły specyfikacji Java EE. W kolejnych odsłonach aplikacji będzie można oczekiwać kolejnych usprawnień, jak wykorzystanie komponentu sesyjnego EJB 3.0 jako fasady dla encji i zniwelowania konieczności użycia mechanizmów obsługi transakcji bezpośrednio w kodzie komponentu zarządzanego JSF. Chciałbym uniezależnić się również o środowiska programistycznego IDE, czyli pojawiłby się również Apache Maven 2 czy alternatywni dostawcy JPA. Pora rozpocząć podsumowanie wiedzy odnośnie EJB 3.0 i JPA 1.0 i wreszcie zaspokoić swoje ego certyfikatem Sun Certified Business Component Developer (SCBCD) 5.0. Pamiętam ile mogłem nauczyć się podczas egzaminu SCJP 5 i jak wiele wyszło braków. Sądzę, że SCBCD może spełnić podobną funkcję - pogłębienie wiedzy odnośnie specyfikacji. Jeśli przy tym zdobędę certyfikat, to i dobrze (jest on potrzebny do podejścia do Sun Certified Enterprise Architect (SCEA), a o tym to jeszcze nawet nie myślałem, więc z SCBCD mogłoby być ciekawie. Przy okazji, czy ktoś z czytających rozważa SCEA, albo już posiada to cudeńko?).

Nie mógłbym nie wspomnieć o innej przyczynie spisania przemyśleń odnośnie wykorzystania usług serwera aplikacyjnego Java EE 5. Kilka dni temu otrzymałem list od Piotra Kochańskiego, który zwrócił mi uwagę na pewien niuans w wykorzystaniu JPA i mechanizmu wstrzeliwania zależności. Chodzi o wykorzystanie adnotacji @PersistenceUnit i @PersistenceContext. W zasadzie obie dotyczą tej samej funkcjonalności (tak w wielkim skrócie), ale pierwszy z nich jest stosowany dla przekazania referencji do fabryki PU podczas, gdy drugi jest przekazaniem kontekstu PU. I kiedy dopiszę, że pierwszy jest odporny na wielowątkowość, a drugi nie i że użycie drugiego było w servlecie wszystko powinno być jasne - moja aplikacja nie była odporna na wielowątkowość (!) W dodatku sam o tym niedawno wspominałem w kontekście komponentów zarządzanych JSF, które działają w zasięgu (ang. scope) session oraz application, więc z wielkim zadowoleniem przyjąłem uwagę Piotra. Jakby jeszcze było mało, właśnie dzisiaj natrafiłem na ciekawą wzmiankę o tym w artykule Using Java Persistence with JavaServer Faces Technology. Podsumowaniem mogłoby być stwierdzenie, że z prostotą w Java EE 5 idzie również większa odpowiedzialność i jest to przykład czułego miejsca w naszych aplikacjach korzystających z Korporacyjnej 5-tki. Wielkie dzięki Piotr za wychwycenie błędu! Jak zauważyłem, Piotr również spisuje swoje doświadczenia na stronie Xoft.pl, więc może odwdzięczę mu się tym samym?! ;-)

Wracając do artykułu to wspomnę, że natrafiłem na kilka miejsc, których nie miałem świadomości istnienia.

Jednym z nich był mechanizm DI w przypadku komponentu zarządzanego JSF z serwera aplikacyjnego (adnotacja @PersistenceContext) oraz samego środowiska JSF - plik faces-config.xml. Jeśli w konstruktorze korzystamy z obu elementów to z oczywistych względów DI z serwera nie będzie jeszcze wykonane i możemy być zaskoczeni nieprzyjemnym NullPointerException. Więcej o tym w kolejnych notatkach albo nawet i artykule.

Inną kwestią, która mnie zaskoczyła, było wykorzystanie JPA z JTA i uruchomienie EntityManager.merge po wywołaniu EntityManager.getTransaction. Jest to niemożliwe w konfiguracji JTA i kończy się wyjątkiem Exception Description: Cannot use an EntityTransaction while using JTA. W zasadzie jest to bardzo logiczne, że to monitor transakcyjny serwera aplikacyjnego Java EE zarządza transakcjami, ale możnaby oczekiwać, że...zostawiam dywagacje na później.

I na koniec coś, co oczekuje właściwego nagłośnienia, ale przy święcie nie mógłbym o tym nie wspomnieć - JAVArsovia. Grupa Warszawa JUG przygotowuje się do swojego debiutu jako organizator pierwszej konferencji-warsztatów technologii Java, która odbędzie się na Wydziale MIMUW. Więcej w kolejnej notatce...niebawem. Czas pozbierać wszystkie dane i rozpocząć promocję imprezki. Chciałbym, aby podsumowaniem sobotniej konferencji JAVArsovia był toast na Polach Mokotowskich, ale jak będzie zobaczymy. Prelegenci są, sala jest, chętni również, więc poza plakatem i promocją na forach jest wszystko. Dobrze byłoby rozpoczać promocję właśnie dzisiaj - 1 czerwca 2007. Jeszcze jest kilka godzin ;-)

8 komentarzy:

  1. Na dobry początek dobra nazwa! JAVArsovia jest super! Jeszcze tylko jakieś fajne logo by się przydało. Znasz Jacek jakichś grafików-magików? Ja wiem że znasz conajmniej jednego, tylko nie wiem czy o tym wiesz :) Kolega z pracy Wojtek K

    OdpowiedzUsuń
  2. Racja! Całkowicie o jego umiejętnościach zapomniałem. Dziękuję Mariusz! Przyjaciół poznaje się w biedzie ;-)

    OdpowiedzUsuń
  3. Jacek, niestety muszę Cię zmartwić, że kod który napisałeś jest może i pouczający - ale w przypadku PostgreSQL bezsensowny. PostgreSQL nie wspiera transakcji XA. Nie zmieni tego żaden driver nawet taki który udaje XA. Doskonały tekst na ten temat napisał jakiś czas temu Colin Sampaleanu: http://blog.exis.com/colin/archives/2006/02/17/jta-does-not-equal-automatic-support-of-two-phase-commit/

    Artur Karazniewicz

    OdpowiedzUsuń
  4. Witaj Arturze!

    Rozpocznę od stwierdzenia, że trudno mnie zmartwić, a wytknięcie mi błędu w tekście, który publikuję, uważam, za sukces, który z pewnością mnie nie zmartwi, a wręcz przeciwnie. Właśnie taka była idea Notatnika - publikować wiedzę inspirując społeczność ludzi zainteresowanych technologiami Java do przemyśleń, chęci dzielenia się własnymi doświadczeniami i co najważniejsze oczekując krytycznego spojrzenia na moją działalność. W efekcie, uzyskam (i wierzę, że inni również) efekt propagowania słusznego postrzegania otaczających nas technologii i zwiększenia naszej świadomości o ich znaczeniu w rozwiązaniach informatycznych, które tworzymy.

    A odnośnie JTA to kolejna uwaga, która nie powinna jednak nikogo zmartwić, użycie konfiguracji JTA wskazuje na oddelegowanie zarządzania transakcjami do serwera aplikacyjnego Java EE 5, a to niekoniecznie musi pociągać za sobą wykorzystania transakcji rozproszonych, XA. Wszystko zależy od konfiguracji źródła danych, z którego korzysta dostawca JPA w serwerze. Użycie JTA może być mylnie odebrane, że mamy do czynienia z transakcjami rozproszonymi, ale sprowadza się to do możliwości monitora transakcyjnego w serwerze aplikacyjnym oraz zarządzanego zasobu, w tym przypadku bazy danych.

    Dziękuję za komentarz i zapraszam do następnych. Postaram się skomentować wpis szerzej w Notatniku, jeśli nie masz nic przeciwko. Wartościowe komentarze warto nagłaśniać. Twój pasuje do tej kategorii idealnie.

    Tym razem Ci się nie udało mnie zmartwić, ale może następnym razem?! Próbuj ;-)

    OdpowiedzUsuń
  5. Jacek, proszę bardzo. Chętnie podyskutuję bo uważam ten temat za szczególnie interesujący. Oczywiście JTA!=XA, niemniej delegowanie obsługi transakcji do kontenera w przypadku JPA, bez transakcji rozproszonych, uważam za overkill.

    OdpowiedzUsuń
  6. overkill? Nie może być, że to piszesz (albo, że ja to piszę bez dokładnego sprawdzenia).

    Podeprę się kilkoma wycinkami ze specyfikacji JPA 1.0:

    5.5 Controlling Transactions (strona 118):

    A container-managed entity manager must be a JTA entity manager. JTA entity managers are only specified
    for use in Java EE containers.

    oraz

    Both JTA entity managers and resource-local entity managers are required to be supported in Java EE
    web containers and EJB containers.Within an EJB environment, a JTA entity manager is typically used.
    In general, in Java SE environments only resource-local entity managers are supported.

    i dalej w sekcji 5.5.1 JTA EntityManager:

    An entity manager whose transactions are controlled through JTA is a JTA entity manager. A JTA
    entity manager participates in the current JTA transaction, which is begun and committed external to the
    entity manager and propagated to the underlying resource manager.

    a odnośnie 5.5.2 Resource-local EntityManagers:

    An entity manager whose transactions are controlled by the application through the EntityTransaction
    API is a resource-local entity manager. A resource-local entity manager transaction is mapped
    to a resource transaction over the resource by the persistence provider. Resource-local entity managers
    may use server or local resources to connect to the database and are unaware of the presence of JTA
    transactions that may or may not be active.

    Co mi mówi, że obojętnie, czy dotykamy XA, czy nie, użycie trybu JTA jest zalecane, wręcz wymagane, w środowisku serwera Java EE 5 i zmniejsza ilość kodu pisanego przez programistę delegując zarządzanie transakcjami do serwera.

    Sam fakt, czy sterownik JDBC wspiera XA to całkowicie inny temat i nie dotyczy JPA bezpośrednio (chyba, żeby potraktować persistence.xml, gdzie definiuje się dostęp do bazy danych jako konfigurację XA dla JPA).

    OdpowiedzUsuń
  7. Przepraszam, nie do końca jasno się wyraziłem i dokonałem pewnego skrótu myślowego, pewnie dlatego, że od paru ładnych lat przywykłem do dobrodziejstw Springa ;). Czemu uważam to za overkill? To przekonanie fundamentalne ;). Bo jeśli nie używamy XA to co daje nam JTA i delegacja obsługi transakcji do kontenera - ano daje nam TYLKO zarządzanie demarkacją (jakie jest na to Polskie słowo?) - której zresztą, w przykładowej aplikacji, nie używasz, a może szkoda (dużo lepiej by to wyglądało gdyby użyć zamiast ręcznego zarządzania transakcjami - CMT oraz @TransactionAttriute - a tak to naprawdę aplikacja wygląda jakby wciśnięto do niej JTA lekko na siłę). Ale wracając do tematu - cóż, ale demarkację możemy mieć w bardzo łatwy sposób bez kontenera. Znowu powrócę do mojego ulubionego springa. Dlatego uważam to za overkill. Nie wspominając, że uturdnia nam to koszmarnie Unit Testy aplikacji out-of-the-container. Reasumując, jeśli tylko nie musimy, a w przypadku nie korzystania z XA - nie musimy, nie komplikujmy. Oczywiście to moje zdanie - ale to jak spór między Gavinem (Seam) i Rodem (Spring).

    Artur

    OdpowiedzUsuń
  8. Też jestem zainteresowany XA z PostgresQL. Nie wiem komu wierzyć, więc może i Wy zerkniecie w link
    http://www.saddi.com/software/news/archives/56-TranQL-Connector-for-PostgreSQL.html
    Myślę, że to wnosi co nieco w temacie

    pozdrawiam

    OdpowiedzUsuń