Service Component Architecture (SCA) provides declarative
mechanisms in the form of intents for describing the
transactional environment required by components.
Using a global transaction
Components
that use a synchronous interaction style can be part of a single,
distributed ACID transaction within which all transaction resources
are coordinated to either atomically commit or roll back. This is
specified by using the
managedTransaction.global intent in
the
requires attribute of the
<implementation.java> element
as shown below.
<component name="DataAccessComponent">
<implementation.java class="example.DataAccessImpl"
requires="managedTransaction.global"/>
</component>
It is possible to control whether a component's
service runs under its client's global transaction by specifying either
the
propagatesTransaction or
suspendsTransaction intent
on the component's
<service> element.
- propagatesTransaction - The service runs under its client's
global transaction. If the client is not running in a global transaction
or chose not to propagate its global transaction, the service runs
in its own global transaction.
- suspendsTransaction - The service runs in its own global
transaction separate from the client transaction.
It
is also possible to control whether a component global transaction
is propagated to a referenced service by specifying either the
propagatesTransaction or
suspendsTransaction intent
on the component
<reference> element.
- propagatesTransaction - The component's global transaction
is made available to the referenced service. The referenced service
might or may not use this transaction depending on how it is configured.
- suspendsTransaction - The component's global transaction
is not made available to the referenced service.
Transaction context
is never propagated on @OneWay methods. The SCA run
time ignores propagatesTransaction for OneWay methods.
The
following example shows the use of the
managedTransaction.global,
propagatesTransaction,
and
suspendsTransaction intents. The
DataUpdateComponent runs
in its own global transaction, not in its client's transaction, because
suspendsTransaction is
specified on its
<service> element. Its global
transaction is propagated to the referenced service
DataAccessComponent because
propagatesTransaction is
specified on its
<reference> element.
<component name="DataUpdateComponent">
<implementation.java class="example.DataUpdateImpl"
requires="managedTransaction.global"/>
<service name="DataUpdateService"
requires="suspendsTransaction"/>
<reference name="myDataAccess" target="DataAccessComponent"
requires="propagatesTransaction"/>
</component>
Propagating transactions over
the Web service binding requires the use of a WebSphere
® policy
set that contains the WS-Transaction policy type. You can set up this
policy set in one of the following ways:
- You can import the WSTransaction policy set that is provided with
the product.
- You can create your own policy set and include the WS-Transaction
policy type.
The following example assumes the use of the WSTransaction
policy set.
<composite name="WSDataUpdateComposite"
xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:ws="http://www.ibm.com/xmlns/prod/websphere/sca/1.0/2007/06">
<component name="WSDataUpdateComponent">
<implementation.java class="example.DataUpdateImpl"
requires="managedTransaction.global"/>
<service name="DataUpdateService"
requires="propagatesTransaction">
<binding.ws ws:wsPolicySet="WSTransaction"/>
</service>
<reference name="myDataBuddy" target="DataBuddyComponent"
requires="propagatesTransaction">
<binding.ws ws:wsPolicySet="WSTransaction"/>
</reference>
</component>
</composite>
Tip: Transaction propagating might not
result in a managed connection. Use a qualifying Java EE
module for a managed connection and connection sharing.
Using local transaction containment
Business
logic might have to access transactional resource managers without
the presence of a global transaction. A component can be configured
to run under local transaction containment (LTC). The SCA runtime
starts an LTC before dispatching a method on the component and completes
the LTC at the end of the method dispatch. The component's interactions
with resource providers (such as databases) are managed within resource
manager local transactions (RMLTs). A resource manager local transaction
(RMLT) represents a unit of recovery on a single connection that is
managed by the resource manager.
The local transaction containment
policy is configured by using an intent. There are two choices:
- managedTransaction.local - Use this intent when each interaction
with a resource manager should be part of an extended local transaction
that is committed at the end of the method. The SCA runtime wraps
interactions with each resource manager in a resource manager local
transaction (RMLT). The SCA runtime commits each RMLT at the end
of method dispatch, unless an unchecked exception occurs, in which
case the SCA runtime aborts each RMLT. The component might not use
resource manager commit/rollback interfaces or set AutoCommit to true.
If multiple resource managers are used, the RMLTs are committed independently
so it is possible for some to fail and some to succeed. If this behavior
is not what you want, use a global transaction.
- noManagedTransaction - The SCA runtime does not wrap interactions
with resource managers in a RMLT. The component implementation manages
the start and end of its own RMLTs or gets AutoCommit behavior (which
commits after each use of a resource) by default. The component must
complete any RMLTs before the end of the method dispatch otherwise
the SCA runtime will abort them.
The intent is specified by using the requires attribute
on the
<implementation.java> element. An example is
shown below.
<component name="DataAccessLocalComponent">
<implementation.java class="example.DataAccessImpl"
requires="managedTransaction.local"/>
</component>
A local transaction cannot be propagated from one
component to another. It is an error to specify propagatesTransaction on
a component's <service> if the component uses the managedTransaction.local or noManagedTransaction intent.
Rollback
The
SCA run time performs a rollback under the following circumstances:
- When managedTransaction.global is used, the SCA run time
performs a rollback if the component method that started the global
transaction throws an unchecked exception. An unchecked exception
is a subclass of java.lang.RuntimeException or java.lang.Error. A
checked exception does not force a rollback.
- When managedTransaction.local is used, the SCA run time
performs a rollback if the component method throws an unchecked exception.
An unchecked exception is a subclass of java.lang.RuntimeException
or java.lang.Error. A checked exception does not force a rollback.
- When noManagedTransaction is used, the SCA run time performs
a rollback of any RMLT that has not been committed by the component
method, regardless of whether the method throws an exception or not.
When
managedTransaction.global or
managedTransaction.local is
used, the business logic can force a rollback by using the UOWSynchronization
interface.
com.ibm.websphere.uow.UOWSynchronizationRegistry uowSyncRegistry =
com.ibm.wsspi.uow.UOWManagerFactory.getUOWManager();
uowSyncRegistry.setRollbackOnly();
Transaction intent default behavior
If
transactional intents are not specified, the default behavior is vendor-specific.
If a transactional intent in not specified for the implementation,
the default is managedTransaction.global. If a transactional
intent is not specified for a service or reference, the default is suspendsTransaction.
It is recommended to specify the required intents rather than to
rely on default behavior so that the application is portable.
Using @Requires annotation to specify transaction
intents
You can also specify transaction intents in the
implementation class by using the @Requires annotation.
The general form of the annotation is:
@Requires("{http://www.osoa.org/xmlns/sca/1.0}intent")
For
example, you can use the following in the implementation class:
@Requires("{http://www.osoa.org/xmlns/sca/1.0}managedTransaction.global")
You
can specify required intents on various elements, including the composite,
component, implementation, service and reference elements. An element
inherits the required intents of its parent element except when they
conflict. For example, if a composite element requires managedTranaction.global and
a component element requires managedTransaction.local,
then the component uses managedTransaction.local.