How to stop printing exception stack trace on Console?

17,177

Solution 1

Instead of adding java.lang.Exception in your web.xml why won't you just try to add socket exception in web.xml itself like below

<error-page>
  <exception-type>java.net.SocketException</exception-type>
  <location>/exceptionHandler</location>
</error-page>

and just do nothing in your servlet Or instead add a empty jsp file like

<error-page>
  <exception-type>java.net.SocketException</exception-type>
  <location>/error.jsp</location>
</error-page>

Solution 2

Here is what I done so war as work around.

Added one filter and hijack all the request and response.Catch the exception and check the type.

/**
 * Hijacks all the http request and response here.
 * Catch the SocketException and do not print 
 * If other exceptions print to console
 * date : 9-18-2013
 * 
 * @author Suresh Atta
 *
 */
public class ExceptionHandler implements Filter {

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2) throws IOException, ServletException {
        try{
        arg2.doFilter(arg0, arg1);
        }catch(SocketException e ){
           // Please don't print this to log.    
        }
    }


}

And in web.xml ,filter mapping

<filter>
        <filter-name>ExceptionHandler</filter-name>
        <filter-class>com.nextenders.server.ExceptionHandler</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ExceptionHandler</filter-name>
        <dispatcher>  REQUEST   </dispatcher>
        <url-pattern> /*</url-pattern>
    </filter-mapping>  

I'm not marking this as answer,since I'm not sure this is a standard way or not.Just a work around.

Solution 3

Use Jboss Custom Logging Handler to solve this problem.

If you don't want to log any SocketException exception stack trace then just skip it while loggin into a file.

Steps to follow:

  • A custom handler must inherit java.util.logging.Handler

Here is the code:

package com.custom.jboss.logging;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.logging.ErrorManager;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

public class SocketExceptionCustomLoggingHandler extends Handler {

    private String logFile;
    public BufferedWriter out = null;

    public SocketExceptionCustomLoggingHandler() {
        super();
        logFile = "";
    }

    @Override
    public void publish(LogRecord record) {
        if (!initialize()) {
            return;
        }
        if (isLoggable(record)) {
            process(record);
        }
    }

    private synchronized boolean initialize() {
        if (out == null && logFile != null && !logFile.equals("")) {
            FileWriter fstream = null;
            try {
                fstream = new FileWriter(logFile, true);
                out = new BufferedWriter(fstream);
            } catch (IOException e) {
                reportError(e.getMessage(), e, ErrorManager.OPEN_FAILURE);
            }
            logToFile("Log file initialized. Logging to: " + logFile);
        }
        return true;
    }

    private void process(LogRecord logRecord) {

        String log = getFormatter().format(logRecord);
        if (log.indexOf("java.net.SocketException") == -1) {
            logToFile(log);
        }
    }

    private void logToFile(String text) {
        try {
            if (out != null) {
                out.write((new Date()).toString() + "\t" + text + "\n");
                out.flush();
            }
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.WRITE_FAILURE);
        }

    }

    @Override
    public void flush() {
        try {
            if (out != null) {
                out.flush();
            }
        } catch (IOException e) {
            reportError(e.getMessage(), e, ErrorManager.FLUSH_FAILURE);
        }
    }

    @Override
    public void close() {
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                reportError(e.getMessage(), e, ErrorManager.CLOSE_FAILURE);
            }

        }
    }

    public void setLogFile(String logFile) {
        this.logFile = logFile;
    }

}
  • The file is then packaged into a jar and placed in the modules directory.

    i.e. Jboss-7.1.1/modules/com/custom/jboss/loggers/main together with a module.xml file. The contents of the module.xml should look like this.

    <?xml version="1.0" encoding="UTF-8"?>   
    <module xmlns="urn:jboss:module:1.0" name="com.custom.jboss.loggers">  
         <resources>      
               <resource-root path="SocketExceptionHandler.jar"/>  
              <!-- Insert resources here -->   
         </resources>    
         <dependencies>      
              <module name="org.jboss.logging"/>  
              <module name="javax.api"/>   
         </dependencies>  
    </module>  
    
  • Then modify the standalone.xml to support logging to the custom logger

    <subsystem xmlns="urn:jboss:domain:logging:1.1">
        ...
        <custom-handler name="SocketExceptionAppender" class="com.custom.jboss.logging.SocketExceptionCustomLoggingHandler" module="com.custom.jboss.loggers">
            <level name="DEBUG"/>
            <formatter>
                <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
            </formatter>
            <properties>
                <property name="logFile" value="d:\\temp\\logfile.txt"/>
            </properties>
        </custom-handler>
        ...
        <root-logger>
            <level name="INFO"/>
            <handlers>
                <handler name="SocketExceptionAppender"/>                    
            </handlers>
        </root-logger>
    </subsystem>
    
  • Add more handler in root-logger if needed such as FILE, CONSOLE etc.

  • Now all the logs will be logged in your custom log file via this custom handler where we have skipped SocketException
  • We can make this class more generic passing properties from standalone.xml such as used to pass log file path.

Please let me know if there is any issue.

Solution 4

You probably will have to override fillInStackTrade method

public static class CustomException extends Exception {
@Override
public Throwable fillInStackTrace() {
    return null;
}       

}

Solution 5

As I understand it, exceptions are logged to the console when it is not caught before reaching the container. As such using a filter to catch unhandled exceptions makes sense.

Struts2 also has an exception 'interceptor' as its last interceptor, by default. See defaultStack. We need do override this interceptor if we need custom exception handling.

The only thing I would do additionally would be to log the exceptions (atleast to an errors-ignore.txt file) rather than completely skipping them.

Share:
17,177

Related videos on Youtube

Suresh Atta
Author by

Suresh Atta

Send a direct message My Fav questions How can a string be initialized using " "? The meaning of Java code (Object[])(Object[])arrayOfBytes[1] Where is .class defined in Java? (Is it a variable or what?)

Updated on March 14, 2020

Comments

  • Suresh Atta
    Suresh Atta about 4 years

    I wrote a servlet to handle the exceptions occurring in my web app and mapped them in web.xml

        <error-page>
          <exception-type>java.lang.Exception</exception-type>
          <location>/exceptionHandler</location>
        </error-page>
    

    Here is what I have done in the Exception Handling servlet service method:

    @Override
        protected void service(HttpServletRequest req, HttpServletResponse arg1)
                throws ServletException, IOException {
             Object attribute = req.getAttribute("javax.servlet.error.exception");
             if(attribute instanceof  SocketException){
                // don't do anything 
             }else{
              super.service(req, arg1);
             }
        }.
    

    Problem:

    The above approach is not working and the stack trace is printing to the console. This occurs when the user requests something and then closes their browser.

    Question:

    How do I stop printing the stacktrace to the JBoss console whenever a SocketException occurs?

    Reason for doing this:

    I want to avoid seeing all of the log's SocketExceptions at the end of th day because I can't do anything with that information.

    • Taylor Hx
      Taylor Hx over 10 years
      If you know why the exception is occurring, then shouldn't you be handling that exception according to your requirements when it occurs? A filter like you suggest would filter all occurrences of the exception, even when they occur for reasons other than those you expect.
    • Suresh Atta
      Suresh Atta over 10 years
      @Daemon There is no way to handle that. I given the reason :). All I want to do is just escape that stacktrace in server logs.
    • Taylor Hx
      Taylor Hx over 10 years
      Ahh, I see. The exception is being held as an attribute of the ServletRequest, and isn't caught until request is processed.
    • me_digvijay
      me_digvijay over 10 years
      I am not sure why you had to override the service(). I think this could have been done in doGet and doPost methods. Also how do your doGet and doPost methods look like. One more thing, why aren't you calling these two methods inside your service method?
    • Sudarshan_SMD
      Sudarshan_SMD over 10 years
      Are you sure that using 'java.lang.Exception' for specifying exception-type works? Try using java.lang.Throwable, which should be used to specifying generic error handler. <exception-type>java.lang.Throwable</exception-type > As you want to handle SocketException, you might want to use something like this: <exception-type>java.net.SocketException</exception-type >
    • ericson
      ericson over 10 years
      Could you attach the stack trace to your question? thanks.
    • Jorge Campos
      Jorge Campos over 10 years
      @sᴜʀᴇsʜᴀᴛᴛᴀ As you are talking about jboss, what about add an appender to your jboss-log4j.xml? At $JBOSS_HOME/server/{profile}/default/conf
    • Bimalesh Jha
      Bimalesh Jha about 10 years
      Adding to previous comment by @JorgeCampos in log4j.xml check the package (Logger class) that logs the error and increase its Level Threshold to FATAL. This might work. Another option I would explore is to override the default HTTP connector of Tomcat and suppress/log SocketException at debug Level.
    • Braj
      Braj about 10 years
      Please share the stack trace logged for ScoketException so that I can try to figure it out.
    • Braj
      Braj about 10 years
      Have you tries Jboss custom logging handler? Have a look at my answer and let me know if am I wrong as per your requirement.
  • Suresh Atta
    Suresh Atta over 10 years
    To write this I need to get the control over http response.That's stopping me to do this.
  • Matthias
    Matthias over 10 years
    I would do it differently. There is no reason to catch Exception in your code. I would just catch SocketException or at least rethrow the wrongly catched exceptions to allow other filters to react properly on those exceptions, not just swalling it and printing to the console.
  • Suresh Atta
    Suresh Atta over 10 years
    @Matthias Thanks for that spot. Editted with new code. This code posted long back and recently I changed the logic. Catching socket exception and doing nothing there.There is no way to handle that. I given the reason :). All I want to do is just escape that stack trace in server logs.
  • Matthias
    Matthias over 10 years
    Yeah, I understand what you want to achieve and it certainly prevents the log from being scattered with misleading exceptions. The only thing you could do to "handle the SocketException" is to write a small message to your normal log (maybe on debug/info level) that the user aborted the request. This makes it easier to track sessions if you have some issues in production and have to follow a log file. I have that rule to log everything entering or leaving my application so I can track things.
  • Suresh Atta
    Suresh Atta over 10 years
    @Matthias yes, yes. Now doing the same. Inside that catch block there is a little business logic to track things :)
  • Matthias
    Matthias over 10 years
    Wonderful, then I believe your workaround is actually a neat solution.
  • Suresh Atta
    Suresh Atta about 10 years
    Thanks for the valuable response. Will try and get back to you.
  • oxfn
    oxfn about 10 years
    Can you provide an example, how log4j can prevent output of unhandled exception stack trace?