Overview
In general, enterprise-level applications are corresponding to complex business logic, in order to ensure the robustness of the system, it is necessary to face a variety of system business anomalies and run-time anomalies.
Bad exception handling can easily cause application logic to be confusing, fragile and difficult to manage. The application is flooded with fragmented exception-handling code that makes the program code obscure, poorly readable, and difficult to maintain.
A good exception handling framework provides a unified view of the application's exception handling, separating exception handling from the normal running logic of the program to provide a more structured and readable program architecture. In addition, a good exception handling framework is extensible, and it is easy to extend specific exception handling logic based on specific exception handling requirements.
In addition, the exception handling framework relies on and embodies the hierarchy of system architecture to some extent. The system architecture determines the interaction between each subsystem in the system, and the exception processing framework unifies the errors and anomalies of the various interactions in this architecture. Therefore, the exception handling framework is an issue that should be considered when the system is architected.
This article will discuss some aspects of anomaly correlation, and then explore some perspective or design principles for building robust and extensible exception handling frameworks. Because this article introduces some of the concepts associated with exceptions in the Java language, this article assumes that you are familiar with Java-related basics and understand Java EE and EJB-related technologies.
Basic concepts of Java exceptions
In the Java programming language, you use an error-trapping mechanism for exception handling. When the program is running, some exceptions occur, the program may be interrupted, or the result of the error will occur. In this case, the program does not return any values, but instead throws an object that encapsulates the error message. The Java language provides a specialized exception handling mechanism to handle these exceptions. 1 is shown in the Java exception architecture:
Figure 1. Java Exception Architecture
Check for (Checked) Exceptions and non-check (unchecked) exceptions
All exceptions to the Java language specification that are sent to the Error class or the RuntimeException class are called non-check exceptions. All exceptions except "Non-check exceptions" are called check exceptions. Checking for exceptions is an exception that must be handled by the method caller, and when an application defines a large number of methods or calls that are prone to many check exceptions, there are a lot of exception handling code in the program.
If an exception is fatal and unrecoverable and does not know what to do with the method that captures the exception, or if there is no benefit in capturing such an exception, the author believes that such exceptions should be defined as non-check exceptions, handled by the top-level exception handlers, such as database connection errors, Exceptions such as network connection errors or file openings are generally non-check exceptions. Such anomalies are generally related to the external environment, and once they occur, they are largely unable to be effectively processed.
For some exceptions that have the ability to avoid exceptions or anticipate recoverable and have corresponding processing methods, you can define the class exception as a check exception. Exceptions, such as those typically caused by entering illegal data or some business-related exceptions, are essentially check exceptions. When such an exception occurs, it is generally possible to return to the normal state by a valid processing or by retrying.
Because checking for exceptions is an exception that must be handled, there is a lot of exception handling code in the program that has a large number of check exceptions. Also, checking for exceptions causes the interface method to be broken. If a method on an interface has been used in multiple places, when a check exception is added for this method, all code that calls this method needs to be modified to handle the exception. Of course, the presence of an appropriate number of check anomalies is undoubtedly more elegant and helps to avoid many potential errors.
When to use check exceptions and when to use non-check exceptions, there is no absolute standard, depending on the situation. In many cases, in our program, we need to wrap the check exception into a non-check exception to the top-level program, and in some cases, the non-check exception needs to be packaged as a check exception to be thrown uniformly.
Multiple perspectives to understand anomalies
From the system developer's point of view, it is more from the internal logic of the system to see the exception. Some exceptions require an internal interception process, while the other exception is not valid for the source of the exception, thus requiring an exception to be thrown out to the appropriate caller for processing. For developers, it is necessary to anticipate exceptions, and to consider when to handle exceptions, when to throw exceptions, and, if necessary, to record or notify exceptions in some way. All in all, developers need to address or avoid exceptions by handling exceptions that might occur when the system is running to ensure proper operation of the system, and to record, notify, and render an unhandled exception in an appropriate way to find the cause of the exception.
Figure 2. Exception view
Exception Management and exception framework
Basic exception handling Structure
3, the code structure is handled for a common generic exception. Where the Try statement block represents the code to be run and is monitored by the exception, where the code is an exception, an exception object is created and thrown.
A catch statement block captures the exception that occurs in a try code block and matches its own exception type and, if matched, makes exception handling in its catch code block. A catch statement block can have multiple, and when an exception is thrown in a try statement block, a match is made for each catch block, and once a catch block is matched, the catch block is processed and no longer matches the other catch block.
A finally statement block is a block of statements immediately following a catch statement, which is always executed before the method returns, regardless of whether the try statement block has an exception.
Figure 3. Exception handling code structure
As I said earlier, in general, exception handling may require some general processing, such as exception logging, exception notification, and redirection to a unified error page (such as a Web app) when an exception occurs. If these generic exception handling is placed in the catch block, it will result in a large number of duplicate code, which may cause log redundancy, the implementation of the same exception diversification, and so on. In addition, a large number of exception handlers placed in the catch block result in high coupling of the program. In order to solve such problems, it is necessary to isolate the exception handlers, unify the exception processing style, reduce the coupling, and enhance the reuse degree of the exception handling module. Typical exception handling modes include the business Delegate mode (Delegate), the Front Controller mode (Front controllers), the Interceptor Filter mode (intercepting filter), the AOP mode, the template method mode, and so on.
Generic Exception Handling Framework
In order to solve the problems caused by the basic exception handling structure, it is advisable to delegate the exception handling to a dedicated service agent, thus separating out the exception processing business, and processing it in a unified manner and logic, as shown in 4. Exception Service mainly handles two aspects: on the one hand, it is necessary to call the general handler to handle the exception according to the actual system requirements, such as log record, abnormal interface display, exception notification, etc. on the other hand, we need to find a custom exception handler for exception handling by filtering the type of exception received. Applications for exception service can typically be automatically intercepted at the top level of the system (typically in multi-layered systems, such as in the front-end controller Front controllers), or actively invoking the exception service for processing.
Figure 4. Generic Exception Handling Framework
The class diagram shown in 5 shows a specific exception handling framework:
Figure 5. Exception handling Framework Class drawing example
The framework mainly consists of three parts: Exception Service, exception handling filter, System exception hierarchy definition.
Exception Service: The core of the entire exception framework, typically used to proactively intercept exceptions or to handle exceptions by passive calls. According to the specific business needs, call the General Service program to perform generalized exception handling, such as Log service, exception message notification service, etc. in addition, the primary purpose of exception service is to intercept and handle exceptions, which need to maintain a custom exception handler chain for specific processing of specific types of exceptions.
Exception Handling Filters: Maintain various exception handlers in the system, including adding exception handlers, removing exception handlers, finding exception handler operations, and more. One of the most important functions is to receive a specific exception and find a matching exception handler to handle. Exception handling filter implementations can maintain mappings of all exceptions and exception handlers through a single configuration file, while maintaining all defined exception handlers in the system through a separate configuration file. Thus, the exception-handling filter can be initialized through the configuration file.
Exception hierarchy Definition: The exception hierarchy defines the exception infrastructure of the application system, which is the set of target exception types that the exception handling filter handles.
Exception Hierarchy Definition
The exception hierarchy should be defined in a universally common principle. Therefore, we can use the object-oriented language to have polymorphic properties and hide the actual implementation of the exception. For exception Service, only the most basic application exception appexception needs to be captured, and the exception handling filter will automatically filter the actual exception type and find the appropriate exception handler. In addition, in the throws statement of the method do not need to put a large number of check exceptions, the method caller will not appear chaotic catch block, up to one can only be used to handle the basic application exception Appexception (delegate to the exception Service processing).
As mentioned in the previous section, application exceptions can be considered from two perspectives of users and developers. Therefore, we can divide the exception into two types: Business operation exception and system internal runtime exception. The decision to throw a business-level exception or system run-time exception needs to be combined with the architecture hierarchy of the application itself, considering the level of exception to be handled. 6 is shown as a typical exception hierarchy:
Figure 6. Examples of exception hierarchy class drawings
Where Bussinessexception is a basic business operation exception, all business operation exceptions are inherited from the class. For example, typically the UI layer or WEB layer is driven by the system end user performing business operations, so it is best to throw a business class exception. Serviceexception generally belong to the intermediate service layer anomaly, the exception caused by this layer operation is generally packaged into basic serviceexception. Daoexception is a basic exception related to data access.
For multilayer systems, each layer has a basic exception to that layer. At the time of the transfer of information between layers and the method call, once an exception occurs at a certain layer, it is generally packaged into the layer exception until the UI layer is closest to the user, thus translating into user-friendly error messages.
Exception translation and exception chaining
The previous discussion of checking exceptions and non-checking exceptions, in the presence of a large number of exceptions, means that a lot of exception handling code leads to obscure exception handling, and that checking for exceptions can easily break the interface method. In order to solve the defects caused by the inspection anomaly, we can use the method of abnormal translation to turn the inspection anomaly into a non-check exception, which is handled by the exception Service interception.
Exception translation is the conversion of an exception to another exception. Exception translation is for all exception classes that inherit the Throwable superclass. An example of exception translation is shown in the code in 7:
Figure 7. Sample Exception Translation Code
For any application system, any exception or error that occurs during the operation of the system should be notified to the user or record in the appropriate manner; Because the source of the exception may come from many aspects, the exception that it throws is mostly not understood by the system user, and the various types of exceptions must be translated into various user-understandable exceptions. This is also the aspect that the abnormal framework needs to focus on and solve.
In the process of abnormal layer translation, an anomaly chain is formed. The entire chain of exceptions preserves the cause of each layer's exception. A recursive call to the Getcause () method iterates through all the causes of the exception. It is important to note that in the process of forming an abnormal chain, more resources are consumed, resulting in reduced system performance. Here is the principle of exception, there is no need to say that there is interest to consult the relevant information. In the anomaly framework presented in this paper, abnormal service can intercept the anomalies from each layer of the system without the need of abnormal layer translation.
Conclusion
This paper first briefly introduces the basic concept of the anomaly and the basic exception architecture of Java language, focusing on the two concepts of check (checked) exception and non-check (unchecked) exception in Java exception. Then, it emphatically introduces the anomaly of how to look at the application system from two angles of users and developers in an application system, and it can provide good design principle for designing a reasonable system anomaly frame through multi-angle view to apply system anomaly. Finally, a general extensible exception handling framework is introduced, which includes design principles, definition of exception hierarchies and exception translation considerations.
Especially for larger software systems, the exception handling framework is an important aspect to be considered in software system architecture. A good exception handling structure can not only deal with the exception, but also ensure the scalability and availability of exception handling, and finally need to ensure that the performance of the system is not subjected to additional losses.
Analysis of exception and exception handling framework