Michael HönnigMichael Hönnig
Fast täglich, meist beim Debuggen, aber auch für Logfiles, muss ein Java-Entwickler die ursprüngliche Ursache einer Exception herausfinden. So nützt einem die Meldung Can't commit because the transaction is in aborted state, die ein Applikationsserver z.B. nach der Verletzung eines Datenbank-Constraints liefern würde, recht wenig, doch das tief darin verborgene SQLSTATE[23505] ERROR: duplicate key violates unique constraint ... gibt schon einen sehr guten Hinweis darauf, was eigentlich passiert ist. Hier nur eine Methode, welche versucht, diese Information aus der Kette von Exceptions herauszufinden und sie in einer String-Message darzustellen, die dann z.B. im Log ausgegeben werden könnte:

import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
...

	public static String extractCauseMessage(Exception e)
	{
		if ( e.getMessage() != null ) 
			return e.getMessage();
		else if (e instanceof InvocationTargetException )
		{
			String sqlState = null;
			InvocationTargetException ite = 
			        (InvocationTargetException) e;
			Throwable cause = ite.getCause();
			Throwable prev = null;
			while ( cause != null && cause != prev )
			{
				prev = cause;
				cause = prev.getCause();
				if ( (cause == null || cause == prev ) && 
						prev instanceof SQLException )
				{
					SQLException sqlExc = 
					        (SQLException) prev;
					sqlState = sqlExc.getSQLState();
					cause = sqlExc.getNextException();
				}
			}
			if ( cause == null )
				cause = prev;
			if ( cause != null )
				return composeMessage( sqlState, 
					cause.getMessage() );
			return composeMessage( sqlState, 
					ite.getTargetException().getMessage() );
		}

		return e.getClass() + " without detail message";	
	}
	
	private static String composeMessage(
					String sqlState, String message)
	{
		if ( sqlState != null )
			return "SQLSTATE[" + sqlState + "] " + message;
		return message;
	}