77

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Enrique San Martín
  • 2,202
  • 7
  • 30
  • 51
  • 3
    Gahhhh... so many runs and processes and invokes and executes and dos... http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html – amara Jun 03 '10 at 22:57
  • 1
    see: http://stackoverflow.com/questions/1167888/howto-increase-lines-of-java-stack-trace-dump and http://stackoverflow.com/questions/1043378/print-full-call-stack-on-printstacktrace and http://stackoverflow.com/questions/437756/how-do-i-stop-stacktraces-truncating-in-logs to list just a few – akf Jun 03 '10 at 23:18
  • Hi! Look at http://people.inf.elte.hu/balopat/bug.html I generated you, hover over the circles, I hope it'll help you understand what `... 23 more` means :) Basically the answers are true, this is only an illustration. – Balint Pato Jun 22 '10 at 14:56
  • Does this answer your question? [Print full call stack on printStackTrace()?](https://stackoverflow.com/questions/1043378/print-full-call-stack-on-printstacktrace) – Philippe Cloutier May 18 '23 at 15:24

4 Answers4

45

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.

Community
  • 1
  • 1
mikej
  • 65,295
  • 17
  • 152
  • 131
42

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
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Well, now when a long time has passed i read that the answers was very simple, it's was a jar hell problem (or in this case that is missing the jar with the DB2 driver. Its in the: "Caused by: java.lang.ClassNotFoundException: COM.ibm.db2.jcc.DB2Driver" – Enrique San Martín Aug 27 '13 at 12:35
16

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.

mdma
  • 56,943
  • 12
  • 94
  • 128
6

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();
        }
    }
}
arcamax
  • 610
  • 1
  • 7
  • 14
  • You could use a `Reader` to read through `printStackTrace` output till it hits _Caused by_ then get the cause and print its stack trace (looking for next _Caused by_)... and recursively repeat this process until there are no more stack traces. That way you don't have to build your own custom stacktrace formatter - you get to use what's already available `:)` – ADTC Aug 27 '13 at 10:28
  • 1
    Your code is working well. To send the trace to system.out, I just add `BufferedWriter logWriter = new BufferedWriter(new OutputStreamWriter(System.out));` and at the end : `logWriter.flush();` – Ben Feb 27 '18 at 16:44