A Systematic Approach for Structuring Exception Handling in Robust Component-Based Software

This article addresses the systematic incorporation of exception handling into component-based systems. By "component-based", one can infer "object-oriented" since the use of libraries of classes, such ast STL and JCL, can be seen as the use of components, building blocks, while constructing large-scale software systems. Read this article in its entirety to get a sense of how to put exception handling to good use.

5. Case Study

5.4 Implementation of the Exceptional Behaviour

For most architectural components of the CMS the initial implementation was modified to adhere to the internal structure shown in Figure 4 (Section 4.2). However, the initial implementation of the ComplaintMgr component was reused as an OTS component. Hence, the internal structure of the new ComplaintMgrcomponent resembles Figure 5. In our implementation, ALE, BLE, and CLE handlers were developed as classes where methods correspond to the actual handlers.

Façade classes of components were modified to introduce explicit checks for pre- and post-conditions. In the initial implementation, pre- and post-conditions of operations were checked at the presentation layer, or not at all. In the robust implementation, façade classes raise an exception of type RejectedRequestException, if a service request violates a pre-condition. When a response violates a post-condition, the façade class invokes the appropriate BLE handler. In most cases, the BLE handler signals an exception of a subtype of RecoveredFailureException or UnrecoveredFailureException(Section 4.1).

The use of BLE handlers guarantees that components always produce meaningful responses, when errors occur. For instance, during the execution of the listRoadSections operation, if the implementation classes of the SectionMgrcomponent signal an exception of type SectionDatabaseQueryException, this exception is automatically propagated, since it denotes an anticipated exceptional condition. However, if an exception of type NullPointerException reaches the component boundary, it is treated as signalling an unanticipated exceptional condition. Hence, the handler encapsulates this exception as an instance of RecoveredFailureException and raises it. The component's state is guaranteed to be consistent, since it is not modified by the implementation of listRoadSections. If support for backward error recovery is available and the failed operation modifies the system's state, the BLE handlers may try to restore it to a previous state free of errors.

1 package business.complaintMgr.impl;
2 // imports all the required types
3 public class ComplaintMgrInterceptor implements IComplaintMgt {
4  private IManager manager;
5  public ComplaintMgtInterceptor(IManager manager){
6  	this.manager = manager;
7	 }
8 public String registerComplaint(...) throws ComplaintRegistrationException
9 {
10	 IComplaintMgt iComplaintMgt = (IComplaintMgt)manager.
11	 getRequiredInterfacerbusiness.complaintMgr.spec.prov.IComplaintMgt”);
12	 String complaintId = new String();
13	 try{
14	   complaintId = iComplaintMgt.registerComplaint(...);
15	 } catch (SQLExcePtion 1) {
16	   ComplaintMgtInterceptor_Exceptional handler =
17	     new ComplaintMgtInterceptor_Exceptional();
18	   handler.handle(e);
19	 }
20	 return complaintId;
21	}
22	(...)
23 }

Figure 12. Implementation of the registerComplaint method of class ComplaintMgrInterceptor

The code snippet in Figure 12 illustrates how the provided interface interceptor of the robust implementation of the ComplaintMgrinterceptor works.

The IManager interface defines methods for managing the dependencies of the component. Each component in the system provides its own implementation. In the example, the interceptor uses an object of type IManagerto obtain a reference to the original ComplaintMgr component.

The class ComplaintMgtInterceptor_Exceptionalimplements the exceptional behaviour of the component. This class implements a polymorphic handle method responsible for handling the exceptions that may be raised by the operations of the original component. In this example, handling consists of transforming instances of SQLException in instances of ComplaintRegistrationException.

We have also modified the initial implementation of the connectors ComplaintMgrConn and UserMgrConn. In both cases, very small modifications were made to their interface adaptor classes (Section 5). For each of them, a new class responsible for the exceptional behaviour was implemented, much like the ComplaintMgrInterceptor_Exceptional in the example above. These CLE handlers were responsible for dealing with unanticipated exceptional conditions. If a server component raises an unexpected exception, the connector is responsible for transforming it into some declared exception defined by the exceptional contract of the client component or, if this is not possible, an appropriate subclass of FailureException.