web-dev-qa-db-ja.com

コンソールで例外スタックトレースの印刷を停止するにはどうすればよいですか?

Webアプリで発生する例外を処理するサーブレットを作成し、それらをweb.xmlにマッピングしました

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

例外処理サーブレットserviceメソッドで行ったことは次のとおりです。

@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);
         }
    }.

問題:

上記のアプローチは機能せず、スタックトレースはコンソールに出力されます。これは、ユーザーが何かを要求してからブラウザを閉じたときに発生します。

質問:

SocketExceptionが発生するたびにJBossコンソールへのスタックトレースの出力を停止するにはどうすればよいですか?

これを行う理由:

その情報では何もできないため、1日の終わりにすべてのログのSocketExceptionsが表示されないようにします。

19
Suresh Atta

これが私が回避策として戦争をしたことです。

1つのフィルターを追加し、すべての要求と応答をハイジャックします。例外をキャッチして、タイプを確認します。

/**
 * 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.    
        }
    }


}

そしてweb.xml、フィルターマッピング

<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>  

これが標準的な方法であるかどうかわからないため、これを回答としてマークしていません。回避策だけです。

7
Suresh Atta

Web.xmlにJava.lang.Exceptionを追加する代わりに、以下のようにweb.xml自体にソケット例外を追加しようとしないのはなぜですか。

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

サーブレットでは何もしませんまたは代わりに次のような空のjspファイルを追加します

<error-page>
  <exception-type>Java.net.SocketException</exception-type>
  <location>/error.jsp</location>
</error-page>
7
Prakash

Jbossカスタムロギングハンドラーを使用してこの問題を解決します。

SocketException例外スタックトレースをログに記録したくない場合は、ファイルにログインするときにスキップしてください。

従う手順:

  • カスタムハンドラーはJava.util.logging.Handlerを継承する必要があります

コードは次のとおりです。

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;
    }

}
  • 次に、ファイルはjarにパッケージ化され、modulesディレクトリに配置されます。

    つまり、Jboss-7.1.1/modules/com/custom/jboss/loggers/mainmodule.xmlファイルと一緒に。 module.xmlの内容は次のようになります。

    <?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>  
    
  • 次に、standalone.xmlを変更して、カスタムロガーへのロギングをサポートします。

    <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>
    
  • 必要に応じて、FILE、CONSOLEなどのハンドラーをルートロガーに追加します。

  • これで、すべてのログは、SocketExceptionをスキップしたこのカスタムハンドラーを介してカスタムログファイルに記録されます。
  • このクラスを、ログファイルパスの受け渡しに使用されるような、standalone.xmlからのより一般的な受け渡しプロパティにすることができます。

何か問題がありましたらお知らせください。

3
Braj

おそらくfillInStackTradeメソッドをオーバーライドする必要があります

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

}

2
MansoorShaikh

私が理解しているように、例外は、コンテナーに到達する前にキャッチされない場合、コンソールに記録されます。そのため、フィルターを使用して未処理の例外をキャッチすることは理にかなっています。

Struts2には、デフォルトで最後のインターセプターとして例外「インターセプター」もあります。 defaultStack を参照してください。カスタム例外処理が必要な場合は、このインターセプターをオーバーライドする必要があります。

私が追加で行う唯一のことは、例外を完全にスキップするのではなく、例外をログに記録することです(少なくともerrors-ignore.txtファイルに)。

2
Ravindra HV

別のファンキーなアイデア:例外ハンドラーを作成できます

class SocketExceptionSwallower implements Thread.UncaughtExceptionHandler {
        public void uncaughtException(Thread t, Throwable e) {
            if (e instanceof SocketException) {
                // swallow
            } else {
                e.printStackTrace();
            }
        }
    }

と登録

Thread.setDefaultUncaughtExceptionHandler(new SocketExceptionSwallower());

または

Thread.currentThread().setUncaughtExceptionHandler(new SocketExceptionSwallower());

単純で、チェーン内の別のフィルターのオーバーヘッドはありませんが、スレッドを混乱させ、おそらくJava EE環境)で何かを壊します
テスト/実験、または独自のコードでスレッドを完全に制御する場合に役立つ可能性があります

1
Yuri

Loggerを使用できます。このためには、log4jライブラリが必要であり、必要なすべての動作と例外がログファイルに書き込まれます。このためには、ログファイルのパスを指定する必要があります

1
UmeshA