<% set_title("How to Run a", product_name, "Cache Transaction") %>

<!--
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.
-->
<a id="task_f15_mr3_5k"></a>


This topic describes how to run a <%=vars.product_name%> cache transaction.

Applications manage transactions on a per-cache basis. A <%=vars.product_name%> cache transaction starts with a `CacheTransactionManager.begin` method and continues with a series of operations, which are typically region operations such as region create, update, clear and destroy. The begin, commit, and rollback are directly controlled by the application. A commit, failed commit, or voluntary rollback by the transaction manager ends the transaction.

You can run transactions on any type of cache region except regions with **global** scope. An operation attempted on a region with global scope throws an `UnsupportedOperationException` exception.

A transaction may not be nested within another transaction. An attempt to begin a nested transaction will throw an `IllegalStateException` exception.

This discussion centers on transactions on replicated and partitioned regions. If you use non-replicated distributed regions, follow the guidelines for replicated regions.

1. **Configure the cache copy-on-read behavior in the members hosting the transactional data, or perform cache updates that avoid in-place changes.** This allows the transaction manager to control when cache updates are visible outside the transaction. See [Setting Global Copy on Read](working_with_transactions.html#concept_vx2_gs4_5k).
2. **Configure your regions for transactions in the members hosting the transactional data.**

    | If you use...                                                                               | then you should...                                                                                                                                                                                                                                                                                                                                                                                            |
    |---------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    | **replicated regions**                                                                      | Use `distributed-ack` scope. The region shortcuts specifying `REPLICATE` use `distributed-ack` scope. This is particularly important if you have more than one data producer. With one data producer, you can safely use `distributed-no-ack`.                                                                                                                                                                        |
    | **partitioned regions**                                                                     | Custom partition and colocate data among regions so all the data for any single transaction is hosted by a single member. If the transaction is run from a member other than the one hosting the data, the transaction will run by proxy in the member hosting the data. The partitioned region must be defined for the application that runs the transaction, but the data can be hosted in a remote member. |
    | **persistent regions**                                                                      | Configure <%=vars.product_name%> to allow transactions on persistent regions. By default, the configuration does not allow transactions on persistent regions. Enable the use of transactions on persistent regions by setting the property `gemfire.ALLOW_PERSISTENT_TRANSACTIONS` to true.                                                                                              |
    | **a mix of partitioned and replicated regions**                                             | Make sure any replicated region involved in the transaction is hosted on every member that hosts the partitioned region data. All data for a single transaction must reside within a single host.                                                                                                                                                                                                             |
    | **delta propagation**                                                                       | Set the region attribute `cloning-enabled` to true. This lets <%=vars.product_name%> do conflict checks at commit time. Without this, the transaction will throw an `UnsupportedOperationInTransactionException ` exception.                                                                                                                                                                      |
    | **global JTA transactions with only <%=vars.product_name%> cache transactions** | Set the region attribute `ignore-jta` to true for all regions that you do *not* want to participate in JTA global transactions. It is false by default. For instructions on how to run a JTA global transaction, see [JTA Global Transactions with <%=vars.product_name%>](JTA_transactions.html).   |

3. **Update your cache event handler and transaction event handler implementations to handle your transactions.** 
    Cache event handlers may be used with transactions. Cache listeners are called after the commit, instead of after each cache operation, and the cache listeners receive conflated transaction events. Cache writers and loaders are called as usual, at the time of the operation.

    Follow these additional guidelines when writing cache event handler callbacks:
    -   Make sure cache callbacks are transactionally aware, because a transactional operation could launch callbacks that are not transactional.
    -   Make sure cache listeners will operate properly, given entry event conflation. Two events for the same key are conflated by removing the existing event and queuing the new event.

    See [Using Cache Writer and Cache Listener Plug-Ins](working_with_transactions.html#concept_ysx_nf1_wk) for more information.

    Transaction event handlers are available. Transaction event handlers are cache-wide. You can install one transaction writer and any number of transaction listeners. Follow these guidelines:
<ul>
    <li>Implement with synchronization for thread safety. Listener and writer handlers may be invoked at the same time by different threads for different transactions.</li>
    <li>Keep transactional callback implementations lightweight, and avoid doing anything that might cause the callbacks to block.</li>
</ul>
    See [Configuring Transaction Plug-In Event Handlers](working_with_transactions.html#concept_ocw_vf1_wk) for more information.

4. **Write the transaction code.** For example: 

    ``` pre
    CacheTransactionManager txManager =
              cache.getCacheTransactionManager();

    try {
        txManager.begin();
        // ... do work
        txManager.commit();
    } catch (CommitConflictException conflict) {
        // ... do necessary work for a transaction that failed on commit
    }
    ```

    Follow these guidelines when writing the transaction:
    -   Start each transaction with a begin operation.
    -   Consider whether you will want to suspend and resume the transaction. If some operations should not be part of the transaction, you may want to suspend the transaction while performing non-transactional operations. After the non-transactional operations are complete, you can resume the transaction. See [Basic Suspend and Resume Transaction Example](transaction_suspend_resume_example.html#concept_40AAC4332DCE4E4EB60C4BA141B729A4) for an example.
    -   If your transaction operates on a mix of partitioned and replicated regions, do the first region operation on an entry of the partitioned region. This sets the host for the entire transaction.
    -   If you did not configure copy-on-read to true, be sure all cache updates avoid in-place changes.
    -   Take into account the behavior of transactional and non-transactional operations. All transactional operations that are run after the begin and before the commit or rollback are included in the transaction.
    -   End each transaction with a commit or a rollback. Do not leave any transaction in an uncommitted or unrolled back state. Transactions do not time out, so they will remain for the life of the application.

5. **Review all of your code for compatibility with transactions.** 
    When you commit a transaction, while the commit is in process, the changes are visible in the distributed cache. This provides better performance than locking everything involved with the transaction updates, but it means that another process accessing data used in the transaction might get some data in the pre-transaction state and some in the post-transaction state.

    For example, suppose keys 1 and 2 are modified within a transaction, such that both values change from A to B. In another thread, it is possible to read key 1 with value B and key 2 with value A, after the commit begins, but before the commit completes. This is possible due to the nature of <%=vars.product_name%> reads. This choice sacrifices atomic visibility in favor of performance; reads do not block writes, and writes do not block reads.


