Figure 1.2 shows an overview of the OSGi transaction architecture in Fuse ESB. The core of the architecture is a JTA transaction manager based on Apache Geronimo, which exposes various transaction interfaces as OSGi services.
The JTA Transaction Services Specification section of the OSGi Service Platform Enterprise Specification describes the kind of transaction support that can (optionally) be provided by an OSGi container. Essentially, OSGi mandates that the transaction service is accessed through the Java Transaction API (JTA).
The transaction service exports the following JTA interfaces as OSGi services (the JTA services):
javax.transaction.UserTransaction
javax.transaction.TransactionManager
javax.transaction.TransactionSynchronizationRegistry
Only one JTA provider should be made available in an OSGi container. In other words, the JTA services are registered only once and the objects obtained by importing references to the JTA services must be unique.
The Fuse ESB transaction service exports the following additional interfaces as OSGi services:
org.springframework.transaction.PlatformTransactionManager
org.apache.geronimo.transaction.manager.RecoverableTransactionManager
By obtaining a reference to the PlatformTransactionManager
OSGi service,
it is possible to integrate application bundles written using the Spring transaction API
into the Fuse ESB transaction architecture.
Fuse ESB provides an OSGi-compliant implementation of the transaction service in the following bundle (which is installed in the OSGi container by default):
org.apache.aries.transaction.manager
The Fuse ESB transaction bundle exports exports a variety of transaction interfaces as OSGi services (making them available to other bundles in the container), as follows:
JTA interfaces—the JTA
UserTransaction
,TransactionManager
, andTransactionSynchronizationRegistry
interfaces are exported, as required by the OSGi transaction specification.Spring transaction interface—the Spring
PlatformTransactionManager
interface is exported, in order to facilitate bundles that are written using the Spring transaction APIs.
The PlatformTransactionManager
OSGi service and the JTA services access
the same underlying transaction manager.
The underlying implementation of the Fuse ESB transaction service is provided by the Apache Geronimo transaction manager. Apache Geronimo is a full implementation of a J2EE server and, as part of the J2EE implementation, Geronimo has developed a sophisticated transaction manager with the following features:
Support for enlisting multiple XA resources.
Support for 1-phase and 2-phase commit protocols.
Support for suspending and resuming transactions.
Support for automatic transaction recovery upon startup.
The transaction recovery feature depends on a transaction log, which records the status of all pending transactions in persistent storage.
The implementation of the transaction log is provided by HOWL, which is a high speed persistent logger that is optimized for XA transaction logs.
Normally, it is recommended that application bundles access the transaction service through the JTA interface. To use the transaction service in a JTA-based application bundle, import the relevant JTA service as an OSGi service and use the JTA service to begin, commit, or rollback transactions.
If you have already implemented an application bundle using the Spring transaction
API, you might find it more convenient to access the transaction service through the
Spring API (represented by the PlatformTransactionManager
Java interface).
This means that you are able to deploy the same source code either in a pure Spring
container or in an OSGi container, by changing only the configuration snippet that
obtains a reference to the transaction service.
In order to enlist multiple resources in the same transaction (where a transaction is
committed through the 2-phase commit protocol), it is necessary for each participating
resource to provide an XA switch. An XA switch is an object that
enables the transaction manager to control a resource manager through the XA
interface, javax.transaction.xa.XAResource
.
The JTA provides a method for enlisting XAResource
objects in the
current transaction. Using this approach, it is possible to enlist multiple XA resources
in the current transaction.
The standard JTA approach to enlisting XA resources is to add the XA resource to the
current javax.transaction.Transaction
object (representing the current
transaction). In other words, you must explicitly enlist an XA resource every
time a new transaction starts.
If you are familiar with how transactions work in J2EE containers, you might find this approach surprising: a J2EE container automatically enlists the relevant XA resource in the current transaction whenever you access a data source. In contrast to the J2EE approach, however, the OSGi container does not automatically enlist XA resources in the current transaction. You must write the code to enlist the XA resources yourself or implement a custom wrapper layer.
In the case of JMS XA resources, Fuse Message Broker provides an XA pool wrapper class that implements auto-enlistment for you. Use the following JMS connection factory class:
org.apache.activemq.pool.XaPooledConnectionFactory
Implements JMS pooled connections and auto-enlistment of the JMS XA resource. This class is provided by the
activemq-pool
Maven artifact.
![]() | Note |
---|---|
If you are using a JMS implementation other than Fuse Message Broker, you could use the XA
pool connection factory from the Jencks project,
|
Fuse Message Broker supports the standard JMS framework for managing transactions. The approach to managing transactions in JMS depends on whether you use local transactions (where the broker is the only participating resource) or global transactions (where multiple resources participate in the transaction), as follows:
Local transactions—transactions involving the receiving or sending of messages are demarcated using the
commit()
orrollback()
methods of thejavax.jms.Session
object (assuming that the current JMS session is marked as transacted).Global transactions—the JMS client must use the
ActiveMQXAConnectionFactory
JMS connection factory to access the broker in this case. This connection factory enables you to createjavax.jms.XASession
session objects, which provide an XA resource through thegetXAResource()
method. You can then enlist the XA resource in the current JTA transaction and use thejavax.transaction.TransactionManager
interface to demarcate transactions.
Through the ActiveMQXAConnectionFactory
JMS connection factory, Fuse Message Broker
can provide an XA resource that represents the underlying message broker. This means
that messages will not be added to or removed from the broker's persistent storage,
unless the current transaction completes successfully. The following broker persistence
layers provide full support for the XA protocol (including a persistent transaction log
that enables recovery):
AMQ
Journal
KahaDB
To obtain a reference to the Fuse Message Broker XA resource, you must use the
ActiveMQXAConnectionFactory
JMS connection factory to access the
broker.
Fuse Mediation Router provides a Camel JMS component, which is capable of integrating with the JTA transaction service with full support for XA transactions. In order to support XA transactions, you must configure the Camel JMS component's JMS connection factory and transaction manager as follows:
Connection factory—use the Apache ActiveMQ
XaPooledConnectionFactory
class to wrap an Apache ActiveMQActiveMQXAConnectionFactory
instance.Transaction manager—use the Spring
JtaTransactionManager
class to wrap the JTAUserTransaction
andTransactionManager
instances (alternatively, you could just reference thePlatformTransactionManager
instance exported by the Fuse ESB transaction manager implementation—see Spring transaction integration).
In principle, you can replace the default transaction manager with an alternative transaction manager, but this requires you to write a significant amount of custom code. If you want to replace the Geronimo transaction manager with a different transaction manager implementation, you could do so as follows:
Uninstall the default OSGi transaction service bundle,
org.apache.aries.transaction.manager
.Implement your own transaction service bundle, which exports the standard JTA interfaces as OSGi services (see OSGi mandated transaction architecture).
Install your custom transaction service bundle into the OSGi container.
![]() | Tip |
---|---|
For example, a suitable alternative transaction manager is Atomikos TransactionEssentials, which is another Open Source, Apache-licensed transaction manager. But this transaction manager does not currently provide its own OSGi integration layer, so you would have to implement that yourself. |
The following specifications are relevant to the transaction architecture in Fuse ESB:
OSGi transaction specification—in section 123 JTA Transaction Services Specification v1.0 from the OSGi Service Platform Enterprise Specification v4.2
Spring transactions API—see the Transaction Management chapter from the current Spring Reference Manual.