= Getting started with the Transaction Control Service

To make use of scoped resources and transactions using the transaction control service you need two things:

* A `org.osgi.service.transaction.control.TransactionControl` implementation  (found in the service registry).
You may want to start with link:localTransactions.html[local transactions].
* A `org.osgi.service.transaction.control.ResourceProvider` for each of the  resources that you want to use.
You may want to start with link:localJDBC.html[local JDBC].

== Scoping Work using TransactionControl

The Transaction Control Service defines three different scopes:

* Unscoped - There is no scope associated with the current thread
* _No Transaction Scope_ - There is a scope associated with the current thread, but no ongoing transaction
* _Transactional Scope_ - There is an ongoing transaction associated with the current thread

Scoped resources have different behaviours in each of these three scopes:

* Unscoped - The resource is generally not usable and will throw exceptions
* _No Transaction_ Scope - The same physical resource will be used throughout the scope,  and will be automatically tidied up at the end of the scope (e.g.
closed or returned to a pool)
* _Transactional Scope_ - The same physical resource will be used throughout the scope, will be  automatically committed or rolled back up at the end of the transaction, and then tidied up afterwards

=== Starting and Finishing scopes

A scope is defined using a piece of work wrapped in a `Callable`.
This means that it is lambda-friendly.

 Integer result = txControl.required(() -> {
         //Work goes in here
         return 42;
     });

The scope starts immediately before the work is executed, and finishes immediately afterwards.
The  `required` and `requiresNew` methods can be used to ensure that a  _Transactional_ scope has been started.
The `supports` and `notSupported` methods can be used to ensure that a _No Transaction_ scope has been started.

Simple scope management is perfect in most situations, but you may also wish to read about link:advancedScopes.html[more advanced scope control techniques] or link:exceptionManagement.html[exception management] once you've mastered the basics.
There are also some things to consider if you're link:spring-tx.html[migrating from Spring or Java EE].

== Accessing Resources

A `ResourceProvider` 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  `JDBCConnectionProvider` and `JPAEntityManagerProvider` interfaces.
If needed you can link:advancedResourceProviders.html[make your own ResourceProvider].

To create your scoped resource you make one call to `getResource` passing in the  `TransactionControl` service that the resource should integrate with.
The returned object is thread-safe, and can be cached for use in any scope.

=== Declarative Services Example

The following component provides read and write access using JDBC to a list of messages created by a user.
The transactionality and lifecycle of the database resources is automatically managed.

....
@Component
public class MyDaoImpl implements MyDao {

    @Reference
    TransactionControl control;

    Connection dbConn;

    @Reference
    void setResource(JDBCConnectionProvder provider) {
        dbConn = provider.getResource(control);
    }

    @Override
    public void saveMessage(String user, String message) {
        txControl.required(() -> {
                PreparedStatement ps = connection.prepareStatement(
                        "Insert into MESSAGES values ( ?, ? )");
                ps.setString(1, user);
                ps.setString(2, message);
                return ps.executeUpdate();
            });
    }

    @Override
    public void getMessagesForUser(String user) {
        return txControl.supports(() -> {
                PreparedStatement ps = connection.prepareStatement(
                        "Select MESSAGE FROM MESSAGES WHERE USER = ?");
                ps.setString(1, user);

                List<String> result = new ArrayList<>();

                ResultSet rs = ps.executeQuery();

                while(rs.next()) {
                    result.add(rs.getString(1));
                }

                return result;
            });
    }
}
....
