Author: timothyjward
Date: Fri May 20 15:20:46 2016
New Revision: 1744756

URL: http://svn.apache.org/viewvc?rev=1744756&view=rev
Log:
Add a page describing Spring migration and problems with proxies

Added:
    aries/site/trunk/content/modules/tx-control/spring-tx.mdtext   (with props)
Modified:
    aries/site/trunk/content/modules/transactioncontrol.mdtext
    aries/site/trunk/content/modules/tx-control/quickstart.mdtext

Modified: aries/site/trunk/content/modules/transactioncontrol.mdtext
URL: 
http://svn.apache.org/viewvc/aries/site/trunk/content/modules/transactioncontrol.mdtext?rev=1744756&r1=1744755&r2=1744756&view=diff
==============================================================================
--- aries/site/trunk/content/modules/transactioncontrol.mdtext (original)
+++ aries/site/trunk/content/modules/transactioncontrol.mdtext Fri May 20 
15:20:46 2016
@@ -16,7 +16,8 @@ ensure that the implementations are comp
 
 #Getting started
 
-If you're new to the Transaction Control service then we recommend that you 
read the [quickstart documentation first][2].
+If you're new to the Transaction Control service then we recommend that you 
read the 
+[quickstart documentation first][2].
 
 More detailed documentation is available in the [Aries Transaction Control 
Project][3]
 
@@ -26,31 +27,35 @@ Simply put the Transaction Control servi
 transaction lifecycle or closing connections, and there's built in support for 
useful features like 
 connection pooling.
 
+In addition to being simple the Transaction Control service also makes 
transaction management explicit. As a
+result it is easier to follow the transactions flowing throughout your code, 
and it protects you from the 
+[proxy problem][4] that declarative transaction strategies often suffer from.
+
 ## Modules
 
 The following modules are available for use in OSGi
 
-1. [tx-control-service-local][4] :- A purely local transaction control service 
implementation. This can be 
+1. [tx-control-service-local][5] :- A purely local transaction control service 
implementation. This can be 
 used with any resource-local capable ResourceProvider
 
-2. [tx-control-service-xa][5] :- An XA-capable transaction control service 
implementation based on the 
+2. [tx-control-service-xa][6] :- An XA-capable transaction control service 
implementation based on the 
 Geronimo Transaction Manager. This can be used with XA capable resources, or 
with local resources. 
 Local resources will make use of the last-participant gambit.
 
-3. [tx-control-provider-jdbc-local][6] :- A JDBC resource provider that 
provides connection pooling and
+3. [tx-control-provider-jdbc-local][7] :- A JDBC resource provider that 
provides connection pooling and
 that can integrate with local transactions. The JDBCConnectionProviderFactory 
service may be used 
 directly, or a service may be configured using the 
_org.apache.aries.tx.control.jdbc.local_ pid
 
-4. [tx-control-provider-jdbc-xa][7] :- A JDBC resource provider that provides 
connection pooling and 
+4. [tx-control-provider-jdbc-xa][8] :- A JDBC resource provider that provides 
connection pooling and 
 that can integrate with local or XA transactions. The 
JDBCConnectionProviderFactory service may be 
 used directly, or a service may be configured using the 
_org.apache.aries.tx.control.jdbc.xa_ pid
 
-5. [tx-control-provider-jpa-local][8] :- A JPA resource provider that can 
integrate with local transactions. 
+5. [tx-control-provider-jpa-local][9] :- A JPA resource provider that can 
integrate with local transactions. 
 The JPAEntityManagerProviderFactory service may be used directly, or a service 
may be configured using 
 the _org.apache.aries.tx.control.jpa.local_ pid. The implementation can also 
provide connection pooling 
 if required
 
-6. [tx-control-provider-jpa-xa][9] :- A JDBC resource provider that integrates 
with XA transactions. 
+6. [tx-control-provider-jpa-xa][10] :- A JDBC resource provider that 
integrates with XA transactions. 
 The JPAEntityManagerProviderFactory service may be used directly, or a service 
may be configured using 
 the _org.apache.aries.tx.control.jpa.xa_ pid. The implementation can also 
