A form handler that can manipulate repository items should ensure that all operations that occur in a handler method call happen in a single transaction. If all the operations in a method call do not occur in the same transaction, there is the risk that if something goes wrong in the middle of the operation, incomplete data is committed to the repository. Committing all the operations at once ensures that a repository or database transaction is either completed successfully, or not completed at all, and any partially committed data is rolled back.

The RepositoryFormHandler and TransactionalRepositoryFormHandler classes ensure atomic transactions in this way. If you subclass either class without overriding the handler methods, your subclass handles transactions properly. If you override any handler methods, or add new handler methods, you must make sure that these methods handle transactions properly.

To create a form handler that works with repository items while a transaction is in progress:

Note: Keep in mind that RepositoryFormHandler and TransactionalRepositoryFormHandler are useful for manipulating repository items specifically. If you’d rather work with the JDBC directly in a form handler that supports transactions, use the atg.droplet.TransactionFormHandler.

Using RepositoryFormHandler or TransactionalRepositoryFormHandler

You need to decide which form handler, TransactionalRepositoryFormHandler or RepositoryFormHandler, you want to subclass. The source code for both form handlers is provided here: <ATG9dir>/DAS/src/Java/atg/repository/servlet. You can also navigate to API documentation for both classes in ATG API Reference.

The atg.repository.servlet.RepositoryFormHandler is a base form handler that provides tools for creating, modifying, and deleting items stored in an SQL repository. The only direct instance of this class provided in the ATG Adaptive Scenario Engine is /atg/demo/QuincyFunds/FormHandlers/EmailRepositoryFormHandler. Learn more about this form handler by reading the Using Repository Form Handlers chapter of the ATG Page Developer’s Guide.

The atg.repository.servlet.TransactionalRepositoryFormHandler, a subclass of the RepositoryFormhandler, provides enhanced transaction support by broadening the scope of the transaction. This class also defines a few additional properties that are useful for transaction monitoring. ATG Adaptive Scenario Engine does not include any instances of this class.

Both form handlers create a transaction if one is not already in progress and provide the status of all operations performed by the form handler while the transaction is in place. The main difference between the form handlers is the lifespan of the transaction.

In the RepositoryFormhandler, the transaction is governed entirely by the submit handler method, meaning the transaction starts when a submit handler method is invoked and ends when it completes execution. Transaction status is reported for the data validation and the data commit operations.

Transactions in the TransactionalRepositoryFormHandler begin when the beforeSet method is invoked and end with the afterSet method. Because a transaction status is generated for all operations that occur during its execution, a status is recorded for each the following operations:

  • beforeSet method execution

  • processing of all other tags in the JSP (tags that implement submit operations have the lowest priority on the page)

  • submit handler method data validation

  • submit handler method data commit

  • afterSet method execution

So, choose your superclass form handler class based on the actions that you want included in a transaction.

Note: A transaction is started and ended by a form handler only when there are no other active transactions. If a transaction is in progress, the form handler returns a status for each operation it attempts and permits the transaction to continue after the form handler itself finishes processing.

Creating Methods that Support Transactions

After you create your subclass, make sure that the methods you specify for it can correspond with the Transaction Manager. There are two ways to do this:

New Methods Based on handleUpdate Source Code

The code provided here implements the handleUpdate method. Create your own handler methods by making changes to this code sample and inserting it into your subclassed form handler:

public boolean handleUpdate(DynamoHttpServletRequest pRequest,
                            DynamoHttpServletResponse pResponse)
     throws ServletException, IOException
{
  TransactionDemarcation td = getTransactionDemarcation();
  TransactionManager tm = getTransactionManager();
  try {
    if (tm != null) td.begin(tm, td.REQUIRED);

    int status = checkFormError(getUpdateErrorURL(), pRequest, pResponse);
    if (status != STATUS_SUCCESS) return status == STATUS_ERROR_STAY;

    // update the repository item
    preUpdateItem(pRequest, pResponse);

    if (!getFormError())
      updateItem(pRequest, pResponse);

    postUpdateItem(pRequest, pResponse);

    // try to redirect on errors
    if ((status = checkFormError(getUpdateErrorURL(), pRequest, pResponse))
     != STATUS_SUCCESS)
   return status == STATUS_ERROR_STAY;

    // try to redirect on success
    return checkFormSuccess(getUpdateSuccessURL(), pRequest, pResponse);
  }
  catch (TransactionDemarcationException e) {
    throw new ServletException(e);
  }
  finally {
   try { if (tm != null) td.end(); }
    catch (TransactionDemarcationException e) { }
  }
}

Extending Existing Methods

The three existing submit handler methods (handleCreate, handleUpdate, and handleDelete) each come with a pair of empty pre and post methods to which you can add custom code.

It is likely that you use either the preX or the postX method for a given existing handler method although it is possible for you to customize both. For example, consider a subclass of TransactionalRepositoryFormHandler where preUpdate and postUpdate are used:

  1. The form is rendered, which causes getX method to display current values for properties used in the form.

  2. The user fills in the form and submits it.

  3. The form handler’s beforeSet method is invoked. If a transaction is not currently in progress, the TransactionalRepositoryFormHandler component creates a one.

  4. If tag converters are used, they are applied to the specified content. Any form exceptions that occur now or at any point during the form handler execution are saved to the form handler’s formException property.

  5. The setX method is called, followed by the form handler’s handleUpdate method. Severe form exceptions might cause form processing to stop and the transaction to rollback, before redirecting users to a different page.

  6. The preUpdateItem method is invoked. The preX method for the handleUpdate method is preUpdateItem. Serious errors generated from this operation might also prompt the transaction to rollback.

  7. The updateItem method, which is the handleUpdate method responsible for processing the content and updating the database, is invoked. Again, this is another operation that can cause a transaction to rollback when serious errors are detected. At this point, the changes made by the actions associated with the transaction are kept private, meaning that they are only visible within the transaction itself.

  8. The postUpdateItem method is invoked. Again, the transaction is rolled back if serious errors are detected.

  9. The afterSet method is invoked. If the transaction was started by the beforeSet method, the transaction concludes and the content it saved to the database is publicly visible.

You should use the preX method when you want to expand the constraints for data validation. For example, you might want to check if the user-entered zip code and country correspond to each other. The countries that use zip codes require them to be a certain length. The preX method can verify that a zip code uses the appropriate format for the country, before saving the zip code and country values to the database. Any discrepancies produce a form exception and roll back the transaction.

Alternatively, the postX method is useful when you want to verify user entered-data after that data has been converted by tag converters. For example, a form handler that saves credit card information might use a postX method to handle authorization. After that credit card number has been formatted correctly and all related information is updated in the database, the postX method executes. If the authorization fails, the transaction is rolled back, the original data refreshed, a form error exception is thrown, and the user is redirected to a page where the use can re-enter credit card information.

 
loading table of contents...