ruslan platonov - transactions

Download Ruslan Platonov - Transactions

If you can't read please download the document

Upload: dmitry-buzdin

Post on 16-Apr-2017

1.196 views

Category:

Technology


6 download

TRANSCRIPT

Slide 1

Transaction Management Patterns

Ruslan PlatonovLead Java Developer at C.T.Co

Definition of Transaction

Transaction = Logical unit of work

Provides ACID

Atomicity

Consistency

Isolation

Durability

Typical Issues

Lack of knowledge in the area

Not clear understanding (knowledge) of transaction management strategy on application level

DB team should care about transactions

All these things results inanti patterns insideour projects

Ex 1: Auto-commit

hibernate.connection.autocommit = true

hibernate.connection.release_mode = after_statement

Ex 2: Programmatic Control

Connection connection = null;Statement statement = null;try { Class.forName("driverClass"); connection = DriverManager.getConnection("url", "user", "pass"); connection.setAutoCommit(false); statement = connection.createStatement();

// Execute queries statement.executeUpdate("UPDATE Table1 SET Value = 1 WHERE Name = 'foo'"); statement.executeUpdate("UPDATE Table2 SET Value = 2 WHERE Name = 'bar'");

connection.commit();

} catch (SQLException ex) { if (null != connection) { connection.rollback(); }} finally { if (null != statement) { statement.close(); } if (null != connection) { connection.close(); }}

Ex 3: Incorrect Demarcation

@Repositorypublic class UserRepository {

@Transactional public void save(User user) { ... }

}

@Componentpublic class UserService { @Autowired private UserRepository repo;

public void disableUsers( List usersList) { for(User user : usersList) { repo.save(user); } }}

Ex 4: Batch processing

@Componentpublic class LongRunningJob {

@Autowiredprivate RecordRepository repository;

@Transactional public void updateRecords() { for(int i = 1; i < 100000; i++) { Record rec = repository.getById(i); repository.updateTimeStamp(rec, new Date()); } }}

Consequences

Data Inconsistency

Performance Issues

High load on DB

How can we improveour code?

Some Ideas

Use declarative definition

Add transparency

Decouple from application logic, make flexible

Simplify maintenance

Transaction Models

Transaction Models

Local

Programmatic

Declarative

Local Transaction Model

Transactions are handled by DB

Developer manage connections not transaction

Local Transaction Model Example

Local Transaction Model Considerations

Not recommended

Suitable for simple cases

Plenty of room for errors

Cannot maintain ACID when coordinating multiple resources (DB, JMS)

Programmatic Transaction Model

Developer manages transactions not connections

Developer is responsible for starting and terminating transactions

Programmatic Transaction Model Example

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;}}

Programmatic Transaction Model Considerations

Not recommended

Typical scenarios

Client-initiated transactions

Localized JTA transactions

Long running transactions (span multiple request)

Manual handling of rollback (pay attention to exceptions)

Declarative Transaction Model

The most recommended model

No Java code for transaction management

Developer only tells the container how to manage transactions

Declarative Transaction Model with ASPECT (1)

public class AccountServiceImpl implements AccountService { @Transactional public boolean transferAmount(final Amount amount, final Account debetAcc, final Account creditAcc) { ..... }}

Declarative Transaction Model with ASPECT (2)

@Aspectpublic class TransactionAspect { private TransactionService transactionService = new TransactionServiceNull();

@Pointcut("execution(@org.spring...Transactional * *(..))") public void transactionalMethod() {} public void setTransactionService(final TransactionService transactionService) { this.transactionService = transactionService; } .... to be continued ....

Declarative Transaction Model with ASPECT (3)

... continued ... @Before("transactionalMethod()") public void beforeTransactionalMethod(JoinPoint joinPoint) { transactionService.beginTransaction(); } @AfterReturning("transactionalMethod()") public void afterTransactionalMethod(JoinPoint joinPoint) { transactionService.commit(); } @AfterThrowing(pointcut = "transactionalMethod()", throwing = "e") public void afterThrowingFromTransactionalMethod(JoinPoint joinPoint, RuntimeException e) { transactionService.rollback(); }}

Declarative Transaction Model
with Spring Annotations

@Componentpublic class UsersService { @Transactional(propagation = Propagation.REQUIRED) public void modifyUser(User user) { ... }}

Declarative Transaction Model
with Spring XML Configuration

Transaction Propagation Attribute

Required create new or reuse

Mandatory reuse but never starts new

RequiresNew always starts new

Supports not require, but uses if present

NotSupported suspends TX if present

Never cannot be invoked with TX (throws exception)

Transaction Design Patterns

Transaction Design Patterns

Open Session in View

Client Owner

Domain Service Owner

Server Delegate Owner

PresentationApplicationDomainExternal SystemRequest

Open Session in View Pattern

Transactions are demarcated on request level

Whole request is responsible for transaction management

Open Session in View Pattern
Spring Example

oemInViewFilter org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter entityManagerFactoryBeanName reportsEntityManagerFactory

oemInViewFilter *.jsp

Open Session in View Pattern Considerations

Simple to implement and maintain

Single entry point for configuration

May lead to performance issues when mapped to any request

Not suitable for complex applications

Has no control over transaction propagation

Doesn't support long transactions

Client Owner Pattern

Client (presentation) layer is responsible for transaction management

@Component@Scope(BeanDefinition.SCOPE_PROTOTYPE)public class MainScreenController {

@Transactional public void load() { // 1-N Calls to application }

}

Client Owner Pattern Considerations

More flexible control

Most suitable for fine-grained application services

Application and underlying layers should never take control over transactions

Most suitable for cases when application layer architecture can't be changed

Domain Service Owner Pattern

Services layer is responsible for transaction handling

@Component@Scope(BeanDefinition.SCOPE_PROTOTYPE)Public class MainScreenController { private MainScreenApplicationService service; public void load() { service.load(); }}@Componentpublic class MainScreenApplicationService {

@Transactional public void load() { ... }}

Domain Service Owner Pattern Considerations

Client always makes a single request to application layer

Services are course-grained (Facades)

Domain and persistence layers should never take control over transactions

Client doesn't contain any transaction logic

Server Delegate Owner Pattern

A subtype of Command Pattern

External system / services facades own the transaction

Server Delegate Owner Pattern Example

@Component@Transactionalpublic 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); }}

Server Delegate Owner Pattern Considerations

Transactions are encapsulated

Transactions are not managed by presentation and services layers

There is even more to learn

EJB Transaction management patterns and implementation

Java Transaction Service (JTS) and Java Transaction API (JTA)

XA Transaction processing

Transaction management in JMS

Long running transactions

and more

Summary

Try to use Declarative patterns only

Define transaction boundaries correctly

Use appropriate patterns to:

Improve performance

Clearly define transaction management strategy

Make code easy to understand, implement and maintain

Minimize amount of bugs

Thank you!

Questions?

References

http://www.infoq.com/minibooks/JTDS

http://blog.smartkey.co.uk/2010/03/open-session-in-view-pattern-spring-jpa/