provide connection pooling 
 if required
@@ -93,9 +98,10 @@ attribute will be removed from the expor
   [1]: 
https://github.com/osgi/design/blob/master/rfcs/rfc0221/rfc-0221-TransactionControl.pdf
   [2]: tx-control/quickstart.html
   [3]: tx-control/index.html
-  [4]: tx-control/localTransactions.html
-  [5]: tx-control/xaTransactions.html
-  [6]: tx-control/localJDBC.html
-  [7]: tx-control/xaJDBC.html
-  [8]: tx-control/localJPA.html
-  [9]: tx-control/xaJPA.html
\ No newline at end of file
+  [4]: tx-control/spring-tx.html
+  [5]: tx-control/localTransactions.html
+  [6]: tx-control/xaTransactions.html
+  [7]: tx-control/localJDBC.html
+  [8]: tx-control/xaJDBC.html
+  [9]: tx-control/localJPA.html
+  [10]: tx-control/xaJPA.html
\ No newline at end of file

Modified: aries/site/trunk/content/modules/tx-control/quickstart.mdtext
URL: 
http://svn.apache.org/viewvc/aries/site/trunk/content/modules/tx-control/quickstart.mdtext?rev=1744756&r1=1744755&r2=1744756&view=diff
==============================================================================
--- aries/site/trunk/content/modules/tx-control/quickstart.mdtext (original)
+++ aries/site/trunk/content/modules/tx-control/quickstart.mdtext Fri May 20 
15:20:46 2016
@@ -63,13 +63,14 @@ methods can be used to ensure that a _No
 
 Simple scope management is perfect in most situations, but you may also wish 
to read about
 [more advanced scope control techniques][1] or [exception management][2] once 
you've mastered the basics.
+There are also some things to consider if you're [migrating from Spring or 
Java EE][3].
 
 ##Accessing Resources
 
 A <code>ResourceProvider</code> is a generic factory for scoped resources. 
Typically you will use a more 
 specific interface for type safety. For example the Transaction Control 
specification defines 
 <code>JDBCConnectionProvider</code> and <code>JPAEntityManagerProvider</code> 
interfaces. If
-needed you can [make your own ResourceProvider][3].
+needed you can [make your own ResourceProvider][4].
 
 To create your scoped resource you make one call to <code>getResource</code> 
passing in the 
 <code>TransactionControl</code> service that the resource should integrate 
with. The returned object
@@ -127,4 +128,5 @@ The transactionality and lifecycle of th
 
   [1]: advancedScopes.html
   [2]: exceptionManagement.html
-  [3]: advancedResourceProviders.html
\ No newline at end of file
+  [3]: spring-tx.html
+  [4]: advancedResourceProviders.html
\ No newline at end of file

