2. Exception Handling - general rules
- use exception only for exceptional situation. Creating an exception in Java is expensive and hence you should
not do it just for testing if something is present, valid or permitted. In the latter case design your API to return this
as a regular result.
- every exception has to be logged in specific file to provide necessary information for “service desk”
- decide what is the type of exception:
- Business Exception - caused by invalid behavior of user, which need to be shown to him with specific
message.
- Technical Exception - caused by unexpected and exotic situation, are unchecked and try-catch is needed!
This exception should be wrapped into Business Exception (Runtime exception), which could be shown
to user as “system occur some technical problem, please try later”.
3. Exception Handling - general rules
- all exceptions should be named in specific and easy to understand way describe what unusual situation
happened. Name suffix should be Exception. Examples: ObjectNotFoundException,
IllegalArgumentException, MissingMetricException, DataValidationException …
- Runtime exceptions have to be represented by specific status - proper for each situation.
4. Exception Handling - http status
● 304 Not Modified - Used when HTTP caching headers are in play
● 400 Bad Request - The request is malformed, such as if the body does not parse
● 401 Unauthorized - When no or invalid authentication details are provided. Also useful to trigger an auth popup
if the API is used from a browser
● 403 Forbidden - When authentication succeeded but authenticated user doesn't have access to the resource
● 404 Not Found - When a non-existent resource is requested
● 405 Method Not Allowed - When an HTTP method is being requested that isn't allowed for the authenticated
user
● 500 Internal Server Error - when server has internal error, usually some technical or configuration problem
● … more if necessary
5. global exception
handler/controller layer
service layer
Exception workflow
create exception create bundles
throw & catch Technical
Exception
throw Business
Exception
handle Business
Exception
REST API
Return response with
proper HTTP status and
message
Client
Show view with proper
message
log
log
User
7. Create proper language versions.
//exception.properties
exception.objectNotFound= Cannot find object of type {0}
//exception_pl.properties
exception.objectNotFound= Nie znaleziono obiektu typu {0}
http://www.mkyong.com/spring/spring-resource-bundle-with-resourcebundlemessagesource-example/
8. Register bundles as @Bean
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new
ReloadableResourceBundleMessageSource();
messageSource.setBasename("/exception");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
Note the basename is filepath of base msg file without .properties extension
http://www.concretepage.com/spring-4/spring-4-mvc-internationalization-i18n-and-localization-l10n-annotation-example
9. Create new exception
public abstract class BaseLocalizedException extends RuntimeException {
public String getLocalizedMessageKey() {
return "exception.objectNotFound"
}
public abstract Object[] getLocalizedMessageArguments();
}
public class BusinessObjectNotFoundException extends BaseLocalizedException {
private String objectType;
public String getLocalizedMessageKey() {
return "exception.objectNotFound"
}
public Object[] getLocalizedMessageArguments() {
return new Object[] {objectType};
}
}
10. Service layer
Throwing & catching Technical Exception
Anytime you catch technical exception you wrap it into business exception and
throw it in service layer.
Throwing Business Exception
You have to throw all business exception from service layer (in some cases
they could be throw from controller layer as well e.g. form validation)
12. @ResponseStatus annotation
Unhandled exception causes server to return HTTP 500 response
Exceptions annotated with @ResponseStatus - when not handled - will return
chosen HTTP response accordingly to settings.
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order") // 404
public class OrderNotFoundException extends RuntimeException {
// ...
}
14. For specific controller …
@Controller
public class ExceptionHandlingController {
// @RequestHandler methods
...
// Exception handling methods
// Convert a predefined exception to an HTTP Status code
@ResponseStatus(value=HttpStatus.CONFLICT, reason="Data integrity violation") // 409
@ExceptionHandler(DataIntegrityViolationException.class)
public void conflict() {
// Nothing to do …
}
15. … and globally
@ControllerAdvice
class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.CONFLICT) // 409
@ExceptionHandler(DataIntegrityViolationException.class)
public void handleConflict() {
// Nothing to do ...
}
}
16. Global Exception Handler
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = Logger.getLogger(GlobalExceptionHandler.class);
@ResponseStatus(value = HttpStatus.UNAUTHORIZED, reason = "AuthenticationException")
@ExceptionHandler(AuthenticationException.class)
public void handleAuthenticationException(HttpServletRequest request,
AuthenticationException ex) {
logger.error("AuthenticationException: URL=" + request.getRequestURL(), ex);
}
}
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
17. Logging strategy
Always log exception on at least warning level.
Log Technical Exception on service layer and Business Exception in Global
Exception Handler.
18. Logger - SLF4J + logback / log4j / java.util.
logging
SLF4J - Simple Logging Facade for Java - allows end user to plug-in the desired
logging framework at the deployment time.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
19. Comparison of logger frameworks
Log4j - logging library for Java [2000-2002] ( no info about bugs )
Logback - Logback is intended as a successor to the popular log4j project,
picking up where log4j leaves off. [2006-now ] ( 324 unresolved )
Log4j 2 - Apache Log4j 2 is an upgrade to Log4j that provides significant
improvements over its predecessor, Log4j 1.x, and provides many of the
improvements available in Logback while fixing some inherent problems in
Logback's architecture. - [2012-now] (276 unresolved issues)