Document Properties
Kbid275R84
Last Modified04-Feb-2020
Added to KB19-May-2016
Public AccessEveryone
StatusOnline
Doc TypeGuidelines, Concepts & Cookbooks
Product
  • ICM 7.6
  • ICM 7.7
  • ICM 7.8
  • ICM 7.9
  • ICM 7.10

Guide - Control Transactions

1 Introduction

This guide is addressed to developers who intend to enhance persistent objects' beans.

The transaction control as discussed here aims at preventing errors that may occur because of (pipeline-based) transactions that have been triggered in parallel, like, for example, double-clicking a link or a button in the storefront.

Changing a PO bean requires a transaction, for example when:

  • Creating a new instance
  • Removing an instance
  • Setting an attribute or a relation

With POs, there are no implicit transactions (as in EJBs). Changing an object without transaction leads to an exception. There are two basic alternatives for transaction handling in this context:

  • Control transactions in pipelines
    This is the recommended option. In case a pipelet changes a PO, mark the pipelet as transactional. This ensures that the pipeline opens a transaction before executing the pipelet. In addition, the scope of transactions can be controlled at pipeline level (see Transaction Control at Pipelet and Pipeline Level ).
  • Manual transaction handling
    See Manual Transaction Handling .

2 Manual Transaction Handling

It is possible to open and close transactions manually using the ORM engine API. To get the transaction for the current thread:

ORMMgr mgr = (ORMMgr) NamingMgr.getInstance().lookupManager(ORMMgr.REGISTRY_NAME);
ORMEngine engine = mgr.getORMEngine();
Transaction txn = engine.getTransactionManager().getCurrentTransaction();
txn.begin(); txn.store(); txn.commit();

Transactions are reusable, hence multiple begin - commit - begin - ... cycles are allowed. Note, however, that transaction nesting is not supported by the ORM engine.
The ORM transaction exposes a method to set a cache synchronization mode. The respective method is:

public void com.intershop.beehive.orm.capi.transaction.Transaction.setSynchronizationMode
(com.intershop.beehive.orm.capi.synchronization.SynchronizationMode mode)

The synchronization mode is considered only if cache synchronization is switched on. The mode is one of NONE, INSTANCE, CLASS or CACHE.

  • NONE
    No cache synchronization is performed at the end of the transaction. Here are two possible scenarios where this mode can be useful:
    • The transaction is part of an import process where an external cache refresh event is always sent due to updates bypassing the ORM layer.
    • A custom transaction listener deals with cache synchronization.
  • INSTANCE
    This is the default mode. It is equivalent to the behavior in previous releases. For each updated or deleted persistent object, a single cache synchronization message is sent. The servers receiving such an event will remove the according object state from the cache (if available there).
  • CLASS
    Synchronization events are sent on class level, i.e. changing or deleting multiple objects of the same class will result in one single cache synchronization message for this class. The servers receiving this event will drop all object states of the according class from the cache. This mode is useful for executing mass data operations through the ORM layer to reduce the number of multicast messages.
  • CACHE
    One single message is sent after committing the transaction successfully. Servers receiving this event will clear the entire cache. Only useful for heavy changes.

3 Transaction Control at Pipelet and Pipeline Level

At pipelet and pipeline level, it is possible to explicitly control transaction demarcation, i.e., to define at which point the pipeline processor should begin, commit or rollback a database transaction. This makes it possible to execute a single pipelet or a series of pipelets within a single database transaction. The transaction context extends into pipelines joined by call or jump nodes.

3.1 Implicit and Explicit Transaction Demarcation

If a pipelet defines transaction-sensitive methods, the pipelet property "Transaction Required" can be set. This forces the pipeline processor to open a transaction before executing the pipelet and to attempt a commit immediately afterwards. This is also true if the pipelet exits through the error exit.

When designing pipelines that contain such a pipelet, you can leave transaction demarcation to the pipeline processor (implicit transaction demarcation) or you can explicitly define at which point during pipeline execution a transaction should begin, commit or rollback.
Consider the simple example in the figure below, each pipeline containing a pipelet which requires a database transaction (marked with a 'T' in the VPM). In the pipeline with the Start1 start node, no explicit transaction points have been set, thus transaction demarcation is handled implicitly by the pipeline processor. The pipeline processor begins a transaction before executing Pipelet2, and commits once the pipelet has been executed. Therefore, the transaction context only spans Pipelet2, but excludes Pipelet1 and Pipelet3.
In the pipeline beginning with start node Start2, it has been defined at the pipeline level that a transaction should begin before processing Pipelet1, and that a commit should take place after processing Pipelet2. Here, the transaction context spans Pipelet1 and Pipelet2, excluding Pipelet3. Pipelet2 joins the transaction opened at the pipeline level.

