An exception is a problem that arises during the execution of a program. An exception can occur for many different reasons. Some of these exceptions are caused by user error, others by programmer error, and others by physical resources that have failed in some manner.
Exceptions in Java provide a consistent mechanism for identifying and responding to error conditions. Effective exception handling will make your programs more robust and easier to debug. Exceptions are a tremendous debugging aid because they help answer various questions like what went wrong, where did it go wrong and why did it go wrong and so on.
Three rules will help you make the best use of exceptions when debugging your programs. These rules are: be specific, throw early, and catch late.
Types of Exception
Java defines an exception class hierarchy, starting with Throwable, which is extended by Error and Exception, which is then extended by RuntimeException. Figure 8-3 shows the exception hierarchy in Java. These four classes are generic and they don’t provide much information about what went wrong.
Figure 8-3. Java Exception Hierarchy
To understand how exception handling actually works in Java, we need to understand the three categories into which exceptions are categorized in Java. They are:
- Checked exceptions: A checked exception is an exception that is typically a user error or a problem that cannot be foreseen by the programmer. These exceptions cannot simply be ignored at the time of compilation. For example, if a file is to be opened, but the file cannot be found, an exception occurs.
- Unchecked exceptions (Runtime exceptions): A runtime exception is an exception which probably could have been avoided by the programmer. As opposed to checked exceptions, runtime exceptions are ignored at the time of compilation.
- Errors: These are not exceptions at all, but problems that arise beyond the control of the user or the programmer. Errors are typically ignored in your code because you can rarely do anything about an error. For example, if a stack overflow occurs, an error will arise. They are also ignored at the time of compilation.
Exception Handling Strategy by Spring
To explain the exception handling strategy adopted by the Spring framework, I had to explain the types of exceptions that we have in Java in the previous topic namely “Types of Exception”.
Spring framework creates and throws all the exceptions which extend from RuntimeException class which makes all the exception as unchecked exception.
Spring follows this strategy of exception handling because of the following reasons:
- If the exceptions thrown by Spring framework is checked in nature, developers have to either handle it or declare it. This makes the application tightly coupled with the Spring API’s, which ideally is not the philosophy of Spring.
- If the exceptions are unchecked in nature, the exceptions can be thrown up the call hierarchy and the best place in the hierarchy can handle it more effectively.
- Methods in between don’t know of these exceptions and for an enterprise application, to some extent, this avoids complexity to the developers and avoids t confusion in handling these exceptions throws by the framework.
In typical application using JDBC conventional SQLException is getting thrown for any database error which happens in your application. This exception is too general and doesn’t give us the real picture of what is happening. The calling class would also know that the your application code uses JDBC and also brings in tight coupling between the technology.
Spring’s special exception which takes care of all the exceptions dealing with data access in your Spring application. DataAccessException provides clear hierarchy which hides the actual technology getting used like JPA, Hibernate etc. and is also consistent among all data access technologies. Since it has clear segregation/hierarchy, the actual thing happening during the exception is well known to the class calling these technologies.
DataAccessException exceptions wrap the original exception so there is never any risk that you might loose any information as to what might have gone wrong.
Customize DataAccessException Handling
For non-defined SQL error codes, Spring clearly will not have any idea of the actual nature of the problem and your application will be forced to throw an UncategorisedSQLException, making it difficult for the application developer to give valid error message to the application user. Again Spring comes to rescue by giving an option to you to customize SQL error codes according to your needs.
Out-of-the box, Spring provides a well-considered and fine-grained runtime DataAccessException hierarchy. This is achieved by mapping SQL error codes to exceptions via a file called as sql-error-codes.xml, which lives in the org.springframework.jdbc.support package inside the org.springframework.jdbc jar of the Spring framework distribution. The file sql-error-codes.xml has definition for common databases ( DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase).
First solution to customize this is to simply extract the file sql-error-codes.xml, add what we want in it, and then put it back. This solution has many drawbacks e.g. when we upgrade we must repeat our steps once again.
Second solution is to add a simple Spring context file to the root of the classpath called sql-error-codes.xml as shown in Listing 8-5 below.
Listing 8-5. Customizing DataAccessException error codes
<bean id="dataIntegrityViolatonTriggerCodes" class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">
<!-- comma-separated list of error code to translate into the given exception class.You can use any error codes that you would like to use in your application -->
<property name="errorCodes" value="20001" />
<property name="exceptionClass" value="org.springframework.dao.DataIntegrityViolationException" />
<ref bean="dataIntegrityViolatonTriggerCodes" />
<bean id="Oracle" class="org.springframework.jdbc.support.SQLErrorCodes">
<property name="customTranslations" ref="customTranslations"/>
The point to remember is that our definition didn’t override all the definition but only definition with the same bean id. We can use this mechanism if we have different database, or if we want to extend or change SQL code mapping to exception.
Page Visitors: 9279