SeamFramework.orgCommunity Documentation

Chapter 4. Seam Catch - Filtering Stack Traces

4.1. Introduction
4.2. ExceptionStackOutput
4.3. StackFrameFilter
4.4. StackFrameFilterResult
4.5. StackFrame

Stack traces are an everyday occurance for the Java developer, unfortunately the base stack trace isn't very helpful and can be difficult to understand and see the root problem. Catch helps make this easier by

The great part about all of this: it's done without a need for CDI! You can use it in a basic Java project, just include the Seam Catch jar. There are four classes to be aware of when using filtering

There's not much to this, pass it the exception to print and the filter to use in the constructor and call printTrace() which returns a string -- the stack trace (filtered or not). If no filter is passed to the constructor, calling printTrace() will still unwrap the stack and print the root cause first. This can be used in place ofThrowable#printStackTrace(), provided the returned string is actually printed to standard out or standard error.

This is the workhorse interface that will need to be implemented to do any filtering for a stack trace. It only has one method:public StackFrameFilterResult process(StackFrame frame). Further below are methods on StackFrame andStackFrameFilterResult. Some examples are included below to get an idea what can be done and how to do it.

This is a simple enumeration of valid return values for the process method. Please see the API docs for definitions of each value.

This contains methods to help aid in determining what to do in the filter, it also allows you to completely replace the StackTraceElement if desired. The four "mark" methods deal with marking a stack trace and are used if "folding" a stack trace is desired, instead of dropping the frame. The StackFrame will allow for multiple marks to be set. The last method,getIndex(), will return the index of the StackTraceElement from the exception.

Example 4.1. Terminate

 @Override

public StackFrameFilterResult process(StackFrame frame) {
   return StackFrameFilterResult.TERMINATE;
}

This example will simply show the exception, no stack trace.


Example 4.2. Terminate After

@Override

public StackFrameFilterResult process(StackFrame frame) {
   return StackFrameFilterResult.TERMINATE_AFTER;
} 

This is similar to the previous example, save the first line of the stack is shown.


Example 4.3. Drop Remaining

@Override

public StackFrameFilterResult process(StackFrame frame) {
   if (frame.getIndex() >= 5) {
      return StackFrameFilterResult.DROP_REMAINING;
   }
   return StackFrameFilterResult.INCLUDE;
}

This filter drops all stack elements after the fifth element.


Example 4.4. Folding

@Override

public StackFrameFilterResult process(StackFrame frame) {
   if (frame.isMarkSet("reflections.invoke")) {
      if (frame.getStackTraceElement().getClassName().contains("java.lang.reflect")) {
         frame.clearMark("reflections.invoke");
         return StackFrameFilterResult.INCLUDE;
      }
      else if (frame.getStackTraceElement().getMethodName().startsWith("invoke")) {
         return StackFrameFilterResult.DROP;
      }
   }
   if (frame.getStackTraceElement().getMethodName().startsWith("invoke")) {
      frame.mark("reflections.invoke");
      return StackFrameFilterResult.DROP;
   }
   return StackFrameFilterResult.INCLUDE;
}

Certainly the most complicated example, however, this shows a possible way of "folding" a stack trace. In the example any internal reflection invocation methods are folded into a single java.lang.reflect.Method.invoke() call, no more internal com.sun calls in the trace.