As illustrated in the figure, explicit transaction demarcation at the pipeline level is expressed via properties of transitions connecting pipeline nodes (see the table below).

Property

Description

None

Default setting. If you do not need an explicit transaction, this value is set automatically and does not need to be changed.

Begin

Ensures that a transaction is active. If a transaction is already active, the nested transaction counter is incremented.

Commit

Decrements the nested transaction counter and commits the transaction to the database when the outermost nested transaction is reached. If no transaction is active, nothing happens.

Savepoint

Used to write any data that has been changed within the current transaction. Any following rollback will only be effective to this point.

FlushUsed to store the current transaction to the database without committing it. In addition, the transactional ORM cache is cleared.
StoreUsed to store the current transaction to the database without committing it.

Rollback

Used to undo any change done on processed data to the beginning of the outermost nested transaction.

The following basic properties of transaction demarcation are important:

  • If a transaction is still active when pipeline execution finishes (e.g., an interaction node is reached), the transaction is automatically committed to the database.
  • Implicit and explicit transaction demarcation do not interact. To close a transaction which was begun explicitly (before the end of the pipeline has been reached), an explicit Commit is necessary.

For further information, refer to Reference - Pipeline Node Reference.

3.2 Pseudo-Nested Transactions

It is possible to nest transactions in pipelines, using multiple begin/ commit pairs. The pipeline manager tracks nested transactions with a counter. A begin raises the count by 1, a commit decreases it by one. If, after its one-unit decrease, the count is 0, a true database commit is performed. This behavior can become complicated with commits and savepoints in nested transactions.
A commit decreases the count by 1, but a real database commit only takes place if the counter is 0. A savepoint writes the active transaction to the database (and so makes the changes available to, e.g., JDBC select statements) and does not change the value of the counter.

3.3 Additional Transaction Handling Guidelines

  • Use Short Transactions
    When using transactions, keep in mind that transactions are memory and resource intensive operations. Use transactions only where necessary and try to minimize the transaction's context.
  • Read Operations Should be Performed Outside of Transactions
    Database queries should always be executed outside transactions, in particular if the queries return large data sets that are handled by a PageableIterator. PageableIterator _objects enable developers to process large result sets in small chunks of data. To view all chunks of the result set, (parts of) pipelines involving _PageableIterator objects are typically iterated multiple times, with each iteration making a subset of data available (see the figure below). In this context, it is important to note that PageableIterator objects use a cache to temporarily hold parts of the result set. If you submit a query and create an PageableIterator object inside a transaction, this cache is cleared once the transaction commits, possibly invalidating parts of the result set. Hence, always commit active transactions before submitting a query, as illustrated in the figure below, which illustrates a pipeline fragment creating and processing an IPageable object.

4 Pipeline Transaction Synchronization

Pipeline transaction synchronization allows for globally switching on transaction synchronization in pipelines. A transaction to be start through a transactional pipelet or a pipeline transition with mode "begin transaction" may be blocked as long as another transaction for the same session (the synchronization scope) is active. Based on a given set of synchronization objects the granularity of synchronization can be controlled. Three synchronization objects exist:

  • CurrentRequest
    Transactions of all incoming requests for the same session are synchronized. No transaction blocking occurs if sessions are different (which also applies to the other synchronization objects discussed below).
    To switch this synchronization behavior on, add the following two lines to the is_home/share/system/config/cluster/appserver.properties file:

    intershop.pipelines.transaction.DefaultSynchronizationScope=CurrentSession
    intershop.pipelines.transaction.DefaultSynchronizationObject=CurrentRequest
    
  • CurrentPipeline
    Transactions of all incoming requests are synchronized if they belong to the same session and the pipeline that was initially called to trigger the request has the same name. Thus, jump nodes and call nodes are not evaluated separately.
    To switch this synchronization behavior on, add the following two lines to the is_home/share/system/config/cluster/appserver.properties file:

    intershop.pipelines.transaction.DefaultSynchronizationScope=CurrentSession
    intershop.pipelines.transaction.DefaultSynchronizationObject=CurrentPipeline
    
  • CurrentStartNode
    Transactions of all incoming requests are synchronized if they belong to the same session and the pipeline that was initially called to trigger the request has the same name and the same start node name. Again, jump nodes and call nodes are not evaluated separately.
    To switch this synchronization behavior on, add the following two lines to the is_home/share/system/config/cluster/appserver.properties file:

    intershop.pipelines.transaction.DefaultSynchronizationScope=CurrentSession
    intershop.pipelines.transaction.DefaultSynchronizationObject=CurrentStartNode
    

If the application server properties are missing or one of the properties has an invalid value assigned, no transaction synchronization takes place. The properties are case sensitive.

Disclaimer

The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.

Customer Support
Knowledge Base
Product Resources
Support Tickets