Wracając do tematu przewodniego, czyli zarządzaniu transakcjami w Spring Framework to udało mi się pozbyć kolejnej zależności od świata zewnętrznego w mojej aplikacji bez straty oferowanej przez nią funkcjonalności. Niedługo trwało, abym całkiem przypadkowo natrafił na rozwiązanie kwestii konieczności istnienia springowej adnotacji @Transactional do oznaczenia metod klasy jako transakcyjnej, o której wspominałem w notatce Apache Wicket z JPA z pomocą Spring Framework i Apache Maven 2, gdzie pisałem:
Najciekawszym elementem artykułu, jakkolwiek o Wicket, jest sama konfiguracja Springa, w taki sposób, że w żaden sposób nie wpłynął na inne pliki aplikacji. W zasadzie mógłbym wyrzucić Springa z aplikacji i nie wymagałoby to żadnej zmiany (poza klasą pl.jaceklaskowski.wicket.model.OsobaDaoImpl, gdzie użyłem adnotacji @Transactional, bez której babranie się z konfiguracją xmlową byłoby dla mnie marnotrawstem czasu)
Wystarczyło zapoznać się z sekcją 12.7. Transaction Management w dokumentacji Spring Framework 2.5.2, abym ostatnią rzecz, jaka wskazywała na użycie Spring Framework w aplikacji - adnotację @Transactional - zdjął z klasy pl.jaceklaskowski.wicket.model.OsobaDaoImpl.
Zmiana w pliku konfiguracyjnym Springa - applicationContext.xml polegała na dodaniu następujących elementów:
xmlns:aop="http://www.springframework.org/schema/aop"Oczywiście koniecznym byłoby dodanie również kilku(nastu?) projektów zależnych związanych z obsługą AOP w Spring, jednakże Maven sprowadził temat do dodania spring-aspects jako jedynej koniecznej zależności projektu w pom.xml.
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
<aop:config>
<aop:pointcut id="osobaDaoMethods"
expression="execution(* pl.jaceklaskowski.wicket.model.OsobaDao.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="osobaDaoMethods" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="create*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<dependency>Jest jeszcze projekt spring-aop, który mógłby wskazywać, że to właśnie jego należałoby dodać, ale testy wskazały, że tak nie jest i to właśnie spring-aspects jest tym, którego potrzebuję.
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
Dla kompletności podaję pełen plik applicationContext.xml, który pozwolił mi na wykorzystanie Spring Framework bez jego interferencji z moimi klasami aplikacji.
<?xml version="1.0" encoding="UTF-8"?>Jeśli kiedykolwiek przyjdzie mi do głowy pomysł pozbycia się Springa z aplikacji to zadanie sprowadza się teraz do usunięcia pliku applicationContext.xml. Niesamowite, jakie możliwości drzemią w Springu. Dodając do tego bezinwazyjne oznaczenie klasy encji jako encji z użyciem orm.xml (to już część Java EE) połączenie dwu środowisk - serwera aplikacyjnego Java EE 5 oraz Spring Framework - wydaje się być obowiązkową architekturą dla większości aplikacji z jakimi ostatnio miałem przyjemność pracować. I jak tu zasnąć po takich wrażeniach?! ;-)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<context:annotation-config />
<bean id="osobaDao" class="pl.jaceklaskowski.wicket.model.OsobaDaoImpl" />
<bean id="wicketApplication" class="pl.jaceklaskowski.wicket.WicketDemoApplication" autowire="byName">
<!-- wszystkie właściwości ustawiane po nazwie - wiele dzieje się poza naszą kontrolą -->
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="hsqlDatasource" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="hsqlDatasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:wicket" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="hsqlDatasource" />
</bean>
<aop:config>
<aop:pointcut id="osobaDaoMethods"
expression="execution(* pl.jaceklaskowski.wicket.model.OsobaDao.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="osobaDaoMethods" />
</aop:config>
<tx:annotation-driven />
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="create*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
</beans>
No coz-od siebie dodam anegdote uslyszana od Alefa Arendsena. Podobno implementacja EJB3 w Weblogicu powstala jako "cwiczenie prkatyczne" ktore Rod Johnson i Arendsen wlasnie urzadzili sobie w ramach wykorzystywania mozliwosci Springa. Zajelo im to raptem kilka godzin, a trafilo gdzies do uszu ludzi z BEA-ktorzy wykorzystali to poczatkowo do testow, a potem zaczeli wcielac do samego serwera.
OdpowiedzUsuńNie wiem, na ile to prawda, na ile anegdota - ale swietnie ilustruje mozliwosci springa. I nawet pomimo tego ze zawsze troche tego XML-a zostanie(szczegolnie w przypadku tych modulow Springa, ktore nie dorobily sie jeszcze wlasnych definicji przestrzeni nazw w XML), mysle ze warto(wystarczy tylko zobaczyc jak mocno inspirowane zestawieniem Spring+Hibernate byly JPA i EJB3 i przyjrzec sie temu, czym tak naprawde beda profile w JEE 6)
Witaj Jacku,
OdpowiedzUsuńtemat ciekawy, zwłaszcza że niedawno zacząłem zabawę ze Springiem i doszło do tematu transakcji. Zanim zacznę zadawać głupie pytania, to może polecisz jakiś ciekawy artykuł, który dogłębnie rozwinie ten temat? Interesuje mnie zwłaszcza w aspekcie pracy w kontenerze j2ee (a konkretnie was 6.1), w połączeniu z hibernate'm. W zwykłych ejb'kach ustawianie propagacji transakcji było proste, w RAD'zie dało się wszystko wyklikać;) Tu widzę, że używasz AOP, a ja skłaniam się jednak ku annotacjom @Transactional. Mam małe problemy (niby wszystko działa, ale nie do końca wiem dlaczego - znając życie zapewne to kwestia konfiguracji :) (websphere'owy transactionManager, LocalSessionFactoryBean, OpenSessionInViewFilter...)
PS. Jak poszła SCEA? Trzeba przyznać, że zadania były trudne bo zawierały mnóstwo błędów...
Artykuł powiadasz? Hmm, jedynie co przychodzi mi do głowy to dokumentacja Springa i Google - potencjalnie książki, ale nie spodziewałbym się wiele o tx w nich. Nie mam nic ponad to.
OdpowiedzUsuńOdnośnie WAS 6.1, to skorzystaj z rozszerzenia EJB3 (EJB3 Feature Pack), które dodaje jego obsługę w serwerze, który wciąż jest na poziomie Java EE 1.4. Testowałem i opisałem. Już niedługo "opisałem" ujrzy światło dzienne.
Użycie AOP vs @Transactional wynikało z potrzeby uniezależnienia aplikacji od środowiska uruchomieniowego. Chciałem, aby aplikacja była czysta od jakichkolwiek dodatków czy to z EJB3, czy JPA, czy w końcu Spring. Udało się i stąd wydawało mi się słusznym, aby o tym napisać. Na razie Springa traktuję jako dodatek i nic poza tym. Docelowym środowiskiem jest serwer aplikacyjny Java EE 5. Ale do tego jeszcze trochę czasu upłynie. Przed tym krokiem chciałbym jeszcze wdrożyć OSGi i zobaczyć jego zalety w aplikacji webowej opartej o Wicket (jeśli w ogóle takie zalety będą widoczne, poza tymi standardowymi - większa modularyzacja, itp.). Gdybym wiedział, czego w WAS 6.1 dotykasz, jaką masz konfigurację serwera i aplikacji mógłbym pomóc więcej. Pisz na priv.
Re PS. SCEAę zarzuciłem, kiedy otrzymałem diagramy UMLowe do rozrysowania i jedynie 2 tygodnie. To było dla mnie za wiele i po jednym dniu stwierdziłem, że poddaję się. Poszukałem sobie coś ciekawszego i tak SCEA poszła w zapomnienie. Widzę, że SCEA 5 jeszcze nie ma, ale na otarcie łez wydano SCWCD 5, więc teraz o tym myślę. Dodatkowo rozpoznaję praktycznie UMLa, więc może kiedy SCEA 5 wyjdzie, ja już będę gotów. Na razie nie jestem.
Cześć,
OdpowiedzUsuńBiorąc pod uwagę nasze przekomarzania, pewnie się tego Jacek spodziewasz, ale oczywiście IMHO linia podziału przebiega między Spring a EJB (dokładnie częścią EJB czyli Session Bean i Message Driven Bean, czyli bez JPA), a NIE między Spring a Java EE.
Nie widzę też w Springu tego "wiele" na jego poprawne zestawienie (ani też nie widzę tego "bez większego wysiłku umysłowego" w EJB).
A już w żadnej mierze - o czym zresztą jakiś czas temu na grupie WJUG było - nie można przeciwstawiać serwera aplikacyjnego i Spring. Kombinacja serwer aplikacyjny JEE + Spring jest bardzo mocną platformą na której można budować serwerowe aplikacje.
Trzymałbym się też rzeczywistości, która jasno pokazuje, że "model Spring" w sposób absolutny zdominował "model EJB" i do "zabójstw" nie dochodzi ;-). Wręcz przeciwnie - dzisiaj wielu (większość ???) programistów szczególną uwagę przywiązuje do możliwości łatwego testowania swojego kodu - problem, którego akurat EJB3 (znowu dotyczy Session i Message-Driven Beans) wciąż nie rozwiązuje i nic "gotowego" tu nie oferuje.
Aby podtrzymać DOBRĄ praktykę przekomarzania się, to przyznam, że Twojej analogii o app serwerze jako "aplikacji opartej o Spring" nie załapałem ;-).
To w sumie też już było kilka razy poruszane, ale moim skromnym zdaniem w fajny sposób pokazałeś, że CZASAMI te zniesławione ostatnimi czasy deployment deskryptory (nawet XMLowe) mogą być lepszym podejściem (biorąc pod uwagę ZAŁOŻENIA) od będących-cool adnotacji. Wybór "adnotacje vs. zewnętrzna konfiguracja" jest kwestią indywidualną danego programisty. Czasem lepiej pasuje jedno, czasem drugie. Akurat mapowanie OR, czy konfiguracja transakcji należą moim zdaniem do tych, gdzie - zwłaszcza w dłuższej perspektywie - zewnętrzna konfiguracja ma przewagę nad adnotacjami. Marzy mi się takie rozszerzenie do IDE, w którym będzie refaktoring zamieniający jednym kliknięciem adnotacje na konfigurację i odwrotnie...
Pozdrawiam,
Waldek Kot
@popaprany,
OdpowiedzUsuńZ tą anegdotą, to coś chyba nie do końca. Bo w WebLogic Server implementacja EJB3 bazuje na 10-letniej już implementacji EJB. To co zostało zaimplementowane przy pomocy Spring, to wstrzeliwanie zależności (czyli stosunkowo niewielka część EJB3). Po prostu zdroworozsądkowo było nie wymyślać koła i skorzystać z tego co jest dobre. Zresztą Rod ani Alef nie mają dostępu do kodu źródłowego WLS, a Spring został już dawno wewnątrz BEA uznany za conajmniej równoprawny model programistyczny do EJB. Z tego co mi się udało zaobserwować, to najpierw ludzie z developmentu BEA postanowili użyć Spring jako kontenera aplikacyjnego w ramach przejścia na OSGi (mSA - micro Service Architecture), a potem, gdy mSA trafiło do WLS wręcz bezpośrednio wykorzystano funkcjonalność Spring DI do implementacji EJB3. Swoją drogą to odbyło się to w taki sposób, że BEA i Spring uruchomili projekt Pitchfork, który jest notabene niezależny od kontenera (choć jedyne mi znane w tej chwili implementacje Pitchfork to - produkcyjna - w WLS i - testowa - w Tomcat). W Pitchfork jednym z głównych developerów jest Michael Cheng, jeden z core developerów EJB3 w WLS, zresztą podobnie jak jednym z core developerów Spring-OSGi jest Andy Piper, dawniej architekt kontenera EJB w WLS oraz guru od CORBA i RMI-over-IIOP. A teraz dev lead produktu WebLogic Event Server, w którym za podstawowy model programowania przyjęto... Spring.
Jak widać sporo tych zależności między Spring a BEA (w obu kierunkach).
Szepnę tylko: stay tuned - there's more comming to the theathers near you ;-)
Pozdrawiam,
Waldek Kot
Panowie,
OdpowiedzUsuńSpring prowadzi do "spagetti xml".
Uzywam spring-a od 2004 i moje pierwsze reakcje byly podobnie entuzjastyczne. Jednak juz w srednich projektach koniguracja springa to dobre 20 plikow, a odkad dodali import zrobila sie z tego niezla makabra.
IoC i testowalnosc sa nie do zaprzeczenia, ale spring nie ma modularnosci. Poza tym XML nawet ten z "naming space" to przerost formy nad trescia.
Przyszedl czas na cos lzejszego - Guice to odpowiedz!
oczywiscie w polaczeniu z bibliotekami springa, ale nie z kontenerem.
Btw. Aop w springu jest strasznie kiepskie, ale nie bede sie tu rozwodzil - wyatarczy spojrzec na koszmarny stack trace...
Jeżeli wgłebic się w dokumentacje Springa lub wpisy na blogach Spring teamu to jest tam jasno powiedziane:
OdpowiedzUsuńAnotacje są tylko dodatkowym sposobem budowania "blueprint" czyli inforamcji w jakie mamy komponenty, jak są ze sobą połączone i jak są obudowywane...
Oprócz anotacji pozostaje jeszcze stary poczciwy XML albo Spring Java Configuration Project.
A najpiekniejsze jest to że można robic mix tych konfiguracji