Transaction Control – a Functional Approach to Modular Transaction Management - Tim Ward

262 views

Published on

OSGi Community Event 2016 Presentation by Tim Ward (Paremus)

Transactions are a critical part of almost all Enterprise applications, but correctly managing those transactions isn’t always easy. This is particularly true in a dynamic, modular world where you need to be certain that everything is ready before you begin.

With the advent of lambda expressions and functional interfaces we now have new, better tools for defining transactional work. The OSGi Transaction Control service uses these functional programming techniques to scope transactions and resource access, providing control and flexibility while leaving business logic uncluttered. The resulting solution is decoupled, modular and requires no container magic at all, making testing and portability a breeze.

Background
Software controlled transactions have existed for a long time — commercial products that are still available now can trace their origins back to the 1960s. Since that time a lot has changed, first we saw the rise of C, then of Object Oriented programming, then of the Web, and now of Microservices.

Over the same time period there have been significant changes to the way that transactions are managed – either transaction boundaries have to be explicitly declared, or the management role is delegated to a container technology. Given the complexity of correctly managing the transaction lifecycle, container managed solutions are regarded as the gold standard, however container managed solutions introduce their own problems.

The rise of the Spring framework was a reaction to the complexity, and heavy-touch management of the original Java EE specifications. Instead Spring focussed on “pure POJO” programming, designed to make your code easily portable, runnable and testable inside or outside the container.

While Spring did a much better job of hiding complexity than those early Java EE servers, the fundamental problem with any pure declarative approach is that there must be a container somewhere. Without a container there is no code to start or end the transaction. Even now with Spring, EJB 3.2, CDI etc, the promise of simpler, container independent components is an illusion.

