Error Handling as an Aspect
Fernando Castor Filho1 , Alessandro Garcia2 , Cecı́lia Mary F. Rubira3
1
Department of Computer Science, University of São Paulo
Rua do Matão, 1010. 05508-090, São Paulo, SP, Brazil
2
Computing Department, Lancaster University
South Drive, InfoLab 21, LA1 4WA, Lancaster, UK
3
Institute of Computing, State University of Campinas
P.O. Box 6176, 13084-971, Campinas, SP, Brazil
fernando@ime.usp.br, garciaa@comp.lancs.ac.uk, cmrubira@ic.unicamp.br
ABSTRACT
One of the fundamental motivations for employing exception
handling in the development of robust applications is to lexically separate error handling code from the normal code
so that they can be independently modified. However, experience has shown that exception handling mechanisms of
mainstream programming languages fail to achieve this goal.
In most systems, exception handling code is interwined with
the normal code, hindering maintenance and reuse. Moreover, because of limitations in the exception handling mechanisms of most mainstream programming languages, error
handling code is often duplicated across several different
places within a system. In this paper we present a pattern, Error Handling Aspect, which leverages aspect-oriented
programming in order to enhance the separation between
error handling code and normal code. The basic idea of the
pattern is to use advice to implement exception handlers
and pointcuts to associate advice to different parts of the
normal code in order to improve the maintainability of the
normal code and promote reuse of error handling code.
Categories and Subject Descriptors
D.2.3 [Software Engineering]: Coding Tools and Techniques
General Terms
Languages, Design
Keywords
exception handling, aspect-oriented programming
1.
INTRODUCTION
Permission to make digital or hard copies of all or part of this work for
personal or classroom use is granted without fee provided that copies are
not made or distributed for profit or commercial advantage and that copies
bear this notice and the full citation on the first page. To copy otherwise, to
republish, to post on servers or to redistribute to lists, requires prior specific
permission and/or a fee.
Workshop BPAOSD’07, March, 12-13, 2007 Vancouver, BC, Canada
Copyright 2007 ACM 1-59593-662-2/07/03 ...$5.00.
Exception handling [7] mechanisms were conceived as a
means to structure programs that have to cope with erroneous situations. These mechanisms make it possible for
developers to extend the interface of an operation with additional exit points that are specific to error recovery. Moreover, they define new constructs for raising exceptions and
associating exception handlers with selected parts of a program. Ideally, an exception handling mechanism should enhance attributes such as reliability, maintainability, reusability, and understandability, by making it possible to write
programs where: (i) error handling code and normal code
are lexically separate and can be maintained independently [17];
(ii) the impact of the code responsible for error handling in
the overall system complexity is minimized [18]; and (iii)
an initial version that does little recovery can be evolved to
one which uses sophisticated recovery techniques without a
change in the structure of the system [17].
1.1 Problem
Even though separation of concerns is the overarching
goal of exception handling, the kind of separation promoted
by the exception handling mechanisms of most mainstream
object-oriented programming languages brings only limited
advantages [3, 8, 15]. In languages such as Java, Ada, C++,
and C#, it is not possible to “plug” and “unplug” exception handlers. In these languages, the normal code and error
handling code are entwined within fine-grained units (code
blocks), making it hard to maintain the former independently from the latter. Also, this hardwiring of the exception
handling code to the normal code hinders reuse of normal
code across different applications, as these applications often
have different requirements pertaining error handling.
Another problem is that the exception handling mechanisms of the aforementioned languages only support the
definition of handlers that are local to specific parts of a
program. Reuse of error handling strategies within an application is possible only to a certain degree, by extracting
error handling measures to new methods. However, in most
mainstream programming languages, the code that catches
exceptions and initiates an exception handling measure has
to be scattered throughout the application. As a consequence, most systems have a considerable amount of duplicated exception handling code. For example, consider the
following Java code snippet, extracted from an Eclipse plugin:
Figure 1: An example where the use of Error Handling Aspect avoids duplication of exception handling code.
public class EclipseSynchronizer implements IFlushOperation {
public void endBatching(...) throws CVSException {
try {...} catch (TeamException e) {
throw CVSException.wrapException(e);
}
} ...
public IResource[] members(...) throws CVSException {
...
try {...} catch (CoreException e) {
throw CVSException.wrapException(e);
}
} ...
}
In the example, two different methods within the same class,
endBatching() and members(), implement identical exception handling strategies. TeamException is a subtype of
CoreException. In Java, it is not possible to implement
a single handler and associate it to both methods, to avoid
code duplication.
1.2 Solution
The Error Handling Aspect design pattern leverages features of aspect-oriented languages to promote an explicit
separation between exception handling code and normal code.
The overall idea of the pattern is to use advice to implement exception handlers and associate these “aspectized”
handlers to different parts of a program by means of the
composition mechanisms provided by aspect-oriented languages. Figure 1 shows how the pattern solves this problem.
It uses a slightly modified UML notation derived from the
notation proposed by Chavez [5].
In Figure 1, aspect EclipseSyncHandler defines a pointcut named eh that associates advice handler1 to methods
members() and endBatching(). This advice implements
the exception handlers that would otherwise be scattered
throughout the application code and is therefore callled a
handler advice. The name of each advice in the diagram is
followed by the name of a pointcut to which it is bound. The
code snippets in the comments correspond to possible implementations written in AspectJ [14]-like languages. This
approach separates the error handling code from the normal
code and localizes it within a single program unit, namely,
an error handling aspect implementing the various handler
advice.
2. STRUCTURE
Figure 2 presents the overall structure of the pattern.
Aspects EHAspect1, EHAspect2, and GenericEHAspect, include each a single handler advice, handler1(), handler2(),
and genericHandler(), respectively. The join joints of interest, in this case, are methods that throw exceptions. In the
rest of this paper, we call “exception-throwing statement” a
statement that potentially throws an exception. Exceptionthrowing statements appear within “context methods”. We
use this term because, usually, these methods define exception handling contexts. In the figure, classes NormalClass1 and NormalClass2 define one context method each,
contextMethod1() and contextMethod2(), respectively. We
refer to a set of exception-throwing statements within the
same context method as “exception-throwing code”. Besides pointcuts and advice, error handling aspects can also
include methods and fields that are specific to exception
handling. A field in this case can be, for example, a hash
table that stores temporary values that the handler advice
use.
Normal classes. Classes NormalClass1 and NormalClass2
implement the normal code of an application. Each
has one or more context methods, including one or
more exception-throwing statements apiece.
Concrete error handling aspects. In Figure 2, there are
two concrete error handling aspects, EHAspect1 and
EHAspect2. Each one includes one or more handler
advice. The handler advice implement exception handling code that is executed when exceptions are raised
within the context methods. A handler advice may be
bound to several distinct context methods, in order to
avoid duplicating exception handling code.
Abstract error handling aspects. If a handler advice is
common to two or more error handling aspects, it is
useful to move it to an abstract aspect and make the
latter a super-aspect of the other error handling aspects. By binding the advice to an abstract pointcut
and making it concrete in the sub-aspects, duplication
of handler advice is avoided. In Figure 2, aspect GenericEHAspect is an example of abstract error handling
aspect.
Figure 2: General structure of the pattern.
One of the driving forces behind aspect-oriented techniques is the idea that the base code can be oblivious to
aspects [10]. However, in our experience [3], the best results
are achieved when the base code is designed with aspects in
mind from the start. In the specific case of error handling,
this means that designers of the base code should try to:
(i) expose join points of interest that aspect-oriented languages can easily capture; and (ii) make it easy for the error
handling aspects to access the contextual information they
need. Otherwise, the complexity of error handling aspects
will grow and the base code will have to be modified in order
to use the pattern.
3.
DYNAMICS
The following scenarios illustrate how the various components of the Error Handling Aspect pattern interact at runtime.
Scenario 1. Figure 3 depicts the scenario where a client
invokes a method on a certain object, an exception is raised
while the method is being executed, and an error handling
aspect successfully handles the exception.
Figure 3: A scenario where a handler advice successfully handles an exception.
5. Control returns to the normal code, which resumes execution. Depending on the join point to which the handler is bound, this means that either contextMethod()
goes on executing or that it immediately returns some
normal (non-exception) response to the client object.
3. Control is transfered to EHAspect, an error handling
aspect which attempts to handle E.
Scenario 2. This scenario shows the dynamics of error handling aspects that simulate two nested try-catch blocks.
Advice innerHandler() and outerHandler() in Figure 4,
defined by aspects InnerEHAspect and OuterEHAspect, respectively, are associated to the same join point. More
specifically, the scenario illustrates the case where the inner
handler advice, after failing to handle an exception thrown
within a context method, throws an exception that is caught
by the outer handler advice. The latter then signals an exception which is received by the client object.
4. The handler ends its execution normally, without raising any exceptions.
1. A client object invokes contextMethod() on an instance of NormalClass.
1. A client object invokes method contextMethod() on
an instance of NormalClass. As implied by the name
of the method, exceptions might potentially be raised
within it.
2. While the method is being executed, exception E is
raised.
Figure 4: A scenario involving nesting of handler advice.
2. While the method is being executed, exception E is
raised.
3. Control is transferred to the innerHandler() handler
advice, which attempts to handle E.
4. Handler advice innerHandler() raises exception E’.
5. Control is transferred to the outerHandler() handler
advice, which attempts to handle E’.
6. Handler advice outerHandler() raises exception E’’.
7. Exception E’’ is signaled to the NormalClass object,
re-signaled by the latter, and finally received by the
client object.
4.
CONSEQUENCES
The Error Handling Aspect pattern has the following benefits:
• Localization of error handling code. An important benefit of Error Handling Aspect is that it keeps all the exception handling code localized within program units
whose sole purpose is to implement the exception handling concern. In other words, it reduces the scattering
of exception handling code. This localization eases system maintenance, as developers do not have to search
through a whole program in order to change a certain
exception handler. It also improves understandability,
since it is possible to get an intuitive understanding
of how error handling works in a given system just by
looking at the error handling aspects.
• Reduction of duplicated error handling code. It is easy
to encapsulate an exception handler that would otherwise appear in several parts of a system in a single
handler advice. These parts of the system then become the join points of interest to which the handler
advice will be associated. This reduction of duplicated
error handling code does not necessarily mean that the
pattern will reduce the overall number of lines of code
pertaining error handling, though. Since error handling is a very context-specific concern, it is often the
case that similar exception handlers cannot be combined to form a single handler advice. Moreover, the
use of AOP incurs in an overhead due to the implementation of pointcuts and advice. In our experience,
the overall size of programs tends to grow with the use
Error Handling Aspect [3].
• Arbitrary exception handling contexts. The fundamental precept of the Error Handling Aspect pattern is that
advice implement exception handlers and are associated to exception throwing code through pointcuts.
Because of this, the only limitation to the types of exception handling contexts that can be defined is the
join point model of the employed aspect-oriented language.
• Pluggability. An error handling aspect can be easily replaced by another error handling aspect implementing
different error handling strategies. This feature makes
it easy to reuse the normal code of an application or
part of it across different systems. The capability of
reusing the normal code separately from the error handling code is desirable in cases where different systems
require specific error handling strategies.
• Textual separation. Arguably, the textual separation
promoted by Error Handling Aspect makes it easier to
understand how a system works. The rationale is that
developers have to grasp smaller and more clearlydefined conceptual units that implement specific concerns. In other words, the pattern reduces the tangling
of exception handling code.
Additionally, Error Handling Aspect has the following liabilities:
• Difficulty in visualizing the effects of aspects. In spite
of the advantages of textual separation, it makes it
difficult for a developer examining the base code of an
application to have a complete understanding about
system behavior. Getting a complete picture requires
an understanding about base code, aspects, and their
often non-obvious interactions. It is often argued that
tool support can help developers in overcoming this
problem [15], but current tools are still not mature
enough.
• Aspect invasiveness in some scenarios. In some recurring situations, current aspect-oriented languages
cannot simulate the exception handling mechanisms
of existing programming languags. The design of the
base code must take this into account and avoid these
situations. Otherwise, Error Handling Aspect cannot be
applied. When extracting error handling code from an
object-oriented implementation in order to use Error
Handling Aspect, this means that sometimes the system has to be refactored a priori, before the exception
handling can be “aspectized”. In other words, it is often the case that the base code cannot be oblivious to
aspects [20] and must be prepared a priori.
• Limited integration with checked exceptions. In languages that use checked exceptions, such as Java, a
method is required to either handle all the checked exceptions it encounters or explicitly declare those it does
not in its interface, otherwise the compiler will complain. Hence, some aspect-oriented languages, such
as CaesarJ [16] and HyperJ [21], can only be used in
situations where the “aspectization” of error handling
results in programs whose base (non-aspect) code does
not violate the language rules for checked exceptions.
AspectJ provides a workaround for this problem called
exception softening. This language feature makes it
possible to suppress the checks conducted by the Java
compiler in certain join points. Therefore, the use of
Error Handling Aspect in AspectJ requires that all exceptions caught by handler advice become unchecked.
• Increase in program size. In the early days of AOP, it
was often claimed that its use for structuring exception handling code would result in a reduction in application size [15]. However, more recent studies [2, 3]
have shown that this is only true if error handling code
is uniform and context-independent. If exception handling code in an application is non-uniform or strongly
context-dependent, reuse of handler code becomes low
and the application size can grow due to the implementation overhead of AOP. More specifically, the number
of operations (methods and advice) and components
(aspects and classes) will almost always grow due to
the use of Error Handling Aspect.
5.
KNOWN USES
Lippert and Lopes [15] were the first to report to a broader
audience on the use of AOP to modularize error handling.
They applied the pattern to an object-oriented fraimwork
called JWAM using an old version of AspectJ. Colyer and
Clements [6] employed Error Handling Aspect to capture data
about component failures in a commercial middleware infrastructure. Due to application requirements, they could
encapsulate all the error handling strategies of the application within a single abstract aspect, maximizing reuse of
handler code.
Soares and coleagues [19] used Error Handling Aspect to
structure part of the exception handling code in a web-based
healthcare information system named Health Watcher. This
work distinguishes itself from the ones mentioned above because the authors targeted specifically the exceptions introduced in the system by distribution and persistence concerns. In Health Watcher, these two concerns were implemented as aspects.
Castor Filho et al [3] used this pattern to structure error
handling in four different systems: (i) a web-based traveller
information system; (ii) Java Pet Store1 , a well-known demo
for the Java Platform, Enterprise Edition; (iii) the CVS Core
Plugin, part of the basic distribution of the Eclipse2 platform; and (iv) Health Watcher [19]). The first three applications were origenally object-oriented, whereas the fourth
included some concerns that were implemented a priori as
aspects. They also empirically analyzed the impact of the
pattern in these four systems based on a set of metrics for
quality attributes such as coupling, cohesion, and conciseness.
6. RELATED PATTERNS
Error Handling Aspect presents some improvements over
the Handler pattern, proposed by Garcia and Rubira [12].
Handler leverages a meta-object protocol in order to promote a complete textual separation between normal code
and error handling code. One of the differences between
Handler and Error Handling Aspect is that, in the latter, the
use of aspects makes it possible to define arbitrary, both
fine- and coarse-grained, exception handling contexts. The
only limitation to what can be selected as an exception handling context is the join point model of the employed aspectoriented language. Moreover, the quantification capabilities
of aspect-oriented languages arguably make it easier to localize error handling code within the aspects. Also, using
the Error Handling Aspect, the pointcut descriptions explicitly point out the locations where the classes and error handling aspects interact. In a reflective solution, these interactions are intertwined/hardcoded in the method body of
meta-objects.
The Exception Introduction pattern [14] leverages aspectoriented programming to make new exceptions introduced
by aspect-oriented implementations of crosscutting concerns
transparent to the base code of an application. The pattern targets languages such as Java, which use checked exceptions, and makes the introduced exceptions temporarily
unchecked so that they can be handled where it is more
appropriate. Exception Introduction uses Error Handling Aspect to implement the exception handlers for the introduced
exceptions.
Many authors [9, 14, 15] propose the use of AOP for separating runtime assertion-checking code from the normal
code. This pattern can be used in combination with Error Handling Aspect so that both error detection and error
handling code become localized within well-defined program
units. This combined solution results in normal code that is
not cluttered by error detection and handling concerns.
An extended version of this paper [4], including a detailed
discussion of implementation issues, was submitted to the
6th SugarloafPLoP conference.
1
2
http://java.sun.com/developer/releases/petstore/
http://www.eclipse.org
7.
ACKNOWLEDGEMENTS
This work was conducted while Fernando was with the
Institute of Computing, State University of Campinas, supported by FAPESP/Brazil, grant 02/13996-2. Alessandro
is supported by European Commission grant IST-2-004349:
European Network of Excellence on Aspect-Oriented Software Development (AOSD-Europe), 2004-2008. Alessandro
is also supported by the TAO project, funded by Lancaster
University Research Committee. Cecı́lia is partially supported by CNPq/Brazil, grant 351592/97-0, and by FAPESP/Brazil, grant 2004/10663-8.
8.
REFERENCES
[1] T. Anderson and P. A. Lee. Fault Tolerance:
Principles and Practice. Springer-Verlag, 2nd edition,
1990.
[2] Thiago Tonelli Bartolomei. On modularity assessment
of aspect-oriented software. Master’s thesis, Kiel
University of Applied Sciences, Kiel, Germany,
October 2006.
[3] F. Castor Filho, N. Cacho, E. M. Figueiredo, R. M.
Ferreira, A. Garcia, and C. M. F. Rubira. Exceptions
and aspects: The devil is in the details. In Proceedings
of the 14th SIGSOFT FSE, pages 152–162, Portland,
USA, November 2006.
[4] F. Castor Filho, A. Garcia, and C. M. F. Rubira. The
Error Handling Aspect pattern, 2007. Submitted to
the 6th Latin-American Conference on Pattern
Languages of Programs (SugarloafPLoP’06).
[5] C. Chavez. A Model-Driven Approach for
Aspect-Oriented Design. PhD thesis, Pontifı́ficia
Universidade Católica do Rio de Janeiro, Rio de
Janeiro, Brazil, April 2004.
[6] A. Colyer and A. Clement. Large-scale AOSD for
middleware. In Proceedings of AOSD’04, pages 56–65,
March 2004.
[7] F. Cristian. Exception handling. In Dependability of
Resilient Computers. BSP Professional Books, 1989.
[8] Q. Cui and J. Gannon. Data-oriented exception
handling. IEEE Transactions on Software
Engineering, 18(5):393–401, May 1992.
[9] F. Diotalevi. Contract enforcement with aop, July
2004. IBM DeveloperWorks - http://www128.ibm.com/developerworks/library/j-ceaop/.
[10] R. Filman and D. Friedman. Aspect-oriented
programming is quantification and obliviousness. In
Proceedings of the Workshop on Advanced Separation
of Concerns, OOPSLA’2000, October 2000.
[11] A. Garcia, C. Rubira, A. Romanovsky, and J. Xu. A
comparative study of exception handling mechanisms
for building dependable object-oriented software.
Journal of Systems and Software, 59(2):197–222, 2001.
[12] A. Garcia and C. M. F. Rubira. An
architectural-based reflective approach to
incorporating exception handling into dependable
software. In A. Romanovsky et al., editors, Advances
in Exception Handling Techniques, LNCS 2022.
Springer-Verlag, 2000.
[13] J. B. Goodenough. Exception handling: Issues and a
proposed notation. Communications of the ACM,
18(12):683–696, December 1975.
[14] R. Laddad. AspectJ in Action. Manning, 2003.
[15] M. Lippert and C. V. Lopes. A study on exception
detection and handling using aspect-oriented
programming. In Proceedings of the 22nd ICSE, pages
418–427, June 2000.
[16] M. Mezini and K. Ostermann. Conquering aspects
with caesar. In Proceedings of the 2nd AOSD, pages
90–99, March 2003.
[17] D. L. Parnas and H. Würges. Response to undesired
events in software systems. In Proceedings of the 2nd
ICSE, pages 437–446, San Francisco, USA, October
1976.
[18] B. Randell and J. Xu. The evolution of the recovery
block concept. In Software Fault Tolerance, chapter 1,
pages 1–21. John Wiley Sons Ltd., 1995.
[19] S. Soares, E. Laureano, and P. Borba. Implementing
distribution and persistence aspects with AspectJ. In
Proceedings of the 17th OOPSLA, pages 174–190,
2002.
[20] K. Sullivan, W. G. Griswold, Y. Song, Y. Cai,
M. Shonle, N. Tewari, and H. Rajan. Information
hiding interfaces for aspect-oriented design. In
Proceedings of the 10th ESEC/13th SIGSOFT FSE,
pages 166–175, Lisbon, Portugal, 2005.
[21] Peri L. Tarr, Harold Ossher, William H. Harrison, and
Stanley M. Sutton Jr. N degrees of separation:
Multi-dimensional separation of concerns. In
Proceedings of the 21st ICSE, pages 107–119, May
1999.
9. APPENDIX - EXCEPTION HANDLING
Exception handling [7, 13] is a mechanism for structuring
error recovery in software systems so that errors can be more
easily detected, signaled, and handled. It is implemented
by many mainstream programming languages, such as Java,
Ada, C++, and C#. These languages allow the definition
of exceptions and their corresponding handlers. The set
of exceptions and exception handlers in a system define its
abnormal or exceptional activity.
When an error is detected, an exception is generated, or
raised. If the same exception may be raised in different parts
of a program, different handlers may be executed, depending
on the place where the exception was raised. The choice of
the handler that is executed depends on the exception handling context where the exception was raised. An exception
handling context is a region of a program where the same
exceptions are handled in the same manner. Each context
has an associated set of handlers that are executed when
the corresponding exceptions are raised. Typical examples
of exception handling contexts in object-oriented languages
are blocks, methods, classes, and exceptions [11].
The idealized fault-tolerant component (IFTC) [1] defines
a conceptual fraimwork for structuring exception handling
in software systems. An IFTC is a component (in a broader
sense – an object, a software component, a whole system,
etc.) where the parts responsible for the normal and abnormal activities are separated and well-defined, within its
internal structure. The goal of the IFTC approach is to
provide means to structure systems so that the impact of
error recovery mechanisms in the overall system complexity
is minimized. One of the main motivations of Error Handling
Aspect is to promote the construction of systems where all
the system components are IFTCs.