Presentation is loading. Please wait.

Presentation is loading. Please wait.

Mastering Transactions In Java Transactions: Basics.

Similar presentations


Presentation on theme: "Mastering Transactions In Java Transactions: Basics."— Presentation transcript:

1

2 Mastering Transactions In Java

3 Transactions: Basics

4 In the world of programming a Transaction is a series of actions that must occur as a group. If any portion of the group of actions fails, the entire Transaction fails. Transactions: Basics This lecture is based in part on the book Java Transaction Design Strategies by Mark Richards. Mark Richards This lecture is based in part on Java Transaction Processing by Mark Little, Jon Maron and Greg Pavlik. Java Transaction Processing

5 A.C.I.D. is the well-known acronym for the characteristics of a successful and valid transaction. Atomicity Consistency Isolation Durability These principles were first described by James Gray in the late 1970s and in 1983 the acronym A.C.I.D. was coined by Andreas Reuter and Theo Härder. Transactions: Basics

6 Atomicityfollows the metaphor of the Atom. You cannot have half an atom. If a transaction does not complete perfectly, it gets undone and the database should be left in a state as if nothing at all ever happened. Transactions: Basics

7 Consistencychange must take the database from one consistent state before the transaction started to another consistent state after the transaction has finished. Referential integrity must be maintained. The data meets all rules for validation. Numeric fields must only hold numeric data, etc. Transactions: Basics

8 Isolationby its nature a transaction consists of several small steps. All the intermediate steps must be completed before the entire transaction can be called complete. While the transaction is in progress but not yet complete, the in-progress changes must be hidden or isolated from the rest of the database and other transactions. If I deduct money from the checking account and then deposit that money in the savings account, the checking deduction must not be visible to anyone until the transaction is done. Transactions: Basics

9 Durabilityonce a transaction is deemed complete, the transaction will not be lost. Dont announce success until everything is committed. Transaction Loga common strategy used to back up the contents of the transaction. Transactions: Basics

10 Transactions: Local Transactions

11 A Local Transaction is a punt. We let the database handle our transactions entirely. This works fine if our Logical Unit of Work [LUW] consists of exactly one query. Not exactly what we have in mind when we think of a transaction. Transactions: Local Transactions

12 If we want to do two things, such as subtract from a savings account and deposit into a checking account, a Local Database transaction is not much help. If we subtract $100 from the savings account and then the system crashes before we get the deposit donewe just lost $100. So, already, we have reached the end of the usefulness of a database-local transaction. Java offers several ways to help us out. Transactions: Local Transactions

13 Transactions: Gotchas In Java

14 In the Java world we are fortunate to have great APIs such as the JTA (Java Transaction API) Thanks to Rod Johnson, we have the wonderful Spring Framework. After the horror story that was EJB2.1 Entity beans, JPA was a reason to pump your fist in joy. Thanks to EJB 3.0, we have some great frameworks that take away all the peril of using transactions… right? Transactions: Gotchas In Java

15 Consider this simple code. It runs flawlessly. id So this JPA code will happily insert the deposit and return the id of the generated row, right? Transactions: Gotchas In Java public class JpaBankServiceImpl EntityManager entityMan; public long makeDeposit( Deposit deposit ) throws Exception { entityMan.persist( deposit ); return deposit.getDepositId(); }

16 Consider this simple code. It runs flawlessly. id So this code will happily insert the deposit and return the id of the generated row, right? Nope! It wont throw an exception, will return 0 and leave the database untouched. It wont do a damn thing! Transactions: Gotchas In Java public class JpaBankServiceImpl EntityManager entityMan; public long makeDeposit( Deposit deposit ) throws Exception { entityMan.persist( deposit ); return deposit.getDepositId(); }

17 What? The newbie asks. What went wrong? Nothing. For this to work you have to wrap it in a transaction. But it wont tell you anything is wrong. Transactions: Gotchas In Java public class JpaBankServiceImpl EntityManager entityMan; public long makeDeposit( Deposit deposit ) throws Exception { entityMan.persist( deposit ); return deposit.getDepositId(); }

18 Your changes were placed in the L1 object cache. transaction object cache But only a transaction tells JPA to synchronize its object cache with the database. Transactions: Gotchas In Java

19 Sidebar: What is the Object Cache? When an object and its dependencies are pulled from the database, it may require several queries. L1 The L1 transaction Object Cache is part of every EnityManager and is not shared. Not to be confused with the L2 shared cache, stored in the EntityManagerFactory, which is visible to all EnityManager s. Each EnityManager keeps its own Object Cache.