The big problem with declarative transaction management is that it tries to take away too much from the application code, replacing it with “container magic”. The problem with relying on magic is that the resulting system ends up being more complex, not less. We therefore should be aiming to simplify and minimise transaction management code, not eliminate it entirely. Java’s support for functional techniques opens a whole new set of API possibilities for transaction management, and the Apache Aries project has been exploring the possibilities of providing generic resource and transaction management in a concise, type-safe way. Examples from this project demonstrate how transaction management can be made both simple and explicit at the same time.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
262
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
11
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Transaction Control – a Functional Approach to Modular Transaction Management - Tim Ward

  1. 1. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 OSGi Community Event 2016 co-located at EclipseCon Europe 2016 Transaction Control – A functional approach to modular transaction management Tim Ward http://www.paremus.com info@paremus.com
  2. 2. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 •Chief Technology Officer at Paremus •8 years developing OSGi specifications •Chair of the OSGi IoT Expert Group •Interested in Asynchronous Distributed Systems •Author of Manning’s Enterprise OSGi in Action •http://www.manning.com/cummins Who is Tim Ward? @TimothyWard
  3. 3. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Transactions in Software
  4. 4. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Controlling Software Transactions Software Transactions have existed since the early 1960s They exist as a means to ensure data integrity Early transactions used special operating systems and vendor APIs Usually these systems performed offline batch reconciliation Modern transaction processing systems normally provide real-time update Handling individual updates leads to the concepts behind ACID Despite the growth of NoSQL datastores, transactions are still a vital tool
  5. 5. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Controlling Software Transactions (2) Originally transactions were all imperatively controlled Direct calls to start, stop, and invalidate the transaction You have to be very careful to handle every return (especially Exceptions) Managing transactions this way is verbose and error prone This lead to the development of declarative transactions Declarative Transactions use metadata to define the transaction boundary Application code is freed from boilerplate, and mistakes
  6. 6. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Declarative Transactions in Java Does anyone remember EJB 1/2? Despite the horror of its XML, transactions were simpler than before The Spring framework added AOP driven transaction management and later annotation driven transaction configuration EJB 3 adopted many of the principals provided by Spring CDI takes this even further
  7. 7. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Problems with Declarative Transactions It may seem that we’ve reached the perfect solution How can this get any simpler? @Transactional public void doUpdate(String foo) { … } Annotations are seductively simple but We’ve traded visible complexity for invisible complexity It’s better that we aren’t directly driving the transactions But who is driving, and can we rely on them?
  8. 8. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 How do Declarative Transactions Work?
  9. 9. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Aspect Oriented Programming Obviously Declarative Transactions must still be started somehow Some container code must run to manage the transaction lifecycle Typically transactions are run as intercepting “aspects” These run before and after every intercepted method call Aspects like this run in one of two ways: The container “weaves” extra bytecode instructions into your class The container creates a delegating proxy, which wrappers your class
  10. 10. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Aspect Oriented Programming (2) The two different implementations have different advantages and drawbacks Proxying works best when you can proxy by interface Final classes, final methods and private methods cannot be proxied Casting to instance types does not work Object identity may be affected Weaving avoids these drawbacks, but… It either needs a pre-deployment step, or a custom class loader It messes up the Java debugger (there’s a lot of code at line 0) It provides inconsistent behaviour compared to proxying!
  11. 11. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Enlisting Resources Starting a Transaction is only one part of the problem In order to participate in a Transaction a resource must “enlist” in it This applies to any Database or JMS Connections, and all other resources All of this happens transparently to the code using the resource But only if the right resource is used! This is why you must use JNDI to get resources in your App Server Even Spring requires you to set up Transactional resources
  12. 12. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 The Proxying problem Proxying is usually the preferred solution as it is less invasive But we mentioned that it is inconsistent compared to weaving… Consider the following object methods: @Transactional(SUPPORTS) public void doCheckAndUpdate(String foo) { // Do some non-transactional work … // Do an update doUpdate(foo); } @Transactional(REQUIRED) public void doUpdate(String foo) { // There must be a transaction here! … } Does this requirement hold?
  13. 13. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 The Proxying problem (2) Aspects provided by proxies can only run when the proxy is called In our method the proxy is not called! @Transactional(SUPPORTS) public void doCheckAndUpdate(String foo) { // Do some non-transactional work … // Do an update doUpdate(foo); } As a result the doUpdate method may not always run in a transaction Switching to weaving will make sure the right boundary is in place But your application should not need to care about this!
  14. 14. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Rolling back on failure A vital behaviour for Transactions is rolling back when things go wrong The most obvious reason for rollback is if the method throws an Exception Java EE decided to do something very strange (copied by Spring) Unchecked Exceptions trigger rollback Checked Exceptions do not trigger rollback The rationale for this is that a checked Exception is part of the API This is a horrible thing to do to your users! Exceptions should never be used as control flow Also SQLException is a checked Exception…
  15. 15. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 So what can we do? The use of declarative transactions is not 100% positive Yes our code is simpler, but it’s still not always correct We have traded visible complexity for invisible complexity! In a modular system we must do better We need to express dependencies on the features we need We need to be able to rely on consistent behaviours using contracts We need to be able to cope when no central container exists Also - let’s fix the crazy transaction behaviour!
  16. 16. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 The OSGi Transaction Control Service
  17. 17. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 The basics of OSGi Transaction Control The OSGi Transaction Control service has two main goals Simple, explicit management of transactional work Modular support for resources with managed lifecycles What does this mean in practice? You tell Transaction Control what transaction scope you want You tell your resources which Transaction Control service to use From there all the transaction and resource lifecycle is handled for you.
  18. 18. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Using Transaction Control to scope work Transaction Control uses a functional API Your business logic is passed as a function to be run within a “scope” A scope can be transactional, or non-transactional Transaction control provides four well-known options for scoping your work required - ensures that a transactional scope is running requiresNew - begins a new transactional scope supports - ensures that a scope (with or without a transaction) is running notSupported - ensures that a non-transactional scope is running
  19. 19. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Using Transaction Control to scope work (2) It should be obvious that a scope is more than just a transaction A scope provides a context for your work A place to store state A place to register completion callbacks An access boundary for your resources Scopes provide a safe way to access resources without leaks The resource is lazily retrieved the first time you use it in a scope The same resource is the available throughout the scope The resource is automatically released when the scope ends
  20. 20. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Finishing Scopes A scope ends once the work function has returned Resource clean up happens regardless of whether the work is successful The value returned by the work is returned by the scope Transactional work has additional rules for the transaction lifecycle: If the scope has been marked for rollback it always rolls back If the work exits with an Exception then the transaction rolls back If the work exits with a normal return then the transaction commits Specific Exception types can be marked not to cause rollback
  21. 21. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Scoped Resources Transaction Control works best when used with scoped resources A Scoped Resource is created from a ResourceProvider ResourceProvider#getResource(TransactionControl) Typically a more specialised sub-interface provides type-safety JDBCConnectionProvider -> java.sql.Connection JPAEntityManagerProvider -> javax.persistence.EntityManager The returned object is a thread-safe proxy Just use it in your methods whenever you need it!
  22. 22. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Putting it all together @Component public class TxComponent { @Reference TransactionControl txControl; @Reference JPAEntityManagerProvider jpa; EntityManager em; @Activate void start() { em = jpa.getResource(txControl); } public void doUpdate(MyEntity foo) { txControl.required(() -> { em.persist(foo); return null; }); } } Inject the services Create the scoped resource Use the scoped resource, safe in the knowledge that it will be committed and cleaned up
  23. 23. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Advanced features of Transaction Control
  24. 24. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 XA or Resource-Local transactions? Most resource types have a programatic API for commit/rollback These only apply to a single resource and so are “Resource Local” If multiple resources are used in the same transaction then we need more The XA protocol defines a robust distributed state machine Transaction Control supports lightweight resource-local transactions The osgi.xa.enabled property can be used to select an XA implementation Importantly the client API is the same whichever you use!
  25. 25. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Connection Pooling Connection Pooling in OSGi can be challenging… Most pooling implementations try to directly load the driver The client often ends up coupled to the pooling implementation The Resource Provider offers an excellent solution The JDBCConnectionProvider has built-in support for connection pooling Fully configurable using a standard factory service Providers can also be defined using Configuration Admin
  26. 26. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 No Rollback for… When starting a transaction the user can nominate Exception types These types can explicitly trigger, or not trigger, rollback. txControl.build() .noRollbackFor(SocketException.class, RemoteException.class) .rollbackFor(ConnectException.class) .required(() -> { em.persist(foo); return null; }); Be careful when using these!
  27. 27. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Nested Scopes Transaction Control Scopes can be easily nested Committing a quick status update part way through a batch Querying for sequence numbers outside the current transaction Each scope is isolated using separate resource instances The scopes also have separate contexts and lifecycle callbacks
  28. 28. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Introspecting the Scope The Transaction Control service can be used to query the current scope What type of scope is it? Querying for sequence numbers outside the current transaction Each scope is isolated using separate resource instances The scopes also have separate contexts and lifecycle callbacks
  29. 29. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Playing with Transaction Control
  30. 30. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 Playing with Transaction Control Let’s use Transaction Control to build a simple REST microservice JAX-RS for request mapping JPA persistence into a database A simple HTML/JavaScript UI running in the browser
  31. 31. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016
  32. 32. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 •For more about OSGi... • Specifications at http://www.osgi.org • Enterprise OSGi in Action • http://www.manning.com/cummins •For more about Transaction Control • http://github.com/osgi/design • http://aries.apache.org/modules/transactioncontrol.html Questions? Thanks! http://www.paremus.com info@paremus.com http://www.manning.com/cummins
  33. 33. Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved. OSGi Community Event Nov 2016 www.paremus.com @Paremus info@paremus.com

×