Transaction Support
Application
controlled Commit and Rollback
The Verj.io 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 Verj.io 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 Verj.io
i.e. using script statements or Java classes invoked from script statements
·
all updates made by EJBs
called from Verj.io (these should have transactional
attribute TX_REQUIRED no enable them to join the Verj.io
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
Verj.io 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 Verj.io plus updates made from Java classes or EJBs called via Verj.io 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, Verj.io 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:
· With 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.
· Can be overridden using Javascript:
system.transactionManager.setDefaultTransactionTimeout();
system.transactionManager.commitAndRestartTransaction();
The default
value for your system should be large enough to accommodate the longest running
transaction that occurs in normal processing. In particular, it may be
necessary to specify 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 (Javascript 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 Verj.io
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,.
Verj.io 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. Verj.io 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.