Using timeouts with transactions

There are situations where the time used to execute a transaction takes too long. This can result in unresponsive applications or the appearance that the application has locked up. To control this behavioral aspect of transaction we need to limit the amount of time allocated to a transaction. In this recipe, we will address how this is done.

Getting ready

Using timeouts involves:

  1. Determining whether a timeout period is needed
  2. Determining what that period should be
  3. Using the setTransactionTimeout method in the case of BMT

    Determining whether timeouts should occur or what the timeout period should be is application-specific. As a result we will not address the first two steps here.

    If it is a CMT, we can use the container services to set this limit. The process for doing this is container-specific. For example, in GlassFish the Transaction Timeout period can be configured using the Transaction Service as illustrated in the following screenshot. Notice a Retry Timeout value can also be specified.

    Getting ready

    For a BMT transaction, we can use the setTransactionTimeout method. The focus of this recipe is on the use of this method.

How to do it...

Using the setTransactionTimeout method is pretty simple. The method has a single argument which represents the duration of the time out in seconds. To illustrate its use, modify the changePopulation method of the BeanManagedPopulationManager as developed in the Handling transactions manually recipe. Add a call to the setTransactionTimeout with an argument of 10. After the begin method, add a sleep method to force the current thread to sleep for 20 seconds.

public void changePopulation(String cityName, long count) throws SystemException {
try {
System.out.println("Executing changePopulation");
userTransaction.setTransactionTimeout(10);
userTransaction.begin();
System.out.println("Transaction State: " + getTransactionStateString(userTransaction.getStatus()));
Thread.sleep(20000);
Query query = em.createQuery(
"UPDATE City c " + "SET c.population = c.population+:count " + "WHERE c.name = :cityName");
query.setParameter("count", count);
query.setParameter("cityName", cityName);
int result = query.executeUpdate();
userTransaction.commit();
System.out.println("result: " + result);
System.out.println("--- end changePopulation");
} catch (Exception e) {
System.out.println("Transaction State: " + getTransactionStateString(userTransaction.getStatus()));
}
}

Modify the PopulationServlet's processRequest method. Replace the body of the try block with the following:

clearTables();
populationManager.addCity("Tokyo", "Japan", 32450000);
try {
bean.changePopulation("Tokyo", 1000);
} catch (SystemException ex) {
System.out.println("SystemException");
Logger.getLogger(PopulationServlet.class.getName()) .log(Level.SEVERE, null, ex);
}
List<City> cities = cityFacade.findAll();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet PopulationServlet</title>");
out.println("</head>");
out.println("<body>");
for (City c : cities) {
out.println("<h5>Rio: " + c.getName() + " - " + c.getPopulation() + "</h5>");
}
out.println("</body>");
out.println("</html>");

Execute the PopulationServlet. It will pause and after 20 seconds the output of the servlet will show that the population has not been updated. In the console you will see the following output:

...

INFO: Executing changePopulation

INFO: Transaction State: STATUS_ACTIVE: The transaction is active

INFO: Transaction State: STATUS_NO_TRANSACTION: There is no transaction

...

How it works...

The setTransactionTimeout argument is expressed in seconds. The value of 10 meant it should not wait for more than 10 seconds before rolling back the transaction.

To test the method, we used the sleep method to suspend the current thread for 20 seconds. This argument is expressed in milliseconds so we used a value of 20000 to direct the method to sleep for 20 seconds.

In the console output, the transaction's status was displayed as explained in the Handling transactions manually recipe. It reflected an initial active transaction but when the exception was thrown, the status indicated that a transaction was no longer present.

See also

The Handling transactions manually recipe illustrates how to use BMTs and the Rolling back a transaction recipe explains the process of rolling back a transaction.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.216.254