You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2016/05/09 17:01:16 UTC

svn commit: r1743006 - in /aries/site/trunk/content/modules/tx-control: advancedResourceProviders.mdtext advancedScopes.mdtext

Author: timothyjward
Date: Mon May  9 17:01:16 2016
New Revision: 1743006

URL: http://svn.apache.org/viewvc?rev=1743006&view=rev
Log:
Fill in TODOs for the Transaction Control Service.

Modified:
    aries/site/trunk/content/modules/tx-control/advancedResourceProviders.mdtext
    aries/site/trunk/content/modules/tx-control/advancedScopes.mdtext

Modified: aries/site/trunk/content/modules/tx-control/advancedResourceProviders.mdtext
URL: http://svn.apache.org/viewvc/aries/site/trunk/content/modules/tx-control/advancedResourceProviders.mdtext?rev=1743006&r1=1743005&r2=1743006&view=diff
==============================================================================
--- aries/site/trunk/content/modules/tx-control/advancedResourceProviders.mdtext (original)
+++ aries/site/trunk/content/modules/tx-control/advancedResourceProviders.mdtext Mon May  9 17:01:16 2016
@@ -16,4 +16,130 @@ Notice:    Licensed to the Apache Softwa
            specific language governing permissions and limitations
            under the License.
 
-#TODO
\ No newline at end of file
+#Making your own Resource Provider
+
+The <code>TransactionControl</code> service is based around the use of <code>ResourceProvider</code>
+instances. When combined the client receives a thread-safe resource instance that they can use.
+
+Resource Provider implementations already exist for [JDBC][1], [XA JDBC][2], [JPA][3] and [XA JPA][4]
+
+##Create an interface 
+
+If you need to create your own Resource Provider then you should define a sub-interface which declares the
+type of the resource. This allows clients type-safe access to the resources, and makes it easier to identify
+the right Resource Provider at runtime.
+
+    public interface MyCustomResourceProvider extends 
+                        ResourceProvider<MyCustomResource> {}
+
+## Create an implementation
+
+The implementation of a ResourceProvider should return a thread-safe delegating proxy. This may be a
+dynamic proxy or a static one. The proxy delegates to the real resource, and is responsible for ensuring
+that the thread consistently accesses the same physical resource throughout the scope. Note that even 
+when multiple proxies are created they should share the same physical resource throughout the life of the
+context.
+
+### Lifecycle - first access
+
+Whenever the resource is accessed then it must check to see whether it has already been accessed 
+within the current scope. If not then a resource should be selected and associated with the scope. This
+physical resource must then be used for the rest of the scope.
+
+Note that if there is no active scope when the resource is accessed then the resource access should 
+fail with a TransactionException.
+
+    /**
+     *  A resource method
+     */
+    @Override
+    public boolean doSomething() {
+        if(!txControl.activeScope()) {
+            throw new TransactionException("There is no scope currently active");
+        }
+
+        // Locate, or create and associate
+        MyCustomResource delegate = locateDelegate(txControl.getCurrentContext());
+        
+        return delegate.doSomething();
+    }
+
+### Lifecycle - enlisting
+
+If a transaction is active then the resource should enlist with it when it is first used. If the resource is
+usable with XA transactions then it should register an XAResource.
+
+    private MyCustomResource locateDelegate(TransactionContext context) {
+        MyCustomResource resource = findExisting(context);
+
+        if(resource != null) {
+            resource = getNewDelegate(context);
+            
+            if(context.activeTransaction()) {
+                if(context.supportsXA()) {
+                    context.registerXAResource(resource.getXAResource());
+                } else {
+                    throw new TransactionException("The transaction does not support XA resources");
+                }
+            }
+            // Other resource preparation
+            ...
+        }
+
+        return resource;
+    }
+
+Local resources are similar, but they register a LocalResource, not an XAResource.
+
+    private MyCustomResource locateDelegate(TransactionContext context) {
+        MyCustomResource resource = findExisting(context);
+
+        if(resource != null) {
+            resource = getNewDelegate(context);
+            
+            if(context.activeTransaction()) {
+                if(context.supportsLocal()) {
+                    context.registerLocalResource(resource.getLocalesource());
+                } else {
+                    throw new TransactionException("The transaction does not support Local resources");
+                }
+            }
+            // Other resource preparation
+            ...
+        }
+
+        return resource;
+    }
+
+### Lifecycle - Tidying up
+
+In addition to registering with an active transaction the resource should also register for cleanup at the end
+of the scope. This may involve closing the physical resource, or returning it to a pool.
+
+    // Other resource preparation
+    
+    context.postCompletion(s -> resource.release());
+
+##Other things to look out for...
+
+1. A client must have a friendly way to access the ResourceProvider. This may be directly via the OSGi Service 
+Registry or via a factory service of some kind.
+
+1. A resource must remain valid throughout a scope, therefore clients should not be able to close or return the
+resource by making calls on the thread-safe proxy. Typically calls to close should be a silent no-op (the
+actual close will occur when the scope ends).
+
+1. When a transaction is active clients must not be able to manually commit or rollback the resource.
+Methods like <code>commit</code>, <code>rollback</code> and <code>setRollbackOnly</code> must
+fail with a TransactionException indicating the incorrect usage. This is different from <code>close</code>
+behaviour because unlike deferring a <code>close</code> ignoring a <code>rollback</code> results in a 
+different overall result from the client's perspective.
+
+1. Resources must not rely on the Transaction Control service recognising duplicate enlistments. A resource
+should be enlisted at most once.
+
+
+  [1]: localJDBC.html
+  [2]: xaJDBC.html
+  [3]: localJPA.html
+  [4]: xaJPA.html
\ No newline at end of file