20 persist Object Cache In JPA, when you persist an object, it only writes the object to its Object Cache. only commit of a transaction JPA only writes its object to the database upon the commit of a transaction. no transaction no commit So, no transaction = no commit. Transactions: Gotchas In Java

21 Transactions: Gotchas In Java: Spring

22 Spring does a lot for us but we still need to think and understand. Remember there are two broad categories: programmatic transactions declarative transactions programmatic Using programmatic transactions, we have to code everything. declarative annotation Using declarative transactions, we add an annotation to our code and a framework such as Spring does the rest, right? Transactions: Gotchas In Java: Spring

23 @Transactional In the case of Spring, our declarative model asks us to provide an annotation such Transactions: Gotchas In Java: Spring public class SpringBankServiceImpl EntityManager public long makeDeposit( Deposit deposit ) throws Exception { entityMan.persist( deposit ); return deposit.getDepositId(); } You test it again and no error, no exception and no change to the DB.

24 The problem is, like with all things Spring, you need to update the Spring configuration file. Transactions: Gotchas In Java: Spring transactionManager bean So, transactionManager must be a Spring bean that is defined elsewhere in your Spring configuration file. interceptor Spring will implement this using a cool Spring feature called an interceptor that in turn will use another

25 Okaysweetnow were good. Transactions: Gotchas In Java: Spring public class SpringBankServiceImpl EntityManager public long makeDeposit( Deposit deposit ) throws Exception { entityMan.persist( deposit ); return deposit.getDepositId(); } But wait a second. There are a lot of choices involved in setting up a transaction. Were using the defaults here.

26 @Transactional When we by itself with no parameters, what are the default values for things like propagation mode, the read-only flag and transaction isolation? Most importantly, what happens when we need to roll back? Transactions: Gotchas In Java: Spring

27 @Transactional When we use a the default values make it as if we had written this: Most importantly, the transaction will not roll back on a checked exception. Transactions: Gotchas In Java: read-only=false, propagation=REQUIRED, isolation-level=READ_COMMITTED )

