Exception Handling in the Java EE Project

Source: Internet
Author: User

Why do we need to talk about exception handling in the J2EE project? Many java beginners may want to say: "exception handling is not a try .... Catch... Finally? Everyone will do that !". This is what I think when I was a beginner in java. In a multi-tier j2ee project, how does one define the corresponding exception classes? How to handle exceptions at each layer of the project? When will an exception be thrown? When is an exception recorded? How to record exceptions? When do I need to convert a checked Exception to an unchecked Exception and a unChecked Exception to a checked Exception? Should exceptions be displayed on the front-end page? How to design an exception framework? This article will discuss these issues.
1. JAVA Exception Handling
In a process-oriented programming language, we can use the return value to determine whether the method is executed normally. For example, in a C language program, if the method is correctly executed, 1 is returned. if the error is returned, 0 is returned. When an error occurs in an application developed by vb or delphi, a message box is displayed to the user.
The returned values of methods do not provide detailed error information. The methods may be compiled by different programmers. When the same class of errors occur in different methods, the returned results are inconsistent with the error message.
Therefore, java adopts a unified exception handling mechanism.
What is an exception? Errors that can be captured and handled during running.
In java, Exception is the parent class of all exceptions. Any exceptions are extended to the Exception class. Exception is equivalent to an error type. If you want to define a new error type, extend a new Exception subclass. The advantage of exceptions is that the source code location that causes program errors can be precisely located and detailed error information can be obtained.
Java exception handling is implemented using five keywords: try, catch, throw, throws, and finally. The specific exception handling structure is determined by try .... Catch .... Finally block. Try block stores java statements that may encounter exceptions. catch is used to capture and handle exceptions. The Finally block is used to clear unreleased Resources in the program. The finally block is always executed without managing how the try block code returns.
A typical Exception Handling Code
Java code
Public String getPassword (String userId) throws DataAccessException {
String SQL = "select password from userinfo where userid = '" + userId + "'";
String password = null;
Connection con = null;
Statement s = null;
ResultSet rs = null;
Try {
Con = getConnection (); // get data connection
S = con. createStatement ();
Rs = s.exe cuteQuery (SQL );
While (rs. next ()){
Password = rs. getString (1 );
}
Rs. close ();
S. close ();
}
Catch (SqlException ex ){
Throw new DataAccessException (ex );
}
Finally {
Try {
If (con! = Null ){
Con. close ();
}
}
Catch (SQLException sqlEx ){
Throw new DataAccessException ("An error occurred while closing the connection !", SqlEx );
}
}
Return password;
}
We can see the advantages of Java's Exception Handling Mechanism:
Errors are classified in a unified manner by extending the Exception class or its subclass. This avoids the possibility that the same error may have different error messages in different methods. When the same error occurs in different methods, you only need to throw the same exception object.
Obtain more detailed error information. Exception classes can be used to provide more detailed error information for users. This allows you to track and Debug programs.
Separate the correct returned results from the error message. Reduces the complexity of the program. The caller does not need to know more about the returned results.
Force callers to handle exceptions to improve program quality. When a method declaration needs to throw an exception, the caller must use try .... The catch Block handles exceptions. Of course, the caller can also make the exception continue to be thrown up one layer.
2. Is the Checked or unChecked exception?
Java exceptions fall into two categories: checked exceptions and unChecked exceptions. All exceptions that inherit java. lang. Exception are checked exceptions. All exceptions that inherit java. lang. RuntimeException are unChecked exceptions.
When a method calls a method that may throw a checked exception, try... The catch Block can capture exceptions or throw them again.
Let's take a look at the Declaration of the createStatement () method of the Connection interface.
Public Statement createStatement () throws SQLException;
SQLException is a checked exception. When the createStatement method is called, java forces the caller to capture SQLException.
Java code
Public String getPassword (String userId ){
Try {
......
Statement s = con. createStatement ();
......
Catch (SQLException sqlEx ){
......
}
......
}
Or
Java code
Public String getPassword (String userId) throws SQLException {
Statement s = con. createStatement ();
}
(Of course, resources such as Connection and Satement need to be closed in time. This is only to show that the checked exception must be forcibly captured by the caller or thrown continuously)
An unChecked exception is also called a running exception. Generally, RuntimeException indicates an exception that cannot be recovered, for example, a database connection or a file cannot be opened. You can also capture unChecked exceptions like handling checked exceptions. However, if the caller does not capture the unChecked exception, the compiler will not force you to do so.
For example, the Code for converting a character into an integer value is as follows:
Java code
String str = "123 ";
Int value = Integer. parseInt (str );
The parseInt method signature is:
Java code
Public staticint parseInt (String s) throws NumberFormatException
NumberFormatException is thrown when the input parameter cannot be converted to the corresponding integer. Because NumberFormatException is extended to RuntimeException, it is an unChecked exception. Therefore, when calling the parseInt method, there is no need to try... Catch
Because java does not force callers to capture unChecked exceptions or throw them up. So programmers always like to throw unChecked exceptions. Or when a new exception class is required, it is always used to extend from RuntimeException. When you call some of its methods, if there is no corresponding catch block, the compiler will always let you pass. At the same time, you do not need to understand what exceptions will be thrown by this method. This seems to be a good method, but it is far away from the real intention of java Exception Processing. It is misleading to the programmers who call your class, because the caller does not know under what circumstances to handle exceptions. The checked exception can clearly tell the caller what exceptions need to be handled when calling this class. If the caller does not process the code, the compiler will prompt that the Code cannot be compiled. Of course, the caller determines how to handle it.
Therefore, Java recommends that people use the checked exception in application code. As we mentioned in the previous section, the advantage of exceptions lies in the ability to force callers to handle the exceptions that will occur. The checked exception is used as a standard in java official documents such as java Tutorial.
An exception occurs when using checked. It should mean that there are many try... Catch is in your code. When writing and processing more and more try... After the catch Block, many people finally began to doubt whether the checked exception should be used as a standard.
Even Bruce Eckel, author of thinking in java, has changed his mind. Bruce Eckel even advocates the unChecked exception as a standard usage. And published an article to test whether the checked exception should be removed from java. Bruce Eckel: "when there is a small amount of code, the checked exception is undoubtedly a very elegant concept and helps avoid many potential errors. However, experience shows that the results are the opposite for a large number of codes"
For more information about checked and unChecked exceptions, see
Alan griiths http://www.octopull.demon.co.uk/java/ExceptionalJava.html
Bruce Eckel http://www.mindView.net/Etc/Disscussions/CheckedExceptions
Java Tutorial Co., http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html
Checked exceptions may cause many problems.
The checked exception causes too many try... Catch code
There may be many checked exceptions that cannot be properly handled by developers, such as SQLException. But developers have to try... Catch. When developers cannot correctly handle a checked exception, they usually simply print out the exception or simply do nothing. Especially for beginners, too many checked exceptions make them feel at a loss.
Java code
Try {
......
Statement s = con. createStatement ();
......
Catch (SQLException sqlEx ){
SqlEx. PrintStackTrace ();
}
Or
Try {
......
Statement s = con. createStatement ();
......
Catch (SQLException sqlEx ){
// Do nothing
}
The checked exception causes many obscure code generation.
When developers must capture a checked exception that they cannot correctly handle, they usually reencapsulate it into a new exception and then throw it. This does not bring any benefits to the program. It makes the code difficult to understand.
As we use JDBC code, we need to process a lot of try... Catch., really useful code is included in try... Within catch. Makes it difficult to understand this method.
The checked exception causes the exception to be encapsulated into another class and then thrown.
Java code
Public void methodA () throws javastiona {
.....
Throw new partition tiona ();
}
Public void methodB () throws ExceptionB {
Try {
MethodA ();
......
} Catch (effectiona ex ){
Throw new ExceptionB (ex );
}
}
Public void methodC () throws writable tinc {
Try {
MethodB ();
...
}
Catch (ExceptionB ex ){
Throw new ExceptionC (ex );
}
}
We can see that exceptions are encapsulated and re-thrown endlessly.
Interface Method damaged due to checked exception
A Method on an interface has been used by multiple classes. When an additional checked exception is added for this method, all code that calls this method must be modified.
It can be seen that the above problems are caused by the caller being unable to correctly handle the checked exception and being forced to capture and handle it. The caller is forced to encapsulate the exception and then throw it again. This is inconvenient and does not bring any benefits. In this case, the unChecked exception is usually used.
The chekced exception does not have to be the same. The checked exception is much easier to use than the error return value of traditional programming. It is much better to use the compiler to ensure correct Exception Handling than to judge through the return value.
If an exception is fatal, it cannot be recovered. Or there is no benefit for the caller to capture it. The unChecked exception is used.
If an exception can be recovered, it can be correctly handled by the caller and the checked exception is used.
When an unChecked exception is used, the unChekced exception that the method may throw must be described in detail in the method declaration. The caller determines whether to capture the unChecked exception.
When is the checked exception used? When is the unChecked exception used? There is no absolute standard. However, I can give some suggestions.
When all callers must handle this exception, the caller can retry the operation, or the exception is equivalent to the second return value of this method. An error occurred while using checked.
This exception can only be handled by a few advanced callers. Generally, callers cannot handle the exception correctly. An error occurred while using unchecked. Callers with processing capabilities can perform advanced processing. Generally, callers simply do not.
This exception is a very serious error, such as a database connection error or a file cannot be opened. Or these exceptions are related to the external environment. It cannot be solved by retry. An error occurred while using unchecked. The caller cannot handle this exception.
If you are not sure, the unchecked exception is used. Describe the exceptions that may be thrown in detail so that the caller can decide whether to handle them.
3. Design a new exception class
When designing a new exception class, first check whether the exception class is actually needed. Generally, try not to design new exception classes, but try to use existing exception classes in java.
For example
Java code
IllegalArgumentException, UnsupportedOperationException
Whether the new exception is a chekced or unChecked exception. We must all consider the issue of exception nesting.
Java code
Public void methodA () throws javastiona {
.....
Throw new partition tiona ();
}
The method methodA declaration will throw tiona.
Public void methodB () throws ExceptionB
The methodB declaration throws ExceptionB. When methodA is called in the methodB method, tiona cannot be processed. Therefore, tiona should continue to throw. One way is to throw the methodB declaration into mongotiona. But this has changed the method signature of MethodB. Once changed, all methods that call methodB must be changed.
Another way is to encapsulate regiontiona into ExceptionB and then throw it. If we do not encapsulate ExceptionA in ExceptionB, the root exception information is lost, making it impossible to track the original source of the exception.
Java code
Public void methodB () throws ExceptionB {
Try {
MethodA ();
......
} Catch (effectiona ex ){
Throw new ExceptionB (ex );
}
}
In the code above, predictionb nested a predictiona. For the moment, we call predictiona "cause exception" because predictiona causes predictionb. In this way, the exception information is not lost.
Therefore, when defining a new exception class, we must provide such a constructor that can contain nested exceptions. There is a private member to save this "cause exception ".
Java code
Public Class ExceptionB extends Exception {
Private Throwable cause;
Public ExceptionB (String msg, Throwable ex ){
Super (msg );
This. cause = ex;
}
Public ExceptionB (String msg ){
Super (msg );
}
Public ExceptionB (Throwable ex ){
This. cause = ex;
}
}
Of course, when we call the printStackTrace method, we need to print all the "cause exception" information at the same time. Therefore, we need to override the printStackTrace method to display all Exception stack traces. Stack tracing with nested exceptions is included.
Java code
Public void printStackTrace (PrintStrean ps ){
If (cause = null ){
Super. printStackTrace (ps );
} Else {
Ps. println (this );
Cause. printStackTrace (ps );
}
}
The source code of a complete checked exception class supporting Nesting is as follows. We will call it NestedException for the moment.
Java code
Public NestedException extends Exception {
Private Throwable cause;
Public NestedException (String msg ){
Super (msg );
}
Public NestedException (String msg, Throwable ex ){
Super (msg );
This. cause = ex;
}
Public Throwable getCause (){
Return (this. cause = null? This: this. cause );
}
Public getMessage (){
String message = super. getMessage ();
Throwable cause = getCause ();
If (cause! = Null ){
Message = message + "; nested Exception is" + cause;
}
Return message;
}
Public void printStackTrace (PrintStream ps ){
If (getCause = null ){
Super. printStackTrace (ps );
} Else {
Ps. println (this );
GetCause (). printStackTrace (ps );
}
}
Public void printStackTrace (PrintWrite pw ){
If (getCause () = null ){
Super. printStackTrace (pw );
}
Else {
Pw. println (this );
GetCause (). printStackTrace (pw );
}
}
Public void printStackTrace (){
PrintStackTrace (System. error );
}
}
Similarly, an unChecked exception class should be designed as well. Only RuntimeException must be inherited.
4. How to record exceptions
As a large application system, you must use log files to record the operation of the system, so as to track and record the operation of the system. System exceptions must be recorded in the log system.
Java code
Public String getPassword (String userId) throws NoSuchUserException {
UserInfo user = userDao. queryUserById (userId );
If (user = null ){
Logger.info ("this user information cannot be found, userId =" + userId );
Throw new NoSuchUserException ("this user information cannot be found, userId =" + userId );
}
Else {
Return user. getPassword ();
}
}
Public void sendUserPassword (String userId) throws Exception {
UserInfo user = null;
Try {
User = getPassword (userId );
//........
SendMail ();
//
} Catch (NoSuchUserException ex )(
Logger. error ("This user information cannot be found:" + userId + ex );
Throw new Exception (ex );
}
We noticed that an error was recorded twice. We recorded the error at the info level only. In the sendUserPassword method, the entire exception information is recorded.
I have seen that many projects record exceptions in this way. No matter how many projects are, the entire exception is recorded only when an exception occurs. If an exception is repeatedly encapsulated and thrown multiple times, it is recorded multiple times. So where should an exception be recorded?
The exception should be recorded at the initial location!
If an exception cannot be correctly handled must be caught, it is simply encapsulated into another exception and thrown up. You do not have to record recorded exceptions again.
If an exception is caught, the exception can be handled. No exception needs to be recorded
Java code
Public Date getDate (String str ){
Date applyDate = null;
SimpleDateFormat format = new SimpleDateFormat ("MM/dd/yyyy ");
Try {
ApplyDate = format. parse (applyDateStr );
}
Catch (ParseException ex ){
// Returns null if the format is incorrect.
}
Return applyDate;
}
When an unrecorded exception or external system exception is caught, the exception details should be recorded.
Java code
Try {
......
String SQL = "select * from userinfo ";
Statement s = con. createStatement ();
......
Catch (SQLException sqlEx ){
Logger. error ("SQL Execution error" + SQL + sqlEx );
}
Where to record the exception information and how to record the exception information may be wise. Some systems even cause exceptions such as record exceptions. When a new exception object is generated, the exception information is automatically recorded.
Java code
Public class BusinessException extends Exception {
Private void logTrace (){
StringBuffer buffer = new StringBuffer ();
Buffer. append ("Business Error in Class :");
Buffer. append (getClassName ());
Buffer. append (", method :");
Buffer. append (getMethodName ());
Buffer. append (", messsage :");
Buffer. append (this. getMessage ());
Logger. error (buffer. toString ());
}
Public BusinessException (String s ){
Super (s );
Race ();
}
This seems to be wonderful, but it will inevitably lead to repeated records of exceptions. At the same time, violation of the "class responsibility allocation principle" is a bad design. Record exceptions that do not belong to exceptions. Record exceptions should be performed by a dedicated log system. And abnormal records are constantly changing. We should provide more information when recording exceptions. This helps us locate the root cause of the problem based on the exception information to solve the problem.
Although we have discussed record exceptions a lot, too much emphasis on this makes developers more confused. A good way is to provide an exception handling framework for the system. The framework determines whether to record exceptions and how to record exceptions. It is not determined by ordinary programmers. But it is helpful to know something.
5. Exception Handling in the J2EE Project
Currently, J2ee projects are logically divided into multiple layers. The classic architecture is divided into three layers: presentation layer, business layer, and integration layer (including database access and external system access ).
The J2ee project has its complexity. Several issues need to be paid special attention to in exception handling of the J2ee project.
In distributed applications, we encounter many checked exceptions. All RMI calls (including remote EJB interface calls) Throw java. rmi. remoteException; at the same time, RemoteException is a checked exception. When we perform remote calls in the business system, we need to write a lot of code to handle these checked exceptions. In the event of RemoteException, these checked exceptions are very serious to the system, and there is almost no possibility of retry. That is to say, when the RemoteException and these terrible checked exceptions occur, we have no need to retry, but we have to write a lot of try... Catch code to process it. Generally, we call RMI at the bottom layer. If there is an RMI call, all upper-layer interfaces require a RemoteException. Because the RemoteException processing method is to continue to throw it. In this way, our business interfaces are damaged. RemoteException these J2EE system-level exceptions seriously affect our business interfaces. The purpose of layering the system is to reduce the dependencies between systems, and the technical changes at each layer will not affect other layers.
Java code
//
Public class UserSoaImplimplements UserSoa {
Public UserInfo getUserInfo (String userId) throws RemoteException {
//......
Remote method call.
//......
}
}
Public interface UserManager {
Public UserInfo getUserInfo (Stirng userId) throws RemoteException;
}
Similarly, SQLException checked exception is thrown during JDBC access.
To avoid in-depth intrusion of system-level checked exceptions to the business system, we can define a business system exception for the business method. For very serious exceptions such as SQLException and RemoteException, we can define a new unChecked exception and then encapsulate SQLException and RemoteException into unChecked exceptions and then throw them.
If a system-level exception is to be handled by a higher-level caller, a new checked business exception can be defined, and system-level exceptions can be stored as business-level exceptions before being thrown.
Generally, we need to define an unChecked exception so that all methods of the integration layer interface can declare that this unChecked exception is thrown.
Java code
Public DataAccessExceptionextends RuntimeException {
......
}
Public interface UserDao {
Public String getPassword (String userId) throws DataAccessException;
}
Public class UserDaoImplimplements UserDAO {
Public String getPassword (String userId) throws DataAccessException {
String SQL = "select password from userInfo where userId = '" + userId + "'";
Try {
...
// JDBC call
S.exe cuteQuery (SQL );
...
} Catch (SQLException ex ){
Throw new DataAccessException ("database query failed" + SQL, ex );
}
}
}
Define a checked service exception so that all methods of the service layer interface declare that the Checked exception is thrown.
Java code
Public class BusinessExceptionextends Exception {
.....
}
Public interface UserManager {
Public Userinfo copyUserInfo (Userinfo user) throws BusinessException {
Userinfo newUser = null;
Try {
NewUser = (Userinfo) user. clone ();
} Catch (CloneNotSupportedException ex ){
Throw new BusinessException ("clone method not supported:" + Userinfo. class. getName (), ex );
}
}
}
The J2ee presentation layer should be a thin layer. Its main function is to obtain page requests, assemble page parameters into POJO objects, call corresponding business methods, and then forward pages, present the corresponding business data to the page. The presentation layer needs to pay attention to one problem. The presentation layer needs to verify the validity of data. For example, some input fields cannot be empty or character length verification.
All J2ee parameters passed from the page to the backend are character-type. If you want to enter a value or a date-type parameter, you must convert the character value to the corresponding value or date value.
If the verification parameters of the Presentation Layer Code are invalid, the system should return to the original page, asking the user to reenter the data and prompt related error information.
We usually convert a parameter from the page to a value. We can see this code.
Java code
ModeAndView handleRequest (HttpServletRequest request, HttpServletResponse response) throws Exception {
String ageStr = request. getParameter ("age ");
Int age = Integer. parse (ageStr );
............
String birthDayStr = request. getParameter ("birthDay ");
SimpleDateFormat format = new SimpleDateFormat ("MM/dd/yyyy ");
Date birthDay = format. parse (birthDayStr );
}
The above code should be seen frequently, but when you enter a character from the page that cannot be converted to an integer or an incorrect date value.
The Integer. parse () method is thrown with a NumberFormatException unChecked exception. However, this exception is definitely not a fatal exception. Generally, when the value entered by the user in the field on the page is invalid, we should prompt the user to reenter it. However, once an unchecked exception is thrown, there is no retry opportunity. Code like this causes a large amount of exception information to be displayed on the page. Make our system look very fragile.
Similarly, the SimpleDateFormat. parse () method also throws the unChecked exception of ParseException.
In this case, we should all capture these unChecked exceptions and prompt the user to reenter them.
Java code
ModeAndView handleRequest (HttpServletRequest request, HttpServletResponse response) throws Exception {
String ageStr = request. getParameter ("age ");
String birthDayStr = request. getParameter ("birthDay ");
Int age = 0;
Date birthDay = null;
Try {
Age = Integer. parse (ageStr );
} Catch (NumberFormatException ex ){
Error. reject ("age", "is not a legal integer ");
}
............
Try {
SimpleDateFormat format = new SimpleDateFormat ("MM/dd/yyyy ");
BirthDay = format. parse (birthDayStr );
} Catch (ParseException ex ){
Error. reject ("birthDay", "is not a legal date. Please enter a date in 'Mm/dd/yyy' format ");
}
}
In the presentation layer, it is necessary to determine whether the method to be called will throw unChecked exceptions. Under what circumstances will these exceptions be thrown and correct processing will be performed.
In the presentation layer, you can call the system's business methods without capturing exceptions. If the exception thrown by the called business method is equivalent to the second return value, capture

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.