Added: aries/site/trunk/content/modules/tx-control/spring-tx.mdtext
URL: 
http://svn.apache.org/viewvc/aries/site/trunk/content/modules/tx-control/spring-tx.mdtext?rev=1744756&view=auto
==============================================================================
--- aries/site/trunk/content/modules/tx-control/spring-tx.mdtext (added)
+++ aries/site/trunk/content/modules/tx-control/spring-tx.mdtext Fri May 20 
15:20:46 2016
@@ -0,0 +1,230 @@
+Title:
+Notice:    Licensed to the Apache Software Foundation (ASF) under one
+           or more contributor license agreements.  See the NOTICE file
+           distributed with this work for additional information
+           regarding copyright ownership.  The ASF licenses this file
+           to you under the Apache License, Version 2.0 (the
+           "License"); you may not use this file except in compliance
+           with the License.  You may obtain a copy of the License at
+           .
+             http://www.apache.org/licenses/LICENSE-2.0
+           .
+           Unless required by applicable law or agreed to in writing,
+           software distributed under the License is distributed on an
+           "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+           KIND, either express or implied.  See the License for the
+           specific language governing permissions and limitations
+           under the License.
+
+#Migrating from declarative transactions
+
+Many popular application containers, such as Spring or Java EE, offer 
declarative transaction management.
+Specifically, the container offers a model where transaction boundaries are 
defined using metadata, usually as
+annotations on public methods.
+
+## The Basics
+
+A typical transactional method in a declarative model might look like this:
+
+    @Transactional
+    public Long getCustomerId(String email) {
+        // Some business logic in here...
+    }
+
+Using Transaction control the same thing would look like:
+
+    public Long getCustomerId(String email) {
+        txControl.required(() -> {
+                // Some business logic in here...
+            });
+    }
+
+The main change is that the transactions have moved from being metadata 
defined, and started by the container,
+to being code defined and started by the Transaction Control service. This 
gives several significant advantages.
+
+## The Scoping Problem
+
+When using method-level metadata to define transaction boundaries it is not 
possible to manage transactions
+on a finer level. This makes it difficult to suspend or nest transactions 
unless you create a new method to hold
+the extra logic.
+
+### A Simple Example
+
+If we want to write an audit message it usually needs to occur in a new 
transaction, as typically it should persist
+even if the overall action fails. In a declarative model this requires a 
separate method with a new boundary,
+even if the audit function is a private implementation detail of the Object.
+
+    @Transactional
+    public void changePassword(String email, String password) {
+
+        auditPasswordChangeAttempt(email);
+    
+        // Some business logic in here...
+    } 
+    
+    @Transactional(REQUIRES_NEW)
+    public void auditPasswordChangeAttempt(String email) {
+        // One line to write the audit message
+    } 
+
+With transaction control there is no need to create a method just for the 
internal audit function.
+
+ @Transactional
+    public void changePassword(String email, String password) {
+        
+        txControl.required(() -> {
+
+                txControl.requiresNew(() -> {
+                        // One line to write the audit message
+                    });
+
+                // Some business logic in here...
+            });
+    } 
+  
+
+## The Proxy Problem
+
+The Proxy problem is a rather insidious issue that affects declarative 
transactions, and it is a result of how they
+are implemented. If bytecode weaving is used to directly add transactional 
behaviour to an object then it will
+always work the same way. Most solutions, however, do not use bytecode 
weaving, but instead use a proxy
+pattern. When a call is made on the proxy the proxy will perform any necessary 
transaction management
+before and after delegating the call to the real object. This works well, 
except if the object makes any internal
+method calls.
+
+In the general case proxying is unsafe because you cannot rely on a method's 
metadata to decide what 
+transaction state will exist when it is called!
+
+### Examples of the Proxy Problem
+
+The following examples are all based on real code migrated from Spring to 
Transaction Control.
+
+#### A Simple Example
+
+    AbstractPersistenceDataManagerImpl {
+
+        @Transactional(propagation = SUPPORTS, readOnly = true)
+        public <T> T search(Class<T> entityClass, Object pk, Object params) {
+            return (T) find(entityClass, pk, params);
+        }
+
+        @Transactional(readOnly = true)
+        public UniWorksSuperDBEntity find(Class entityClass, Object pk, Object 
params) {
+            return (UniWorksSuperDBEntity) em.find(entityClass, pk);
+        }
+    }
+
+In this case the <code>search</code> method does not require a transaction, 
but delegates to the 
+<code>find</code> method which does. If proxying is used then the 
<code>find</code> method will
+sometimes run in a transaction and sometimes not. On the other hand, if 
weaving is used then the
+<code>find</code> method will *always* run under a transaction This may seem 
innocuous, but it 
+can cause big problems. We always want to be certain about where a transaction 
will start and stop!
+
+#### Extending the Simple Example
+
+The following type is part of the same project as the previous example, and 
interacts with it.
+
+    AbstractDataManager {
+
+        @Transactional(propagation = NOT_SUPPORTED, readOnly = true)
+        public UniWorksSuperDTO search(Object pk, Object params) {
+        
+            UniWorksSuperDBEntity entity = persistenceDataManager
+                    .search(getEntityClass(), createNewPKFromDTOPK(pk), null);
+
+            loadLinkedTablesTop(entity, params);
+        }
+
+        protected final void loadLinkedTablesTop(UniWorksSuperDBEntity entity, 
Object params) {
+            loadLinkedTables(entity, params);
+        }
+
+        @Transactional(readOnly = true)
+        public void loadLinkedTables(UniWorksSuperDBEntity entity, Object 
params) {
+            loadLinkedTablesGenerated(entity, params);
+            loadLinkedTransients(entity, params);
+        }
+    }
+
+Now lets imagine that a call comes in to the <code>search</code> method of 
this class from some client.
+
+##### Proxied
+
+ 1. The container proxy for the data manager halts any ongoing transaction due 
to the 
+<code>NOT_SUPPORTED</code> metadata, entering an undefined scope.
+ 2. The code calls search on the persistenceDataManager
+ 3. The container proxy for the persistence data manager does not start or 
stop a transaction due to the
+<code>SUPPORTS</code> scope.
+ 4. The code calls <code>find</code> on the persistenceDataManager, but 
without touching the proxy.
+ 5. The code accesses the entity outside a transaction
+ 6. The code returns the entity, and no transaction change is necessary
+ 7. The code calls loadLinkedTablesTop, which calls loadLinkedTables. No proxy 
is touched therefore no 
+transaction is started.
+8. The Tables are populated with data from the entity. Lazy loading is 
possible as the entity is still attached.
+
+##### Woven
+
+ 1. The weaving code for the data manager halts any ongoing transaction due to 
the 
+<code>NOT_SUPPORTED</code> metadata, entering an undefined scope.
+ 2. The code calls search on the persistenceDataManager
+ 3. The weaving code for the persistence data manager does not start or stop a 
transaction due to the
+<code>SUPPORTS</code> scope.
+ 4. The code calls <code>find</code> on the persistenceDataManager, at this 
point the weaving code starts
+a transaction.
+ 5. The code accesses the entity inside the transaction
+ 6. The code returns the entity, and the transaction completes. This detaches 
the entity and prevents lazy loading.
+ 7. The code calls loadLinkedTablesTop, which calls loadLinkedTables. The 
weaving code starts a new 
+transaction.
+ 8. The Code fails as the entity is not able to access its lazily loaded data.
+
+### Strategies for Managing Transaction States
+
+Ensuring consistency is vital when writing code that uses transactions. It is 
therefore usually a good idea to 
+ensure that any reused code is captured in a private method, and that it 
asserts the correct transaction state
+before it begins.
+
+    AbstractDataManager {
+
+        public UniWorksSuperDTO search(Object pk, Object params) {
+        
+            txControl.build().readOnly().notSupported(() -> {
+                    UniWorksSuperDBEntity entity = persistenceDataManager
+                            .search(getEntityClass(), 
createNewPKFromDTOPK(pk), null);
+
+                    loadLinkedTablesTop(entity, params);
+                    return entity;
+            }
+        }
+
+        protected final void loadLinkedTablesTop(UniWorksSuperDBEntity entity, 
Object params) {
+            loadLinkedTables(entity, params);
+        }
+
+        public void loadLinkedTables(UniWorksSuperDBEntity entity, Object 
params) {
+            txControl.build().readOnly().required(() -> {
+                    loadLinkedTables(entity, params);
+                });
+        }
+
+        /**
+         * This method does not need a transaction, but does need a scope
+         */
+        private void loadLinkedTablesInternal(UniWorksSuperDBEntity entity, 
Object params) {
+            assert txControl.activeScope();
+
+            loadLinkedTablesGenerated(entity, params);
+            loadLinkedTransients(entity, params);
+        }
+    }
+
+Writing code in this way ensures that even when a mixture of transactional and 
non transactional actions are
+needed, there will always be a consistent expectation of the transaction scope 
in each method.
+
+## Exception management
+
+The final significant difference between declarative models and the 
Transaction Control Service is in how much
+work your application code needs to do when managing exceptions. More detail 
about managing exceptions
+[is available here][1].
+
+
+  [1]: exceptionManagement.html
\ No newline at end of file

Propchange: aries/site/trunk/content/modules/tx-control/spring-tx.mdtext
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to