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.

#Making your own Resource Provider

The `TransactionControl` service is based around the use of `ResourceProvider` instances.
When combined the client receives a thread-safe resource instance that they can use.

Resource Provider implementations already exist for link:localJDBC.html[JDBC], link:xaJDBC.html[XA JDBC], link:localJPA.html[JPA] and link:xaJPA.html[XA JPA]

##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...

. 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.
. 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).
. When a transaction is active clients must not be able to manually commit or rollback the resource.
Methods like `commit`, `rollback` and `setRollbackOnly` must fail with a TransactionException indicating the incorrect usage.
This is different from `close` behaviour because unlike deferring a `close` ignoring a `rollback` results in a  different overall result from the client's perspective.
. Resources must not rely on the Transaction Control service recognising duplicate enlistments.
A resource should be enlisted at most once.
