4
\$\begingroup\$

I hate using unnecessary catch blocks and I like to see my code look beautiful. In most of the cases in my project, which is a web application, I can't declare many exceptions as checked exceptions as there is little that my client (browser) can do to recover from the exception. However, only if there is a way that the client of my code (mostly fellow programmer) can gracefully handle the exceptions, I am declaring such exceptions as checked exceptions (so that there are few throws clauses as possible).

I am trying to hide the implementation detail specific checked exceptions of my DAO classes from being known to the Service layer (by wrapping the exception in a layer specific checked exception).

I have the following approach for logging and displaying error messages to the user in the JSPs. I am logging exceptions in a centralized place. A Servlet Filter:

public class WebAppUtils {

    private static final Logger logger = LoggerFactory.getLogger(WebAppUtils.class);

    //Called from the Filter's doFilter() method, which is mapped to /*
    public static void log(ServletRequest request, ServletResponse response, FilterChain chain) {
        try {
            chain.doFilter(request, response);
        } catch (Throwable exception) {
            String rootCauseMessage = ExceptionUtils.getRootCauseMessage(exception);
            request.setAttribute("rootCauseMessage", rootCauseMessage);
            if (exception instanceof RuntimeException) {
                logger.error("A Runtime Exception has occurred. The cause is " + rootCauseMessage, exception);
                throw new RuntimeException();
            }
            if (exception instanceof Exception) {
                logger.error("An Exception has occurred. The cause is " + rootCauseMessage, exception);
            } else {
                logger.error("An Error has occurred. The cause is " + rootCauseMessage, exception);
            }
            throw new RuntimeException();
        }
    }


    //Called when context is being destoyed
    public static void cleanUp() {
        deRegister();

        if (logger.isInfoEnabled()) {
            logger.info("Jdbc drivers have been " +
                    "de-registered to prevent memory leak. Shutting down loggers.");
        }
        LogManager.shutdown();
    }

    private static void deRegister() {
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.info(String.format("De-registering jdbc driver: %s", driver));
            } catch (SQLException e) {
                logger.info(String.format("Error de-registering driver %s", driver), e);
            }
        }
    }
}

My web.xml:

<filter>
    <filter-name>logger</filter-name>
    <filter-class>com.mycompany.ExceptionLogger</filter-class>
</filter>

<filter-mapping>
    <filter-name>logger</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/WEB-INF/error.jsp</location>
</error-page>

Error Page:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    <div>
        //This shows the caused exception name with the optional message. 
        //I am not too happy with it as the user may not be interested in my custom exception name. 
        //How can I improve this?

            Oops! Something went wrong. The cause is 
            <span>
                <c:if test="${!empty requestScope.rootCauseMessage}">
                    <c:out value="${requestScope.rootCauseMessage}"/>
                </c:if>
            </span>

    </div>

How can I improve the shown approach for logging and is there any better way to report error conditions(in a more meaningful way than the one showed)to the user in JSPs?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.