2009-05-19 6 views
4

donc je suis en utilisant un filtre pour attraper exception servlet (parce que nous utilisons un mélange de servlets jsf/plain)correctement printStackTrace d'exception servlet

lors de la capture du ServletException et appelant printStackTrace la plupart des informations est perdu.

la « vraie » exception racine semble être caché derrière la « drôle » expression

((ServletException) e.getRootCause().getCause()).getRootCause().getCause().getCause().getCause() 

c'est clairement pas la façon de le faire.

est un moyen facile d'imprimer les informations "complètes" d'une telle exception. quelqu'un peut-il m'expliquer pourquoi l'exception est enveloppée de cette façon?

Répondre

6

Jetez un oeil à la classe ExceptionUtils de Communes- lang. Il contient plusieurs méthodes utiles pour imprimer toute la chaîne des exceptions.

1

C'est ce qu'on appelle exception chaining. En encapsulant une exception dans une exception différente, vous pouvez laisser les exceptions remonter la pile sans que vos classes d'application principales s'inquiètent de certaines exceptions de bas niveau.

Exemple:

public void doStuff() throws StuffException { 
    try { 
     doDatabaseStuff(); 
    } catch (DatabaseException de1) { 
     throw new StuffException("Could not do stuff in the database.", de1); 
    } 
} 

De cette façon, votre application n'a qu'à gérer StuffException mais il peut arriver à l'DatabaseException sous-jacente si elle a vraiment besoin.

Pour aller au fond le plus (et tous les autres) exception (s) d'une exception que vous vous pris pouvez itérateur sur ses causes profondes:

... 
} catch (SomeException se1) { 
    Throwable t = se1; 
    logger.log(Level.WARNING, "Top exception", se1); 
    while (t.getCause() != null) { 
     t = t.getCause(); 
     logger.log(Level.WARNING, "Nested exception", t); 
    } 
    // now t contains the root cause 
} 
+0

le problème avec cette approche: une tonne d'informations sur les exceptions de niveau supérieur (leurs messages) est perdu. –

+0

Je ne pense pas qu'il veut supprimer la chaîne d'exceptions - il suffit de le connecter intelligemment –

+0

voter pour une bonne justice. bien que cela ne fournisse pas la solution, cela explique l'imbrication des exceptions. –

3

après avoir jeté un oeil à ExceptionUtils, cela a résolu le problème!

final StringWriter stacktrace = new StringWriter(); 
    ExceptionUtils.printRootCauseStackTrace(throwable,new PrintWriter(stacktrace)); 
    msg.append(stacktrace.getBuffer()); 

Ceci imprime la pile complète avec toutes les informations pertinentes.

+0

Huh? Throwable.printStackTrace() l'est aussi. –

+1

Throwable.printStackTrace() suit uniquement la chaîne Throwable.getCause(). Il y a beaucoup d'exceptions bizarres (par exemple SQLException) qui utilisent des noms de méthodes différents pour stocker la cause première d'une exception (en raison d'une manière non standard de le faire avant Java 1.4).ExceptionUtils suit des méthodes telles que getNextException, getTargetException, getRootCause, etc. (voir la classe pour la liste complète) – David

0

Le chaînage d'exception pour ServletException est difficile. En fonction de l'implémentation du serveur Web et du cadre de développement Web utilisé, la chaîne peut utiliser la cause et/ou rootCause lors de l'exécution. Ce link l'explique très bien. Pour compliquer les choses, j'ai vu des exceptions où la cause pointe vers l'exception elle-même. est ici une méthode récursive, nous avons utilisé qui couvre toutes les bases pour ServletExceptions:

public static Throwable getDeepCause(Throwable ex) { 
    if (ex == null) { 
     return ex; 
    } 
    Throwable cause; 
    if (ex instanceof ServletException) { 
     cause = ((ServletException) ex).getRootCause(); 
     if (cause == null) { 
      cause = ex.getCause(); 
     } 
    } else { 
     cause = ex.getCause(); 
    } 
    if (cause != null && cause != ex) { 
     return getDeepCause(cause); 
    } else { 
     // stop condition - reached the end of the exception chain 
     return ex; 
    } 
}