28 Heres a great example from Mark Richards: Transactions: Gotchas In Java: propagation=Propagation.SUPPORTS) public long insertDeposit( Deposit deposit ) throws Exception { // JDBC insert code } Notice this is read-only. So, what happens? A. It throws a read-only connection exception. B. It inserts the deposit and commits the data. C. It does nothing because the propagation level says supports and there is no transaction to support.

29 Heres a great example from Mark Richards: Transactions: Gotchas In Java: propagation=Propagation.SUPPORTS) public long insertDeposit( Deposit deposit ) throws Exception { // JDBC insert code } Notice this is read-only. So, what happens? A. It throws a read-only connection exception. B. It inserts the deposit and commits the data. C. It does nothing because the propagation level says supports and there is no transaction to support. WTF?

30 Transactions: Gotchas In Java: propagation=Propagation.SUPPORTS) public long insertDeposit( Deposit deposit ) throws Exception { // JDBC insert code } B. It inserts the deposit and commits the data. The read-only flag is only honored when there is a transaction. Since its SUPPORTS and there was no already- started transaction to support, it never got one. The JDBC code used a local (database) transaction and committed the code.

31 Transactions: Gotchas In Java: propagation=Propagation.REQUIRED) public long insertDeposit( Deposit deposit ) throws Exception { // JDBC insert code } A. It throws a read-only connection exception. B. It inserts the deposit and commits the data. C. It does nothing because the readOnly flag is set to true. Okay, what if we make the Propagation REQUIRED ?

32 Transactions: Gotchas In Java: propagation=Propagation.REQUIRED) public long insertDeposit( Deposit deposit ) throws Exception { // JDBC insert code } A. It throws a read-only connection exception. B. It inserts the deposit and commits the data. C. It does nothing because the readOnly flag is set to true. Okay, what if we make the Propagation REQUIRED ? Because there was a transaction [ REQUIRED ], the readOnly flag was honored.

33 Transactions: Gotchas In Java: Spring There are a lot of hidden problems with all of the various propagation modes and you need to be very careful.

34 Transactions: Gotchas In Java: Spring Next, I asked: what happens when you need a roll public long transferCash( Transfer transfer) throws Exception { try { deductFromSavings( transfer ); depositIntoChecking( transfer ); return tranfer.getTransactionId(); } catch( Exception e ) { // log error throw e; } What if depositIntoChecking() throws a checked Exception? Does everything get rolled back?

35 Transactions: Gotchas In Java: Spring No! No! The update from deductFromSavings() is public long transferCash( Transfer transfer) throws Exception { try { deductFromSavings( transfer ); depositIntoChecking( transfer ); return tranfer.getTransactionId(); } catch( Exception e ) { // log error throw e; }

36 Transactions: Gotchas In Java: Spring In this scenario ( using default values) for both Spring and EJB 3, only runtime (unchecked) exceptions cause the transaction to roll back. When you code your annotation like this, the transaction will NOT roll back for any checked Why on earth would Spring or EJB be set up that way? The explanation is that there might be some exceptions that you can recover from. So, to not preclude that alternative, they are set up this way.

37 Transactions: Gotchas In Java: Spring So, the take away in Spring declarative transactions is that you must specify which checked exceptions warrant a roll rollbackFor=SQLException.class) The rollbackFor parameter takes either a single exception or an array of them. There is another alternative rollbackForClassName and yet another for noRollbackFor.

38 Transactions: 3 Alternative Models

39 Transactions: 3 Alternative Models There are three broad approaches to doing transactions in Java. Transaction Models These are known as Transaction Models. Local (database) Transactions Programmatic Transactions Declarative Transactions

40 Transactions: 3 Alternative Models: Local Local (database) Transactions Local (database) Transactions are an abdication on the part of the Java tier. The database does 100% of the work. The Connection is the closest you get can to the transactions. By turning off the setAutoCommit( false ); in your Java code you can achieve ACID over several database actions and by then calling either commit() at the end or rollback(); in the case of an Exception.

41 Transactions: 3 Alternative Models: Programmatic With Programmatic Transactions you write program logic to manage the transactions. transaction Instead of managing the Connection, you manage the transaction from your Java code.

42 public class SpringProgrammaticTransaction EntityManager em; JpaTransactionManager transManager = null; public void doTransfer( TransactionValues modifications ) { TransactionStatus ts = jtm.getTransaction( new DefaultTransactionDefinition() ); try { em.persist( modifications ); AcctState acctState = em.find( AcctState.class, modifications.getTransactionId() ); applyTransactionModifications( acctState, modifications ); em.persist( acctState ); transManager.commit( ts ); } catch( Exception e ) { transManager.rollback( ts ); } // Spring injected public void setTransManager( JpaTransactionManager transManager ) { this.transManager = transManager; } Transactions: 3 Alternative Models: Programmatic Spring

43 Transactions: 3 Alternative Models: Declarative With Declarative Transactions you signal your wishes for the transaction and rely on your understanding of the nuances of the annotations and their various attribute values. Another name for CMTContainer-Managed Spring uses EJB 3.0 In declarative transactions automatic roll-back is not a given after a checked exception occurs.

44 Transactions: 3 Alternative Models: Declarative public class EJB30DeclarativeBankingService implements BankingService EntityManager SessionContext TransactionAttributeType.REQUIRED ) public void transferMoney( Transfer transfer ) throws Exception { try { AcctInfo acctInfo = em.find( AccountInfo.class, transfer.getTransferId(); if( transferAcceptible( acctInfo, transfer ) ) { em.persist( transfer ); em.persist( acctInfo ); } catch( Exception e ) { ctx.setRollbackOnly(); }

45 Transactions: 3 Alternative Models: Declarative Spring public class SpringDeclarativeBankingService EntityManager =Propagation.REQUIRED, =Exception.class propagation=Propagation.REQUIRED, rollbackFor=Exception.class ) public void transferMoney( Transfer transfer ) throws Exceptio { em.persist( transfer ); AcctData acctData = em.find( AcctData.class, transfer.getTransferId() ); if( accountAgreesWithTransfer( transfer, acctData ) ) { acctData.applyTransfer( transfer ); }

46 Transactions: High Concurrency Strategies

47 Transactions: High Concurrency Strategies For many concurrent transactions, the transaction strategy changes. If your transactions take too long, you shorten the transaction. You remove operations such as reads and processing that do not need to be transactional.

48 Transactions: High Concurrency Strategies Naked readsyou read a value without a transactioneven though you are planning to update it. Another write could have gotten in there right after your read and then you would lose that update. Each read gets a version stamp and then after your optimistic read you trust but verify and compare the version stamp.

49 Transactions: High Concurrency public class BankingServiceImpl implements BankingService SessionContext unitName=banking ) EntityManager public void transferMoney( Transfer transfer ) throws Exception { try { AccountHolder holder = em.find( AccountHolder.class, transfer.getAccountId() ); Withdrawl withdrawl = sourceAccountContainsSufficientFunds( holder, transfer ) if( withdrawl != null ) { em.persist( withdrawl ); verifySpamBeingSent( holder ); verifyAddressSentToCatalogCompanies( holder ); verifyAccountIsEligibleForOverdraftProtection( holder ); verifySent OfferingToStopSpam( holder ); Deposit deposit = buildDepositFromTransfer( holder, transfer ); em.persist( deposit ); } catch( Exception e ) { ctx.setRollbackOnly(); }

50 Transactions: High Concurrency public class BankingServiceImpl implements BankingService SessionContext unitName=banking ) EntityManager public void transferMoney( Transfer transfer ) throws Exception { try { AccountHolder holder = em.find( AccountHolder.class, transfer.getAccountId() ); Withdrawl withdrawl = sourceAccountContainsSufficientFunds( holder, transfer ) if( withdrawl != null ) { em.persist( withdrawl ); verifySpamBeingSent( holder ); verifyAddressSentToCatalogCompanies( holder ); verifyAccountIsEligibleForOverdraftProtection( holder ); verifySent OfferingToStopSpam( holder ); Deposit deposit = buildDepositFromTransfer( holder, transfer ); em.persist( deposit ); } catch( Exception e ) { ctx.setRollbackOnly(); } Everything in black is included in the transaction. Bad!

51 Transactions: High Concurrency Strategies: Yes! public void transferMoney( Transfer transfer ) throws Exception { UserTransaction txn = null; try { AccountHolder holder = service.getAccountHolder( transfer.getAccountId() ); verifySpamBeingSent( holder ); verifyAddressSentToCatalogCompanies( holder ); verifyAccountIsEligibleForOverdraftProtection( holder ); verifySent OfferingToStopSpam( holder ); Withdrawl withdrawl = sourceAccountContainsSufficientFunds( holder, transfer ); Deposit deposit = buildDepositFromTransfer( holder, transfer ); txn = (UserTransaction) ctx.lookup( UserTransaction ); txn.begin(); service.makeWithdrawl( withdrawl ); service.makeDeposit( deposit ); txn.commit(); } catch( Exception e ) { if( txn != null ) { txn.rollback(); }

52 Transactions: High Concurrency Strategies: Yes! public void transferMoney( Transfer transfer ) throws Exception { UserTransaction txn = null; try { AccountHolder holder = service.getAccountHolder( transfer.getAccountId() ); verifySpamBeingSent( holder ); verifyAddressSentToCatalogCompanies( holder ); verifyAccountIsEligibleForOverdraftProtection( holder ); verifySent OfferingToStopSpam( holder ); Withdrawl withdrawl = sourceAccountContainsSufficientFunds( holder, transfer ); Deposit deposit = buildDepositFromTransfer( holder, transfer ); txn = (UserTransaction) ctx.lookup( UserTransaction ); txn.begin(); service.makeWithdrawl( withdrawl ); service.makeDeposit( deposit ); txn.commit(); } catch( Exception e ) { if( txn != null ) { txn.rollback(); } Everything in black is included in the transaction. Better!

53 Transactions: High Performance Strategies

54 Transactions: High Performance Strategies If your goal is high performance, then there is a bag of techniques. You abandon any transaction management in the Java layer. You revert to local transactions managed 100% by the DB. No transaction-guaranteed ACID across multiple queries

55 Transactions: High Performance Strategies Each read, update, delete rides in its own transaction that commits at the end of each statement. Compensation Strategy It uses a Compensation Strategy. Compensation Strategy A Compensation Strategy keeps track of the transaction steps that were committed. Compensation Strategy undo In case of an error, the Compensation Strategy reverses the transaction steps to undo the committed steps. Isolation No transaction Isolationdata is shared instantly.

56 Transactions: High Performance Strategies J2EE Activity Service for Extended Transactions (JSR 95) can serve as a Compensation Strategy framework. JBoss Business Activity Framework

57 public class TradingService { private CompController compController = new CompController(); private AcctDAO acctDao = new AcctDAO(); private TradeDAO tradeDao = new TradeDAO(); public void processTrade(TradeData trade) throws Exception { String compId = UUID.randomUUID().toString(); try { //start the compensation scope compController.startScope(compId); //get the original account values and set the acct balance AcctData acct = acctDao.getAcct(trade.getAcctId()); double oldBalance = acct.getBalance(); if (trade.getSide().equals("BUY")) { acct.setBalance(acct.getBalance() - (trade.getShares() * trade.getPrice())); } else { acct.setBalance(acct.getBalance() + (trade.getShares() * trade.getPrice())); } //insert the trade and update the account long tradeId = tradeDao.insertTrade(trade); compController.registerAction(compId, "insertTrade", tradeId); acctDao.updateAcct(acct); compController.registerAction(compId, "updateAcct", oldBalance); //close the compensation scope compController.stopScope(compId); } catch (Exception e) { //reverse the individual database operations compController.compensate(compId); throw e; }

58 Transactions: Questions?


Download ppt "Mastering Transactions In Java Transactions: Basics."

Similar presentations


Ads by Google