Sie sind auf Seite 1von 8

Exception Handling Guidelines

Overview
Exception logging: Don't hide exception stack traces and use appropriate logger.error method to log exceptions
Exception logging: Include adequate context information in error messages
Exception Handling : Don't handle runtime exceptions
Exception Handling : Don't ever handle java.lang.Exception or java.lang.Throwable
Exception Handling : Use global exception handler
Exception Handling : Handling Checked Exceptions
Don't ignore exceptions
Don't propagate checked exceptions. If possible recover from the checked exception gracefully. It is a burden on others.
Throwing Exceptions : Always prefer unchecked exceptions for unrecoverable errors. Don't overuse checked exceptions.
Throwing Exceptions : Favor standard exception types
Throwing Exceptions : Document exceptions thrown by your code
Use exceptions for exceptional cases.

Overview
Exception handling in java is an important part of developing robust and clean applications. When it is done wrong it ruins readability and makes
applications error prone.

This page lists the guidelines in exception handling with examples.

Exception logging: Don't hide exception stack traces and use appropriate logger.error
method to log exceptions
Don't do this

try {
// some code throwing an checked exception
} catch (SomeCheckedException exception)
{
LOGGER.error("my error message");
}

Do this

This will help others to triage the errors .

try {
// some code throwing an checked exception
} catch (SomeCheckedException exception)
{
LOGGER.error("my error message",exception);
}

Exception logging: Include adequate context information in error messages


Don't do this .
void addProductToCart(String cartId,String productId) {
try {
// some code throwing an checked exception
} catch (SomeCheckedException exception)
{
LOGGER.error("Adding a product to cart failed ",exception);
}
}

Do this

void addProductToCart(String cartId,String productId) {


try {
// some code throwing an checked exception
} catch (SomeCheckedException exception)
{
LOGGER.error("Adding a product to cart failed cartId="+cartId+ " productId="+
productId,exception);
}
}

Exception Handling : Don't handle runtime exceptions


This and next 2 practices are related.

Runtime exceptions include programming errors, precondition validations and unrecoverable errors such as http communication errors. They
shouldn't be handled .

There could be cases where your code may need to recover from a runtime error. This should be rare , should be document very well
and its scope should be as limited as possible.

If appropriate use a global exception handler to handle all runtime exceptions

Don't do this

void addProductToCart(String cartId,String productId) {


try
{
// some code
ResponseEntity entity = restTemplate.postForEntity(...);
// some more code
} catch (HttpClientErrorException httpExp) {
LOGGER.error("my error", httpExp);
}
}

Do this:

Don't handle the runtime exceptions and let the global exception handler to handle them
void addProductToCart(String cartId,String productId) {
ResponseEntity entity = restTemplate.postForEntity(...);
// some other code
}

Exception to the above rule.

Possible runtime exception handling example


void createUser() {
// some code
try {
ResponseEntity response = restTemplate.postForEntity(...);
} catch(HttpClientErrorException httpException) {
if (getStatus(exception).equals(HttpStatus.BAD_REQUEST) &&
getMessage(exception).equals(DUPLICATED_USER_ID)) {
// When a new user with an existing user ID is created hybris returns
400 bad request error.
// It is likely that store fronts will send same user id multiple times
so we have to handle this error and continue with normal flow.
// This specific error is ignored.
} else {
throw httpException; // all other failures are genuine failures and should
not be handled.
}
}
// some more code
}

Exception Handling : Don't ever handle java.lang.Exception or java.lang.Throwable


This is the most common and most harmful practice.

It makes the code unreadable and hides genuine programming errors. By handling java.lang.Exception your code handles all programming errors
such as NullPointerException etc..

There might be cases where your code may need to recover from all the exceptions: This should be very rare , should be documented very
well and its scope should as limited as possible (try block with 1 line of code). It is ideal to use global exception handler for
handling all exceptions.

Don't ever do this


void addProductToCart(String cartId,String productId) {
try
{
// some lengthy code
ResponseEntity entity = restTemplate.postForEntity(...);
// some more lengthy code
} catch (Exception httpExp) {
LOGGER.error("something went really bad.", httpExp);
}
}

Very rare exception to the above rule.