Modified: aries/site/trunk/content/modules/tx-control/advancedScopes.mdtext
URL: http://svn.apache.org/viewvc/aries/site/trunk/content/modules/tx-control/advancedScopes.mdtext?rev=1743006&r1=1743005&r2=1743006&view=diff
==============================================================================
--- aries/site/trunk/content/modules/tx-control/advancedScopes.mdtext (original)
+++ aries/site/trunk/content/modules/tx-control/advancedScopes.mdtext Mon May  9 17:01:16 2016
@@ -16,4 +16,57 @@ Notice:    Licensed to the Apache Softwa
            specific language governing permissions and limitations
            under the License.
 
-#TODO
\ No newline at end of file
+#Advanced Scope control
+
+There are a number of useful ways to interact with the scopes created by the Transaction Control Service
+
+## Determining the current scope
+
+The Transaction Control Service has methods which can be used to work out whether a scope is in effect:
+
+* <code>txControl.activeScope();</code> - When <code>true</code> there is a scope in effect and resources can be 
+accessed. The scope may, or may not, be transactional. When false there is no current scope and
+<code>txControl.getCurrentContext();</code> will return <code>null</code>.
+
+* <code>txControl.activeTransaction()</code> - When <code>true</code> there is a transactional scope in 
+effect and resources can be accessed transactionally. When false there may, or may not, be a "No Transaction"
+scope in effect.
+
+Note that <code>assert txControl.activeTransaction();</code> can be used to enforce the presence of a
+transaction. This is equivalent to a "Mandatory" transaction in Spring or Java EE.
+
+## Avoiding rollback
+
+When setting up a transaction certain exception types can be marked as not triggering rollback:
+
+    txControl.build()
+        .noRollbackFor(MyCustomException.class)
+        .required(() -> {
+                // A MyCustomException thrown here will not trigger rollback
+            });
+
+
+## Nesting a transaction
+
+Nesting a Transaction can easily be managed using <code>requiresNew()</code>
+
+
+    txControl.required(() -> {
+            // Do some work...
+            
+            return txControl.requiresNew(() -> {
+                    // Do some more work
+                });
+        });
+
+## Suspending a transaction
+
+Suspending a Transaction can easily be managed using <code>notSupported()</code>
+
+    txControl.required(() -> {
+            // Do some work...
+            
+            return txControl.notSupported(() -> {
+                    // Do some more work
+                });
+        });