Transacties met Spring 2

 
03 april 2008

Ik ben fan van het Spring framework! Spring maakt het ontwikkelen van Java EE applicaties stukken eenvoudiger. Dit draagt mijn inziens bij aan zowel de kwaliteit van de applicatie als aan de snelheid van het ontwikkelen.

Spring 1 had als grootste nadeel de grote hoeveelheid XML configuratie die vaak noodzakelijk was. Dit is gelukkig in Spring 2 grotendeels opgelost. De voorbeelden hieronder zijn dan ook gemaakt in het Spring 2 formaat.

Spring sluit ook goed aan bij de visie van Sogyo rondom domein gedreven ontwikkelen; mits de inzet van Spring beperkt wordt tot alleen de “plumbing” lagen rondom het domein, en het domein zelf alleen uit de bekende POJO’s bestaat.

Laten we als voorbeeld de Spring ondersteuning voor transacties nemen. Dit laat mooi de “non intrusive” visie van het Spring framework zien. Java EE biedt standaard twee manieren om gebruik te maken van transacties:

De eerste manier is declaratief via EJB’s. Als je hiervoor kiest krijg je alle andere overhead van het gebruik van EJB’s er gratis en voor niets bij cadeau. Overigens heeft EJB 3 deze overhead gelukkig wel fors verminderd.

De tweede manier is programmatisch transactie management. Je code doet een JNDI lookup naar java:comp/UserTransaction, om een usertransaction object te verkrijgen. Vervolgens moet in de code op dit usertransaction object steeds weer begin() en commit() of rollback() aangeroepen worden.

Spring biedt een combinatie van beide bovenstaande manieren: declaratief transactiemanagement, maar dan met POJO’s. Naast dat Spring de mogelijkheid biedt, is het ook nog eens erg eenvoudig om te configureren. Allereerst moeten we een transactiemanager opnemen in de Spring configuratie. De onderstaande tag is hiervoor al voldoende:

<tx:jta-transaction-manager />

Vervolgens kan met behulp van Spring AOP aangegeven worden welke methodes transactioneel moeten worden. Spring 2 gebruikt voor AOP de AspectJ pointcut expression language. Stel we hebben een java package genaamd ‘nl.sogyo.voorbeeldapplicatie.service’. Deze package bevat een aantal interfaces waarvan de naam eindigt op Service. Om de implementatie van de methodes uit deze interfaces transactioneel te maken komt het volgende in de Spring configuratie te staan:

<aop:config>
    <aop:advisor
        pointcut="execution(* nl.sogyo.voorbeeldapplicatie.services.*Service.*(..))"
        advice-ref="txAdvice" />
</aop:config>  

<tx:advice id="txAdvice">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>

De transaction propagation attributen zijn hetzelfde als bij EJB’s. Dus er kan naast REQUIRED ook MANDATORY, SUPPORTS, REQUIRES_NEW, NEVER en NOT_SUPPORTED gebruikt worden.

Hetgeen rest is het desbetreffende object uit de Spring applicatiecontext ophalen, zodat Spring er een proxy object tussen kan schuiven. Wanneer we zelf het object instancieren met de new operator zal het dus niet werken. Verder blijft de code ongewijzigd. Dit heeft als voordeel dat de code ook buiten een container gedraaid kan worden, bijvoorbeeld in een unittest.


Werken met ?
Kijk dan bij onze mogelijkheden voor starters en/of ervaren IT'ers.


Categorieën: Development, Java (EE)

Tags: , , ,


Reacties (2)

  • Ralf Wolter schreef:

    Helaas is leesbaarheid relatief. Code of configuratie is direct leesbaar en je kunt aanwijzen waar het gebeurt. Dit effect gaat echter niet op voor een groter applicatie, waar je het over lijkt te hebbben met de verwijsing naar een grotere groep ontwikkelaars. In dat geval is een lange lijst net zo onleesbaar als volledige transparantie.

    Het idee is dat het voor de grote groep niet uitmaakt of het wel of niet aanwezig is, je applicatie dient het zelfde te werken of je gewoven services nu wel of niet erin gewoven zit. Alleen de specfieke service werkt niet en dat zal eenvoudig te traceren zijn of je nu wel of geen AOP gebruikt. Het is immers die specifieke service die niet functioneert.

    Het probleem in de meeste applicaties is dus niet dat de koppelingen verborgen zijn, maar juist dat het algehele gedrag te veel afhankelijk is van de combinatie van services, dus services niet niet voldoende opzichzelf staan.

    Proxies beloven vaak het zelfde als AOP. In theorie is het een zelfde koppeling als AOP: een transparante event manipulatie. Helaas lijken proxies in de praktijk last te hebben van het net-niet sindroom. Zoals het werkt net-niet of het is net-niet transparant.

    Proxies zou ik in de meeste gevallen afraden, maar goed ik zou ook Spring in de meeste gevallen afraden.

    Geplaatst op 03 april 2008 om 23:22 Permalink

  • Ivo Limmen schreef:

    Wat ik nou zo jammer vind van het gebruik van Spring is dat je configuratie enorm kan uitgroeien. In het project waar ik momenteel mee bezig ben hebben wij zes verschillende applicatie contexts die een logische indeling hebben.
    Bij een refactorslag moet ik al deze configuratie nalopen om te kijken of niet niet ergens een koppeling verbroken heb.
    Tevens vind ik persoonlijk dat het gebruik van AOP erg onleesbaar vind; het is mooi compact maar als je in een grote groep ontwikkelaars zit kies ik sneller voor een eenvoudige oplossing die meer leesbaarheid en duidelijkheid geeft dan een stuk code die gaaf, compact en onduidelijk is voor een grote groep ontwikkelaars.
    Zo is het ook mogelijk om een simpele proxy class te maken (met een InvocationHandler) die alle methoden in een transactie laten draaien.

    Geplaatst op 03 april 2008 om 21:27 Permalink