How to read the full stacktrace in Java where it says e.g. "... 23 more"

JavaStack Trace

Java Problem Overview


I want to read the full stack trace of an exception that I capture.

For example:

org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.ibm.db2.jcc.DB2Driver'
 at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1136)
 at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
 at com.azurian.lce.usuarios.ConnectionManager.getConnection(ConnectionManager.java:65)
 at com.azurian.lce.usuarios.db2.UsuarioDAOImpl.autenticar(UsuarioDAOImpl.java:101)
 at com.azurian.lce.usuarios.UsuarioServiceImpl.autenticar(UsuarioServiceImpl.java:31)
 at com.azurian.lce.web.admin.actions.LoginAction.execute(LoginAction.java:49)
 at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
 at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
 at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
 at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
 at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: COM.ibm.db2.jcc.DB2Driver
 at java.net.URLClassLoader$1.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClassInternal(Unknown Source)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Unknown Source)
 at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1130)
 ... 23 more

I want to read the "... 23 more" to see where the exception comes from.

Java Solutions


Solution 1 - Java

BalusC is right. See here: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Throwable.html#printStackTrace()

In particular:

> Note the presence of lines containing > the characters "...". These lines > indicate that the remainder of the > stack trace for this exception matches > the indicated number of frames from > the bottom of the stack trace of the > exception that was caused by this > exception (the "enclosing" exception). > This shorthand can greatly reduce the > length of the output in the common > case where a wrapped exception is > thrown from same method as the > "causative exception" is caught.

What this means in your example is that:

BasicDataSource.java line 1136 caught the ClassNotFoundException thrown on line 1130 and reraised it as a SQLNestedException. Hence the remainder of the stacktrace for the ClassNotFoundException matches the SQLNestedException above and the stacktrace is printed in this more concise format.

Solution 2 - Java

The answer is simple, those lines are already in the stacktrace :)

 at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
 at com.azurian.lce.usuarios.ConnectionManager.getConnection(ConnectionManager.java:65)
 at com.azurian.lce.usuarios.db2.UsuarioDAOImpl.autenticar(UsuarioDAOImpl.java:101)
 at com.azurian.lce.usuarios.UsuarioServiceImpl.autenticar(UsuarioServiceImpl.java:31)
 at com.azurian.lce.web.admin.actions.LoginAction.execute(LoginAction.java:49)
 at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
 at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
 at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
 at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
 at java.lang.Thread.run(Unknown Source)

Basically, the following is happening in BasicDataSource#createDataSource():

try {
    Class.forName(driverClassName); // Line 1130
} catch (ClassNotFoundException e) {
    throw new SQLNestedException(e, "Cannot load JDBC driver class '" + driverClassName + "'"); // Line 1136
}

Solution 3 - Java

When the outer exception (SQLNestedException) wraps the inner exception (ClassNotFoundError) they are on the same thread, and so share a common base to their stack trace.

The (23 more...) shows where that common stack starts for the inner exception, which is also the place where the outer exception was thrown. So, whenever you see (XX more...), just look to the exception above to see the rest of the stack trace.

If you want to programmatically print out the stacktrace without the ellipsis for common traces, then you can use Throwable.getStackTrace() and print out all the elements yourself.

Solution 4 - Java

Try this out. This logic loops through the main exception and all the causes of it, till there is no more cause (cause == null) left to process. This way you can avoid the 23 more... message. I have not yet tested this yet, but i believe this should work out for you.

BTW - logWriter is a buffered writer. You may want to use System.out.print or any other logging API.

public static void debugError(final String message, final Throwable th) {
	final String logMessage = "[ERROR] - " + message;

	try {
		logWriter.write(logMessage);
		logWriter.newLine();

		// dump exception stack if specified
		if (null != th) {
			final StackTraceElement[] traces = th.getStackTrace();
			if (null != traces && traces.length > 0) {
				logWriter.write(th.getClass() + ": " + th.getMessage());
				logWriter.newLine();

				for (final StackTraceElement trace : traces) {
					logWriter.write("    at " + trace.getClassName() + '.' + trace.getMethodName() + '(' + trace.getFileName() + ':' + trace.getLineNumber() + ')');
					logWriter.newLine();
				}
			}

			Throwable cause = th.getCause();
			while (null != cause) {
				final StackTraceElement[] causeTraces = cause.getStackTrace();
				if (null != causeTraces && causeTraces.length > 0) {
					logWriter.write("Caused By:");
					logWriter.newLine();
					logWriter.write(cause.getClass() + ": " + cause.getMessage());
					logWriter.newLine();

					for (final StackTraceElement causeTrace : causeTraces) {
						logWriter.write("    at " + causeTrace.getClassName() + '.' + causeTrace.getMethodName() + '(' + causeTrace.getFileName() + ':' + causeTrace.getLineNumber() + ')');
						logWriter.newLine();
					}
				}

				// fetch next cause
				cause = cause.getCause();
			}
		}
	} catch (final IOException ex) {
		System.err.println(logMessage);

		if (null != th) {
			th.printStackTrace();
		}
	}
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEnrique San MartínView Question on Stackoverflow
Solution 1 - JavamikejView Answer on Stackoverflow
Solution 2 - JavaBalusCView Answer on Stackoverflow
Solution 3 - JavamdmaView Answer on Stackoverflow
Solution 4 - JavaarcamaxView Answer on Stackoverflow