Handling errors in a transaction

When an error occurs during the execution of a transaction, the transaction may or may not need to be rolled back. It all depends on the nature of the error. Exceptions are classified as either checked exceptions, a java.lang.Exception derived class, or unchecked exceptions, a java.lang.RuntimeException derived class.

If an unchecked exception is thrown, a transaction is automatically rolled back. For checked exceptions, the UserTransaction's rollback method or the SessionContext's setRollbackOnly method are used to explicitly force a rollback.

Checked exceptions are considered to be application exceptions while unchecked exceptions are system exceptions. However, an application can declare its own unique exceptions which can be checked or unchecked.

To assist in the creation and use of application-specific exceptions, the @ApplicationException annotation is available. This annotation is used to mark an application-specific exception and specify whether a rollback should occur when this exception occurs. Here we focus on the use of this annotation.

Getting ready

The steps used to create such an application-specific exception involve:

  1. Creating the exception class
  2. Applying the @ApplicationException annotation
  3. Creating and throwing the exception where appropriate

    The EJB @ApplicationException annotation is used to declare a class as an application exception. The annotation has two optional elements: inherited and rollback. The inherited element is used to indicate whether any derived classes should have the annotation applied to them. The rollback element indicates whether the exception should force a rollback of a transaction or not. Both of these elements are Boolean. The inherited element defaults to true and the rollback element defaults to false.

How to do it...

To illustrate the use of this annotation, add a class called IllegalPopulationException, which extends the Exception class to the packt package. Add a default constructor and a single argument constructor that uses a simple error message. The rollback element should be set to true.

@ApplicationException(rollback=true)
public class IllegalPopulationException extends Exception {
public IllegalPopulationException() {
}
public IllegalPopulationException(String message) {
super("IllegalPopulationException");
}
}

To test its use, modify the CityFacade's changePopulation method to throw an IllegalPopulationException exception if the count parameter is a negative value. While a negative value is not necessarily an incorrect value, we will use this test to illustrate the exception handling process.

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void changePopulation(String cityName, long count) throws IllegalPopulationException {
System.out.println("Executing changePopulation");
if(count<0) {
throw new IllegalPopulationException();
}
...
}

Next, modify the PopulationManager's updatePopulation method by catching the IllegalPopulationException when the changePopulation method is invoked. In the catch block, use the println method to display a message that the exception has been caught.

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void updatePopulation(String cityName, long count) {
try {
cityFacade.changePopulation(cityName, count);
} catch(IllegalPopulationException e) {
System.out.println("IllegalPopulationException caught");
}
}

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

clearTables();
populationManager.addCity("Tokyo", "Japan", 32450000);
populationManager.updatePopulation("Tokyo", -1000);
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>");

This code sequence adds a city and then attempts to update its population with a negative number.

Execute the PopulationServlet. The browser output will show that the population has not been updated as shown in the following screenshot:

How to do it...

The console output will show the IllegalPopulationException exception being caught.

INFO: PopulationManager afterBegin

INFO: CityFacade afterBegin

INFO: Executing changePopulation

INFO: IllegalPopulationException caught

INFO: PopulationManager afterCompletion

INFO: CityFacade afterCompletion

How it works...

The ApplicationException annotation marked the IllegalPopulationException as one which will result in a rollback if thrown. The exception was created and thrown in the changePopulation method and propagated to the updatePopulation method where it was caught. Notice that the output from the changePopulation method did not reflect the execution of the last two println methods:

INFO: result: 1

INFO: --- end changePopulation

These statements were bypassed and the population was not changed.

See also

The Rolling back a transaction recipe explains the roll back process in more detail.

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

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