Java: How to convert the full stack trace of an Exception to a string for printing or logging – including nested exceptions (“caused by”)

If you want to log an exception and want to include the full stack trace with all nested exceptions, you should use the printStackTrace method from Throwable and get the result as a String:

StringWriter sw = new StringWriter();
pThrowable.printStackTrace(new PrintWriter(sw));
String fullStackTrace = sw.toString();

Now you can log the full stack trace and won’t miss nested exception any more.

Example: Nested exceptions:

import java.io.PrintWriter;
import java.io.StringWriter;

public class Test
{
    /**
     * Convert a stack trace to a string for printing or logging
     * including nested exception ("caused by")
     * @param pThrowable
     * @return
     */
    static String convertStackTraceToString(Throwable pThrowable)
    {
        if (pThrowable == null) {
            return null;
        }
        else {
            StringWriter sw = new StringWriter();
            pThrowable.printStackTrace(new PrintWriter(sw));
            return sw.toString();
        }
    }

    public static void main(String[] args)
        throws InterruptedException
    {
        try {
            // Create and throw 3 nested exceptions:
            Exception r1 = new RuntimeException("1. Expection");
            Exception r2 = new RuntimeException("2. Exception", r1);
            throw new RuntimeException("3. Exception", r2);
        }
        catch(Exception e) {
            System.out.println("convertStackTraceToString(e): -----------------------------------------");
            System.out.println(convertStackTraceToString(e));

            System.out.println("printStackTrace(e): -----------------------------------------");
            Thread.sleep(100); // Avoids timing side effect with println and printStackTrace
            e.printStackTrace();
        }
    }
}

Console Output:

>>> convertStackTraceToString(e): -----------------------------------------
java.lang.RuntimeException: 3. Exception
    at ThrowablePrintTest.main(ThrowablePrintTest.java:37)
Caused by: java.lang.RuntimeException: 2. Exception
    at ThrowablePrintTest.main(ThrowablePrintTest.java:36)
Caused by: java.lang.RuntimeException: 1. Expection
    at ThrowablePrintTest.main(ThrowablePrintTest.java:35)

>>> printStackTrace(e): -----------------------------------------
java.lang.RuntimeException: 3. Exception
    at ThrowablePrintTest.main(ThrowablePrintTest.java:37)
Caused by: java.lang.RuntimeException: 2. Exception
    at ThrowablePrintTest.main(ThrowablePrintTest.java:36)
Caused by: java.lang.RuntimeException: 1. Expection
    at ThrowablePrintTest.main(ThrowablePrintTest.java:35)
Advertisements

PL/SQL: Sleep without using DBMS_LOCK

If you want to wait in your PL/SQL program (“sleep”) you may want to use the procedure “SLEEP” from the package “DBMS_LOCK“. While this function does exactly what you want, your DBA may not grant you access to this package, because it contains some other mighty and dangerous procedures.

But there is help! Here are some valid alternatives:

Option 1: APEX_UTIL.sleep

If APEX is installed you can use the procedure “PAUSE” from the publicly available package APEX_UTIL.

Example – “Wait 5 seconds”:

SET SERVEROUTPUT ON ;
BEGIN
    DBMS_OUTPUT.PUT_LINE('Start ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
    APEX_UTIL.PAUSE(5);
    DBMS_OUTPUT.PUT_LINE('End   ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
END;
/

Option 2: java.lang.Thread.sleep

An other option is the use of the method “sleep” from the Java class “Thread”, which you can easily use through providing a simple PL/SQL wrapper procedure:

CREATE OR REPLACE PROCEDURE SLEEP (P_MILLI_SECONDS IN NUMBER) 
AS LANGUAGE JAVA NAME 'java.lang.Thread.sleep(long)';

Note: Please remember, that “Thread.sleep” uses milli seconds!

Example – “Wait 5 seconds”:

SET SERVEROUTPUT ON ;
BEGIN
    DBMS_OUTPUT.PUT_LINE('Start ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
    SLEEP(5 * 1000);
    DBMS_OUTPUT.PUT_LINE('End   ' || to_char(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
END;
/