void consumeJMSMessage(JMSMessage message) {


// some code to process JMS message
// notify the component XXXX
try
{
LibraryXXX.notify(messageBody);
} catch (Throwable exception) {
// 3rd party library XXXXX may throw java.lang.Error when the message body
contains YYYYY ...
// We can't allow this thread to terminate . If this happens we should handle
all errors and continue with the next message in the queue.
LOGGER.error("Failed to notify component XXXXX. message body was=" +
message.getBody, exception);
return;
}

Exception Handling : Use global exception handler


Restfull services using spring boot has very extensive usage in PMC platform.

It is always good practice to define an general API policy for unexpected errors. Some examples.

If an error occurs:

Caller should be redirected a failure page


Appropriate error response should be returned to the caller.

Best way to achieve this is introducing global exception handler for the whole application.
@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Throwable.class)
void RedirectView handleAllException(final Throwable exception)
{
// This component's API policy is redirecting to an error page for all the errors
// It could have been returning an ResponseEntity with 500 http status
LOG.error("handleAllException:", exception);
return redirectToErrorPage(.....);

}
}

It is a good practice to return appropriate errors and status codes for different types of exceptions. Such as returning 400 http status for llegalAr
gumentException

It is also possible and OK to handle exceptions in Controllers in more granular fashion. See here more on this.

Exception Handling : Handling Checked Exceptions


Checked exceptions include all the errors where your code may recover from an exception. Java language forces programmers to handle
checked exceptions . 3 possible scenarios can occur

Handle the exception gracefully


Mark your function to throw the exception. (Should be rare and only used in the same class where all the logic is encapsulated.)
Handle the exception and rethrow a new exception. This is documented in next section

Don't ignore exceptions


Don't do this

try {
// some code
} catch (SomeException e) {
}

An empty catch block defeats the purpose of exceptions, The catch block at least should contain a comment and explain why it is appropriate to
ignore the exception. Exception should also be logged if appropriate.

Don't propagate checked exceptions. If possible recover from the checked exception gracefully. It is
a burden on others.
Don't do this
class GlobalContentReader {
static void String readContent() throws FileNotFoundException // make them suffer ! {
return readContentFromAFile(somefile);
}
}

/// a caller in other class


try {
String content = GlobalContentReader.readContent();

} catch (FileNotFoundException ex) {


// ?? I have no idea what to do about this. ??
}

Do this

class GlobalContentReader {
static void String readContent() {
try {
return readContentFromAFile(somefile);
} catch (FileNotFoundException ex) {
log.warning ("failed to find the content file . Using the default
content",ex);
return DEFAULT_CONTENT;
}
}
}

// a happy caller
String content = GlobalContentReader.readContent();
// continue with good path.

Throwing Exceptions : Always prefer unchecked exceptions for unrecoverable errors.


Don't overuse checked exceptions.
If the programmer using the your code can do no better, an unchecked exception would be more appropriate.

Don't do this :
void static String decrypt(String encrypted) throws MyDecryptionException {
try {
return decrypt(encrypted);
} catch (FileNotFoundException exception) {
// Decryption key can't be found. So throwing an checked exception . Let others
deal with it !
throw new MyDecryptionException(exception); // MyDecryptionException extends
Exception
}
}

/// a caller in other class


try {
String decrypted = DecryptionUtil.decrypt(encrypted);

} catch (MyDecryptionException ex) {


// Well there is no point of going for the good path. If we can't decrypt the content
we loose
return redirectToFailurePage();
}

Do this :

void static String decrypt(String encrypted) {


try {
return decrypt(encrypted);
} catch (FileNotFoundException exception) {
// Decryption key can't be found. We can't recover from this and callers can't
possibly recover from this too.
throw new MyDecryptionRuntimeException(exception); // MyDecryptionException
extends RuntimeException
}
}

/// a happier caller in other class


String decrypted = DecryptionUtil.decrypt(encrypted);
// use the content
use(decrypted);

Throwing Exceptions : Favor standard exception types

Java libraries provide a basic set of unchecked exceptions . Favor them to custom exception types
Do this :
void validateCart(Cart cart) {
Set<ConstraintViolation<Object>> violations = validator.validate(o);
if (!violations.isEmpty()) {
// IllegalArgumentException is standard java exception . Thrown to indicate
that an illegal or
// inappropriate argument has been passed.
throw new java.lang.IllegalArgumentException( getValidationErrors(violations)
);
}
// all was fine
}

Throwing Exceptions : Document exceptions thrown by your code


Use the Javadoc @throws tag to document exceptions thrown by your code

Use exceptions for exceptional cases.


Query the reasons when throwing or handling exceptions.

Try to stick to the rules above and your code will be much cleaner and easier for others to use

Das könnte Ihnen auch gefallen