Transaction Support
Application
controlled Commit and Rollback
The Ebase
Xi Server treats each interaction with the user as a discrete transaction. In
detail, this means that a transaction is started each time input is received
from the end user and is ended when output is sent back to the user or the form
ends. It is important to realize that the scope of a transaction does not
span multiple user interactions or multiple form pages. For this reason, all
updates should ideally be made at the same time - typically this is done when
all user input has been validated i.e. in the end of form event scripts, or a
script activated as a result of an end user ‘Submit’.
This basic
‘single transaction’ model can be changed if required by using the FPL commit
and rollback commands or API methods TransactionManager.commitAndRestartTransaction() and TransactionManager.rollbackAndRestartTransaction().
Please note
that sequences are not included within the scope of an
Ebase Xi transaction. Updates to sequences are made immediately when the FPL sequence command or API SequenceManager.sequence() method is invoked and cannot be rolled
back.
Each
transaction can include any or all of the following:
·
database updates made from Ebase Xi i.e. using
script statements or Java classes invoked from script statements
·
all updates made by EJBs
called from Ebase Xi (these should have transactional attribute TX_REQUIRED no
enable them to join the Ebase Xi transaction context)
·
all updates made by custom Java functions where
these are made using the standard facilities of the J2EE Application Server
·
all updates made by other application systems
e.g. CICS, SAP etc. where the connection to the system is made using a resource
manager managed by the J2EE Application Server
Ebase Xi
uses the facilities of the J2EE Application Server to provide a transactional
context. The scope of the transaction (i.e. what is included within each
transaction) depends on two factors:
1.
The capabilities of the transaction manager
- this is typically provided by the J2EE Application Server
2.
The capabilities of the resource managers
used e.g. JDBC drivers, JMS providers, CICS resource managers etc.
The
simplest form of transaction involves just one resource manager, usually a
database. This type of transaction is usually easy to configure and in most
cases is the default behaviour for the application server and the resource
manager being used. In this scenario, all updates to the resource made from
Ebase Xi plus updates made from Java classes or EJBs
called via Ebase Xi custom functions and custom resources will be included in
the transaction.
Transactions
that span more than one resource manager are more complex e.g. two database
providers or one database and a JMS provider. These require two things : a two phase commit transaction manager, and
resource managers that understand the two phase commit protocol. This type of
behaviour is more complex and application servers and resource managers vary in
their ability to support it. You will need to read the documentation provided
by your application server and the resource managers to see whether they
provide this support and how it is configured.
To access
the transactional facilities of the J2EE Application Server, Ebase Xi performs
a lookup in the application server's naming service using the name "java:comp/UserTransaction".
However, some application servers use a different name and this can be
specified in the Ufs.transactionJNDIName
property of the server properties file UfsSetup.properties.
The transaction timeout period can be specified in two places:
· Property jotm.timeout in the configuration XML file for the web application e.g. UfsServer/tomcat/conf/Catalina/localhost/ufs.xml. This has a supplied value of 120 seconds.
· Server property Transaction Timeout. If specified this overrides the previous property. This property has the advantage that it can be changed without restarting the server.
This value
should be large enough to accommodate the longest running transaction that
occurs in normal processing. In particular, it may be necessary to specifiy a higher value if long running scheduled tasks are
used. If you have failures which include message Transaction was marked for rollback and has been rolled back, this indicates that the
transaction period has been exceeded.
Each
transaction is committed automatically by the system each time a page is sent
to the end user or when the form ends normally. If an error occurs during form
execution that results in abnormal termination of the form, the transaction
will be automatically rolled back.
In
addition, the FPL commit and rollback script
commands (API methods TransactionManager.commitAndRestartTransaction() and TransactionManager.rollbackAndRestartTransaction() ) are provided to enable the designer
to commit or rollback a transaction as required by the application. These
commands/methods will then start an additional transaction to handle any
further processing. This makes it possible for an application to create many
transactions that are committed or rolled back under application control.
Commit and
rollback can also be called by customer written Java code extensions – custom
functions and custom resources. Both of these extensions can call commitTransaction() and rollbackTransaction() on their respective interfaces UFSFormInterface and ResourceRequestInterface.
In both cases, the system
will automatically start an additional transaction to handle any further
processing. See javadoc
for futher details
Please note
that updates to sequences are not
affected by these commands. These updates are made immediately when the FPL sequence
command or API SequenceManager.sequence() method is issued, and cannot be rolled back or explicitly
committed.
The
transaction support described in the previous section provides a transactional
context covering only a single interaction with the end user. Therefore, this
cannot be used to lock database (or other) resources across an entire form
consisting of multiple pages. To meet these requirements Ebase Xi provides explicit
locking support covering both optimistic and pessimistic locking.
This option
is activated by selecting the optimistic locking option on the Transactions
tab of Form properties for the form. It applies only to database updates
of a single record.
When the option is selected, the system will check that a record about to be updated has the same values as it did when it was originally read from the database using an FPL fetch command or API DatabaseResource.fetch() method. If the values are unchanged then the update is performed. If the values have been changed, the update is not performed:
·
With the FPL language, the command status is set
indicating the error (see update command in FPL Script Command Syntax) and this must
be checked by the script issuing the update; this script should then take
appropriate steps e.g. inform the end user.
· With an API based language, the DatabaseResource.update() method throws an OptimisticLockingException.
Note: optimistic
locking is not available for table
operations where the table is backed by a database resource i.e. it is not
support for fetchtable and updatetable
commands or API Table.fetchTable() or Table.updateTable() methods,.
Ebase Xi
provides the ability to acquire and release locks against an abstract resource.
This is designed for use by more advanced applications where the resource to be
locked is more complex than a simple database table. The locks are acquired and
released using the FPL script commands lock and unlock or API methods LockManager.lock()
and LockManager.unlock(). These
commands both require a resource name and a resource id.
The resource name can be any name but it is obviously important that the
same name is used by all forms that access the same resource. Examples of
resource names might be CUSTOMER, CONTRACT, ORDER etc.
The resource id is a unique identifier to identify this particular
resource e.g. customer number, contract number etc.
With the FPL language, if a lock command is issued and the requested lock is held by another user, the command status will be set to 'ERROR'. The FPL script issuing the lock must check the command status and take appropriate action if the lock could not be acquired.
The
following example shows FPL commands to acquire a lock for a customer
modification form:
lock 'CUSTOMER', CUSTOMER_ID;
(where
CUSTOMER_ID is a form field containing a unique customer identifier)
if [ $COMMAND_STATUS = 'ERROR' ]
message E,1234, CUSTOMER_ID;
endif
Message
1234 is: "Customer && is
currently being modified by another user - please try again later."
The FPL
script command to release the lock is:
unlock 'CUSTOMER', CUSTOMER_ID;
With an API based language, LockManager.lock() returns false if the requested lock is held by another user.
All locks
are exclusive i.e. they can only be held by one user at a time. Ebase Xi does
not support shared locks.
The scope
of a lock includes an entire form i.e. it spans multiple user interactions. All
held locks are released by the system automatically when the form ends, either
normally or abnormally. However, it is good practice to explicitly release
locks when they are no longer required.
The locks
held can be displayed using the Server
Administration Application.