loggingjakarta-eeerror-handlingora-06550

how do I catch errors globally, log them and show user an error page in J2EE app


I have searched this topic on google a bit and seen some best practices. But I need some specific advice. I am working on a J2EE app that has servlets/Struts2/Call to DAO's from JSP's. So the app is all kinds of messed up. Most of the data is fetched via stored procedures, which are being called by iBatis ORM/Spring. Sometimes when an error happens on the SP side it will display an ugly message to the user such as below:

javax.servlet.ServletException: org.springframework.jdbc.BadSqlGrammarException: SqlMapClient operation; bad SQL grammar []; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred in debtowed.xml.  
--- The error occurred while applying a parameter map.  
--- Check the debtowed.getFormerTenantData.  
--- Check the statement (update procedure failed).  
--- Cause: java.sql.SQLException: ORA-06550: line 1, column 11:
PLS-00905: object package.GET_FORMER_ADDRESS is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Caused by: java.sql.SQLException: ORA-06550: line 1, column 11:
PLS-00905: object package.GET_FORMER_ADDRESS is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

At this point the above information is displayed in the browser and logged to server.log.
However, I want to do following:

Plese tell me what is the best way of doing this? Should I be adding something in web.xml? like a listener? will that be the only change or will I have to change existing code?

The code does not do any error checking. it just calls the SP like below

getSqlMapClientTemplate().queryForList("sp.getfmrAddy", paramMap);

Solution

  • I expect this is already solved in some way by Struts - so best check struts docco. If i were you i'd write an ExceptionFilter that can wrap your servlet calls:

    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.log4j.Logger;
    
    public class ExceptionFilter implements Filter{
    
    private static final Logger logger = Logger.getLogger(ExceptionFilter.class);
    private ExceptionService exceptionService = null;
    @Override
    public void destroy() {
        exceptionService.shutdown();
    }
    
    @Override
    public void doFilter(ServletRequest rq, ServletResponse rs, FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(rq, rs); // this calls the servlet which is where your exceptions will bubble up from
        } catch (Throwable t) {
            // deal with exception, then do redirect to custom jsp page
            logger.warn(t);
            exceptionService.dealWithException(t); // you could have a service to track counts of exceptions / log them to DB etc
            HttpServletResponse response = (HttpServletResponse) resp;
            response.sendRedirect("somejsp.jsp");
        }
    }
    
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
        exceptionService = new ExceptionService();
    }
    
    }
    

    and add this to your web.xml:

    <filter>
      <filter-name>ExceptionFilter</filter-name>
      <filter-class>com.example.ExceptionFilter</filter-class>
    </filter>
    
    <filter-mapping>
      <filter-name>ExceptionFilter</filter-name>
      <servlet-name>MyMainServlet</servlet-name>
    </filter-mapping>
    

    then add filter mappings for all your servlets.

    Hope that helps.