Successfully reported this slideshow.

Ruslan Platonov - Transactions

1,193 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Ruslan Platonov - Transactions

  1. 1. Transaction Management Patterns Ruslan Platonov Lead Java Developer at C.T.Co
  2. 2. Definition of Transaction <ul><li>Transaction = Logical unit of work
  3. 3. Provides ACID </li></ul><ul><ul><li>Atomicity
  4. 4. Consistency
  5. 5. Isolation
  6. 6. Durability </li></ul></ul>
  7. 7. Typical Issues <ul><li>Lack of knowledge in the area
  8. 8. Not clear understanding (knowledge) of transaction management strategy on application level
  9. 9. DB team should care about transactions </li></ul>
  10. 10. All these things results in anti patterns inside our projects
  11. 11. Ex 1: Auto-commit <ul><li>hibernate.connection.autocommit = true
  12. 12. hibernate.connection.release_mode = after_statement </li></ul>
  13. 13. Ex 2: Programmatic Control Connection connection = null ; Statement statement = null ; try { Class. forName ( &quot;driverClass&quot; ); connection = DriverManager.getConnection( &quot;url&quot; , &quot;user&quot; , &quot;pass&quot; ); connection.setAutoCommit( false ); statement = connection.createStatement(); // Execute queries statement.executeUpdate( &quot;UPDATE Table1 SET Value = 1 WHERE Name = 'foo'&quot; ); statement.executeUpdate( &quot;UPDATE Table2 SET Value = 2 WHERE Name = 'bar'&quot; ); connection.commit(); } catch (SQLException ex) { if ( null != connection) { connection.rollback(); } } finally { if ( null != statement) { statement.close(); } if ( null != connection) { connection.close(); } }
  14. 14. Ex 3: Incorrect Demarcation @ Repository public class UserRepository { @ Transactional public void save(User user) { ... } } @ Component public class UserService { @ Autowired private UserRepository repo ; public void disableUsers( List<User> usersList) { for (User user : usersList) { repo .save(user); } } }
  15. 15. Ex 4: Batch processing @ Component public class LongRunningJob { @ Autowired private RecordRepository repository ; @ Transactional public void updateRecords() { for ( int i = 1; i < 100000; i++) { Record rec = repository .getById(i); repository .updateTimeStamp(rec, new Date()); } } }
  16. 16. Consequences <ul><li>Data Inconsistency
  17. 17. Performance Issues
  18. 18. High load on DB </li></ul>
  19. 19. How can we improve our code?
  20. 20. Some Ideas <ul><li>Use declarative definition
  21. 21. Add transparency
  22. 22. Decouple from application logic, make flexible
  23. 23. Simplify maintenance </li></ul>
  24. 24. Transaction Models
  25. 25. Transaction Models <ul><li>Local
  26. 26. Programmatic
  27. 27. Declarative </li></ul>
  28. 28. Local Transaction Model <ul><li>Transactions are handled by DB
  29. 29. Developer manage connections not transaction </li></ul>
  30. 30. Local Transaction Model Example
  31. 31. Local Transaction Model Considerations <ul><li>Not recommended
  32. 32. Suitable for simple cases
  33. 33. Plenty of room for errors
  34. 34. Cannot maintain ACID when coordinating multiple resources (DB, JMS) </li></ul>
  35. 35. Programmatic Transaction Model <ul><li>Developer manages transactions not connections
  36. 36. Developer is responsible for starting and terminating transactions </li></ul>
  37. 37. Programmatic Transaction Model Example
  38. 38. Programmatic Transaction Model with Decorator public class AccountServiceDecorator implements AccountService { private AccountService service ; public AccountServiceDecorator(AccountService service) {...} public boolean transfer(Amount amount, Account debetAcc, Account creditAcc { boolean transferred = false ; try { startTransaction(); transferred = service .transfer(amount, debetAcc, creditAcc); commit(); } catch (RuntimeException e) { rollback(); throw e; } return transferred; } }
  39. 39. Programmatic Transaction Model Considerations <ul><li>Not recommended
  40. 40. Typical scenarios </li></ul><ul><ul><li>Client-initiated transactions
  41. 41. Localized JTA transactions
  42. 42. Long running transactions (span multiple request) </li></ul></ul><ul><li>Manual handling of rollback (pay attention to exceptions) </li></ul>
  43. 43. Declarative Transaction Model <ul><li>The most recommended model
  44. 44. No Java code for transaction management
  45. 45. Developer only tells the container how to manage transactions </li></ul>
  46. 46. Declarative Transaction Model with ASPECT (1) public class AccountServiceImpl implements AccountService { @ Transactional public boolean transferAmount( final Amount amount, final Account debetAcc, final Account creditAcc) { ..... } }
  47. 47. Declarative Transaction Model with ASPECT (2) @ Aspect public class TransactionAspect { private TransactionService transactionService = new TransactionServiceNull(); @ Pointcut( &quot;execution(@org.spring...Transactional * *(..))&quot; ) public void transactionalMethod() {} public void setTransactionService( final TransactionService transactionService) { this . transactionService = transactionService; } .... to be continued ....
  48. 48. Declarative Transaction Model with ASPECT (3) ... continued ... @ Before( &quot;transactionalMethod()&quot; ) public void beforeTransactionalMethod(JoinPoint joinPoint) { transactionService.beginTransaction(); } @ AfterReturning( &quot;transactionalMethod()&quot; ) public void afterTransactionalMethod(JoinPoint joinPoint) { transactionService .commit(); } @ AfterThrowing(pointcut = &quot;transactionalMethod()&quot; , throwing = &quot;e&quot; ) public void afterThrowingFromTransactionalMethod(JoinPoint joinPoint, RuntimeException e) { transactionService.rollback(); } }
  49. 49. Declarative Transaction Model with Spring Annotations <context:component-scan base-package=&quot;com........&quot; /> <tx:annotation-driven /> <bean id=&quot;txnMgr&quot; class=&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;> <property name=&quot;dataSource&quot; ref=&quot;dataSource&quot;/> </bean> @ Component public class UsersService { @ Transactional(propagation = Propagation.REQUIRED) public void modifyUser(User user) { ... } }
  50. 50. Declarative Transaction Model with Spring XML Configuration
  51. 51. Transaction Propagation Attribute <ul><li>Required – create new or reuse
  52. 52. Mandatory – reuse but never starts new
  53. 53. RequiresNew – always starts new
  54. 54. Supports – not require, but uses if present
  55. 55. NotSupported – suspends TX if present
  56. 56. Never – cannot be invoked with TX (throws exception) </li></ul>
  57. 57. Transaction Design Patterns
  58. 58. Transaction Design Patterns <ul><li>Open Session in View
  59. 59. Client Owner
  60. 60. Domain Service Owner
  61. 61. Server Delegate Owner </li></ul>
  62. 62. <ul><li>Open Session in View Pattern </li></ul><ul><li>Transactions are demarcated on request level
  63. 63. Whole request is responsible for transaction management </li></ul>
  64. 64. <ul><li>Open Session in View Pattern Spring Example </li></ul>< filter > < filter-name > oemInViewFilter </ filter-name > < filter-class > org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter </ filter-class > < init-param > < param-name > entityManagerFactoryBeanName </ param-name > < param-value > reportsEntityManagerFactory </ param-value > </ init-param > </ filter > < filter-mapping > < filter-name > oemInViewFilter </ filter-name > < url-pattern > *.jsp </ url-pattern > </ filter-mapping >
  65. 65. <ul><li>Open Session in View Pattern Considerations </li></ul><ul><li>Simple to implement and maintain
  66. 66. Single entry point for configuration
  67. 67. May lead to performance issues when mapped to any request
  68. 68. Not suitable for complex applications </li></ul><ul><ul><li>Has no control over transaction propagation
  69. 69. Doesn't support long transactions </li></ul></ul>
  70. 70. Client Owner Pattern <ul><li>Client (presentation) layer is responsible for transaction management </li></ul>@ Component @ Scope(BeanDefinition.SCOPE_PROTOTYPE) public class MainScreenController { @ Transactional public void load() { // 1-N Calls to application } }
  71. 71. Client Owner Pattern Considerations <ul><li>More flexible control
  72. 72. Most suitable for fine-grained application services
  73. 73. Application and underlying layers should never take control over transactions
  74. 74. Most suitable for cases when application layer architecture can't be changed </li></ul>
  75. 75. Domain Service Owner Pattern <ul><li>Services layer is responsible for transaction handling </li></ul>@ Component @ Scope(BeanDefinition.SCOPE_PROTOTYPE) Public class MainScreenController { private MainScreenApplicationService service ; public void load() { service .load(); } } @ Component public class MainScreenApplicationService { @ Transactional public void load() { ... } }
  76. 76. Domain Service Owner Pattern Considerations <ul><li>Client always makes a single request to application layer
  77. 77. Services are course-grained (Facades)
  78. 78. Domain and persistence layers should never take control over transactions
  79. 79. Client doesn't contain any transaction logic </li></ul>
  80. 80. Server Delegate Owner Pattern <ul><li>A subtype of Command Pattern
  81. 81. External system / services facades own the transaction </li></ul>
  82. 82. Server Delegate Owner Pattern Example @ Component @ Transactional public class UpdateRateCommand { private CurrencyRateSystem crs ; private RateData data ; public UpdateRateCommand(RateData data) { this . data = data; } public void execute() { Currency currFrom = data .getFrom(); Currency currTo = data .getTo(); Rate rate = crs .rate(currFrom, currTo, new Date()); data .setRate(rate); } }
  83. 83. Server Delegate Owner Pattern Considerations <ul><li>Transactions are encapsulated
  84. 84. Transactions are not managed by presentation and services layers </li></ul>
  85. 85. There is even more to learn <ul><li>EJB Transaction management patterns and implementation
  86. 86. Java Transaction Service (JTS) and Java Transaction API (JTA)
  87. 87. XA Transaction processing
  88. 88. Transaction management in JMS
  89. 89. Long running transactions
  90. 90. …and more </li></ul>
  91. 91. Summary <ul><li>Try to use Declarative patterns only
  92. 92. Define transaction boundaries correctly
  93. 93. Use appropriate patterns to: </li></ul><ul><ul><li>Improve performance
  94. 94. Clearly define transaction management strategy
  95. 95. Make code easy to understand, implement and maintain
  96. 96. Minimize amount of bugs </li></ul></ul>
  97. 97. Thank you! Questions?
  98. 98. References <ul><li>http://www.infoq.com/minibooks/JTDS
  99. 99. http://blog.smartkey.co.uk/2010/03/open-session-in-view-pattern-spring-jpa/ </li></ul>

×