java - propagacion - ¿Cómo dejar de imprimir el seguimiento de la pila de excepciones en la consola?
propagacion de excepciones en java (7)
Escribí un servlet para manejar las excepciones que ocurren en mi aplicación web y las asigné en web.xml
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/exceptionHandler</location>
</error-page>
Esto es lo que he hecho en el método de service
servlet de manejo de excepciones:
@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);
}
}.
Problema:
El enfoque anterior no funciona y la traza de la pila se está imprimiendo en la consola. Esto ocurre cuando el usuario solicita algo y luego cierra su navegador.
Pregunta:
¿Cómo detengo la impresión del seguimiento de pila en la consola JBoss cada SocketException
produce una SocketException
?
Razón para hacer esto:
Quiero evitar ver todas las SocketException
del registro al final del día porque no puedo hacer nada con esa información.
Aquí es lo que hice para la guerra como trabajo alrededor.
Se agregó un filtro y se secuestraron todas las solicitudes y respuestas. Detecte la excepción y verifique el tipo.
/**
* 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.
}
}
}
Y en web.xml
, mapeo de filtro.
<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>
No estoy marcando esto como respuesta, ya que no estoy seguro de que esto sea una forma estándar o no. Simplemente es una solución.
Como lo entiendo, las excepciones se registran en la consola cuando no se detecta antes de llegar al contenedor. Como tal, usar un filtro para detectar excepciones no manejadas tiene sentido.
Struts2 también tiene una excepción ''interceptor'' como su último interceptor, por defecto. Ver defaultStack . Necesitamos anular este interceptor si necesitamos un manejo de excepciones personalizado.
Lo único que haría adicionalmente sería registrar las excepciones (al menos a un archivo de errores-ignore.txt) en lugar de omitirlas por completo.
En lugar de agregar java.lang.Exception
en tu web.xml, ¿por qué no intentas agregar una excepción de socket en el propio web.xml como se muestra a continuación?
<error-page>
<exception-type>java.net.SocketException</exception-type>
<location>/exceptionHandler</location>
</error-page>
y simplemente no haga nada en su servlet O en su lugar, agregue un archivo jsp vacío como
<error-page>
<exception-type>java.net.SocketException</exception-type>
<location>/error.jsp</location>
</error-page>
Otra idea funky: podrías crear un manejador de excepciones.
class SocketExceptionSwallower implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof SocketException) {
// swallow
} else {
e.printStackTrace();
}
}
}
y registrado con
Thread.setDefaultUncaughtExceptionHandler(new SocketExceptionSwallower());
o
Thread.currentThread().setUncaughtExceptionHandler(new SocketExceptionSwallower());
Simple, no hay sobrecarga de otro filtro en cadena, pero se mete con subprocesos y probablemente romperá algo en el entorno Java EE)
Puede ser útil para probar / experimentar o si controla completamente los hilos en su propio código
Probablemente tendrá que anular el método fillInStackTrade
public static class CustomException extends Exception {
@Override
public Throwable fillInStackTrace() {
return null;
}
}
Puede utilizar el Logger
. Para esto necesita la biblioteca log4j
y todo el comportamiento deseado y las excepciones se escriben en el archivo de registro. Para esto necesitas dar la ruta del archivo de registro.
Utilice Jboss Custom Logging Handler para resolver este problema.
Si no desea registrar ningún SocketException
pila de excepciones de SocketException
, simplemente SocketException
sesión en un archivo.
Pasos a seguir:
- Un controlador personalizado debe heredar java.util.logging.Handler
Aquí está el código:
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;
}
}
Luego, el archivo se empaqueta en un frasco y se coloca en el directorio de módulos.
es decir,
Jboss-7.1.1/modules/com/custom/jboss/loggers/main
junto con un archivo module.xml. El contenido del module.xml debería verse así.<?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>
Luego, modifique el archivo standalone.xml para admitir el registro en el registrador personalizado
<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>
Agregue más manejador en root-logger si es necesario, como ARCHIVO, CONSOLA, etc.
- Ahora todos los registros se registrarán en su archivo de registro personalizado a través de este controlador personalizado donde hemos omitido
SocketException
- Podemos hacer que esta clase pase más propiedades genéricas de standalone.xml, como las que se usan para pasar la ruta del archivo de registro.
Por favor, hágamelo saber si hay algún problema.