web-dev-qa-db-fra.com

Java - recherche la première cause d'une exception

Je dois vérifier si une exception est causée par un problème de base de données. Je reçois une exception et vérifie si sa cause contient la chaîne "ORA" et je la renvoie (quelque chose comme "ORA-00001"). Le problème ici est que l'exception que je reçois est imbriquée dans d'autres exceptions, donc si je ne trouve pas s'il s'agit d'une exception Oracle, je dois vérifier la cause de cette exception et ainsi de suite. Existe-t-il une façon plus propre de procéder? Existe-t-il un moyen de connaître la première cause (l'exception profondément imbriquée) d'une exception donnée?

Mon code actuel ressemble à ceci:

private String getErrorOracle(Throwable e){
        final String Oracle = "ORA";
        if (e.getCause() != null && e.getCause().toString().contains(Oracle)){
            return e.getCause().toString();
        } else if(e.getCause() != null){
            return getErrorOracle(e.getCause());
        } else {
            return null;
        }
    }
34
Averroes

Parcourez simplement la chaîne d'exceptions jusqu'à ce que vous arriviez à une exception sans cause, puis renvoyez simplement ce message, si vous voulez le dernier.

Votre fonction n'aura la première cause que s'il y en a une.

Vous voudrez peut-être chercher à trouver la première cause dans votre package, car la plus profonde réelle peut être une exception Oracle, ce qui est utile, mais à moins que vous ne puissiez voir où vous avez créé le problème, vous aurez du mal à le résoudre.

15
James Black

Dans l'intérêt de ne pas réinventer la roue, si vous utilisez Apache Commons Lang , alors regardez ExceptionUtils.getRootCause () .

Vaut-il la peine d'inclure une bibliothèque juste pour ça? Peut être pas. Mais si vous l'avez déjà sur votre chemin de classe, il est là pour vous, et notez qu'il fait certaines choses qu'une implémentation `` naïve '' pourrait ne pas faire (par exemple, traiter les cycles dans la chaîne de cause ... ugh!)

82
Cowan

Si vous êtes déjà sur Guava alors Throwables.getRootCause () vient à la rescousse.

16
Nándor Krácser

Probablement un peu exagéré pour votre utilisation mais je pense qu'il est plus propre (et réutilisable)

interface ThrowablePredicate {
    boolean accept(Throwable t);
}

public OracleErrorThrowablePredicate implements ThrowablePredicate {
    private static final ORA_ERR = "ORA";

    public boolean accept(Throwable t) {
        return t.toString().contains(ORA_ERR);
    }
}


public class CauseFinder {

   private ThrowablePredicate predicate;

   public CauseFinder(ThrowablePredicate predicate) {
      this.predicate = predicate;
   }

   Throwable findCause(Throwable t) {
      Throwable cause = t.getCause();

      return cause == null ? null 
         : predicate.accept(cause) ? cause : findCause(cause)
   }
}


// Your method
private String getErrorOracle(Throwable e){
    return new CauseFinder(new OracleErrorThrowablePredicate()).findCause(e);
}
4
vickirk

Je pense que toute erreur lancée par Oracle sera enveloppée dans une exception SQLEx (quelqu'un doit me corriger s'il se trompe). Une fois que vous avez accédé à la SQLException, vous devriez pouvoir appeler

getErrorCode () Récupère le code d'exception spécifique au fournisseur pour cet objet SQLException.

Faites-moi savoir si cela fonctionne car je ne l'ai jamais essayé :-)

Karl

2
Karl

Vous pouvez améliorer la vérification de votre code pour SQLException

import Java.sql.SQLException;

private static final String Oracle = "ORA";

public String doHandle(Throwable t) {
    if (t.getClass().isAssignableFrom(SQLException.class)) {
    SQLException e = (SQLException) t;
    int errCode = e.getErrorCode();
    String state = e.getSQLState();
    String msg = e.getMessage();
    if (msg.contains(Oracle)) {
        return msg;
        }
    } else {
        if (t.getCause() != null) {
            return this.doHandle(t.getCause());
            }
        }
    return "";
}

En outre, je pense que dans Oracle "errCode" contient le numéro associé à ORA-nnnn

2
JuanZe

vous pouvez utiliser le getStackTrace () de la classe Throwable. Cela vous donnerait la pile de StackTraceElements avec laquelle travailler. Vous pouvez parcourir le StackTraceElements [] pour rechercher la chaîne "ORA".

Faites-moi savoir si vous avez besoin d'un exemple.

0
coolest_head