Transaction Control – a Functional Approach to Modular Transaction Management - Tim Ward
-
Upload
mfrancis -
Category
Technology
-
view
102 -
download
0
Transcript of Transaction Control – a Functional Approach to Modular Transaction Management - Tim Ward
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 2016co-located at
EclipseCon Europe 2016
Transaction Control – A functional approach to modular transaction management
Tim Ward http://www.paremus.com [email protected]
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
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
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 1960sThey exist as a means to ensure data integrity
Early transactions used special operating systems and vendor APIsUsually these systems performed offline batch reconciliation
Modern transaction processing systems normally provide real-time updateHandling individual updates leads to the concepts behind ACID
Despite the growth of NoSQL datastores, transactions are still a vital tool
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 controlledDirect calls to start, stop, and invalidate the transactionYou have to be very careful to handle every return (especially Exceptions)
Managing transactions this way is verbose and error proneThis lead to the development of declarative transactions
Declarative Transactions use metadata to define the transaction boundaryApplication code is freed from boilerplate, and mistakes
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 SpringCDI takes this even further
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 solutionHow can this get any simpler?@Transactionalpublic void doUpdate(String foo) {
…}
Annotations are seductively simple butWe’ve traded visible complexity for invisible complexity
It’s better that we aren’t directly driving the transactionsBut who is driving, and can we rely on them?
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?
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 somehowSome 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 classThe container creates a delegating proxy, which wrappers your class
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 interfaceFinal classes, final methods and private methods cannot be proxiedCasting to instance types does not workObject 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!
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 itThis applies to any Database or JMS Connections, and all other resources
All of this happens transparently to the code using the resourceBut only if the right resource is used!
This is why you must use JNDI to get resources in your App ServerEven Spring requires you to set up Transactional resources
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 invasiveBut 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 updatedoUpdate(foo);
}
@Transactional(REQUIRED)public void doUpdate(String foo) {
// There must be a transaction here!…
}
Does this requirement hold?
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 calledIn our method the proxy is not called!@Transactional(SUPPORTS)public void doCheckAndUpdate(String foo) {
// Do some non-transactional work…// Do an updatedoUpdate(foo);
}
As a result the doUpdate method may not always run in a transactionSwitching to weaving will make sure the right boundary is in placeBut your application should not need to care about this!
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 wrongThe 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 rollbackChecked Exceptions do not trigger rollback
The rationale for this is that a checked Exception is part of the APIThis is a horrible thing to do to your users!Exceptions should never be used as control flowAlso SQLException is a checked Exception…
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% positiveYes our code is simpler, but it’s still not always correctWe have traded visible complexity for invisible complexity!
In a modular system we must do betterWe need to express dependencies on the features we needWe need to be able to rely on consistent behaviours using contractsWe need to be able to cope when no central container exists
Also - let’s fix the crazy transaction behaviour!
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
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 goalsSimple, explicit management of transactional workModular support for resources with managed lifecycles
What does this mean in practice?You tell Transaction Control what transaction scope you wantYou tell your resources which Transaction Control service to use
From there all the transaction and resource lifecycle is handled for you.
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 workrequired - ensures that a transactional scope is runningrequiresNew - begins a new transactional scopesupports - ensures that a scope (with or without a transaction) is runningnotSupported - ensures that a non-transactional scope is running
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 workA place to store stateA place to register completion callbacksAn access boundary for your resources
Scopes provide a safe way to access resources without leaksThe resource is lazily retrieved the first time you use it in a scopeThe same resource is the available throughout the scopeThe resource is automatically released when the scope ends
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 returnedResource clean up happens regardless of whether the work is successfulThe 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 backIf the work exits with an Exception then the transaction rolls backIf the work exits with a normal return then the transaction commits
Specific Exception types can be marked not to cause rollback
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 ResourceProviderResourceProvider#getResource(TransactionControl)
Typically a more specialised sub-interface provides type-safetyJDBCConnectionProvider -> java.sql.ConnectionJPAEntityManagerProvider -> javax.persistence.EntityManager
The returned object is a thread-safe proxyJust use it in your methods whenever you need it!
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
@Componentpublic 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
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
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/rollbackThese only apply to a single resource and so are “Resource Local”
If multiple resources are used in the same transaction then we need moreThe XA protocol defines a robust distributed state machine
Transaction Control supports lightweight resource-local transactionsThe osgi.xa.enabled property can be used to select an XA implementation
Importantly the client API is the same whichever you use!
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 driverThe client often ends up coupled to the pooling implementation
The Resource Provider offers an excellent solution
The JDBCConnectionProvider has built-in support for connection poolingFully configurable using a standard factory serviceProviders can also be defined using Configuration Admin
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 typesThese 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!
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 nestedCommitting a quick status update part way through a batchQuerying for sequence numbers outside the current transaction
Each scope is isolated using separate resource instancesThe scopes also have separate contexts and lifecycle callbacks
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 scopeWhat type of scope is it?Querying for sequence numbers outside the current transaction
Each scope is isolated using separate resource instancesThe scopes also have separate contexts and lifecycle callbacks
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
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 microserviceJAX-RS for request mappingJPA persistence into a database
A simple HTML/JavaScript UI running in the browser
Copyright © 2005 - 2016 Paremus Ltd. May not be reproduced by any means without express permission. All rights reserved.
OSGi Community Event Nov 2016
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 [email protected]
http://www.manning.com/cummins
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 [email protected]