RE: [coldbox:16249] [coldbox-3.5.2] Getting Stack Trace Array from ExceptionBean

35 views
Skip to first unread message

br...@bradwood.com

unread,
Oct 15, 2012, 5:56:53 PM10/15/12
to col...@googlegroups.com
You're correct that the ColdBox Exception object is duplicating the actual error object on init which is converting it from a Java Exception object to a simple struct. 

The equivilant data is accessible with ExceptionBean.getStackTrace() but that is going to return to string, not an array of java.lang.StackTraceElement objects.  If all your legacy code is doing is looping over the array and calling toString on the StackTraceElements, it would be easiest to just get the string from the ExceptionBean anyway, but I understand that you'd have to touch your legacy code to accept the string instead.

I'll be honest, I'm not sure why we duplicate the error struct.  It may have to do with asynchronous logging but that's just a guess.  I'd say you have 3 options (ranked in the order of what I would recommend):
  1. Modify the legacy code to use the StackTrace string (and hope there's not a good reason why it was using getStackTrace())
  2. Modify the ExceptionBean not to duplicate (and hope there's not a good reason why it is doing that)
  3. Decorate the ExceptionBean and take the StackTrace string and build your own array of java.lang.StackTraceElement objects out of it to fake a getStackTrace() method back in.  (This is possible, but a messy last resort in my opinion)
Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: br...@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com 


-------- Original Message --------
Subject: [coldbox:16249] [coldbox-3.5.2] Getting Stack Trace Array from
ExceptionBean
From: Joel Watson <existd...@gmail.com>
Date: Mon, October 15, 2012 12:16 pm
To: col...@googlegroups.com

I'm trying to integrate my ColdBox site error logging/management with an existing, non-CB system's error logging.

In a part of the non-CB system's code, there is a bit where the code attempts to retrieve an array of stack trace elements by using the [exception].getStackTrace(). 
I've noticed that if I try to pass through the exceptionStruct from ExceptionBean, I get a "getStackTrace()" method cannot be found" error.

I am assuming this is because instance.exceptionStruct in ExceptionBean is being duplicated from the original CF error structure.

My question is whether anyone has run into this issue and can propose a work-around outside of modifying ExceptionBean to store a reference to the original CF error structure.

I do have access to the non-CB system code, but I'd prefer not to have to modify it if possible.

I appreciate anyone's thoughts or suggestions--thanks!
--
--
You received this message because you are subscribed to the Google Groups "ColdBox Platform" group.
To post to this group, send email to col...@googlegroups.com
To unsubscribe from this group, send email to coldbox-u...@googlegroups.com
For more options, visit this group at http://groups-beta.google.com/group/coldbox
For News, visit http://blog.coldbox.org
For Documentation, visit http://wiki.coldbox.org
 
 
 

Exist~Dissolve

unread,
Oct 15, 2012, 6:09:43 PM10/15/12
to col...@googlegroups.com
Hi Brad--

Thanks for the suggestions. On #2, what are your thoughts on adding the actual error object to the ExceptionBean? That way, the duplicate can still occur but the exception object will still be available as well.

#3, though messy, is intriguing to me as well. I might have to explore that a bit, just for fun :)

Thanks again!
--
The only thing we learn from history is that we learn nothing from history.

http://singularityconcepts.com

br...@bradwood.com

unread,
Oct 15, 2012, 6:23:58 PM10/15/12
to col...@googlegroups.com
Thanks for the suggestions. On #2, what are your thoughts on adding the actual error object to the ExceptionBean? That way, the duplicate can still occur but the exception object will still be available as well.

Well, if you are going to leave in the original error object, I wouldn't see any point in leaving the duplicated version as well.

#3, though messy, is intriguing to me as well. I might have to explore that a bit, just for fun :)

Yes, the reason it took me a bit to respond is because I actually got off in the weeds playing with that option just to see if you could do it.  I eventually got caught up on my inferior grasp of regex.  Basically, I was looping over the string stackTrace as a list with chr(10)&chr(13) as the delimiter.  Then trying (unsuccessfully) to break out each line item which looks something like this:
coldfusion.runtime.CfJspPage._get(CfJspPage.java:377)

into its separate parts which would look something like this:

className: coldfusion.runtime.CfJspPage
methodName: _get
fileName: CfJspPage.java
lineNumber: 377

You can create a StackTraceElement like so once you have all the peices:
createObject("java", "java.lang.StackTraceElement").init("declaringClass","methodName","fileName", lineNumber)

Like I said, I would consider that a last resort, but if you wanted to keep from touching the legacy site at all costs, and didn't want to fiddle with core ColdBox, it should work. 

Joel Watson

unread,
Oct 16, 2012, 10:01:39 AM10/16/12
to col...@googlegroups.com
Hey Brad--

I played around a bit with the regex option, and I think I've got something working. My knowledge of regex is quite limited, so there are probably better ways to do this. However, I've thrown a number of different kinds of errors at this, and it seems to be working. Here's the code if anyone is interested/would like to suggest improvements.

// array for all our stack trace elements
var tracers = [];
// loop over the list-to-array converted stacktrace
for( element in stacktrace ) {
    // create the regex pattern
    var pattern = CreateObject( "java", "java.util.regex.Pattern" );
       // compile the pattern; using 4 "or" matchers so we can get all the pieces we need in one pass
       pattern.Compile( "(?<=at ).*(?=\..*\()|(?<=:).*(?=\)$)|(?<=\().*(?=:)|(?<=[a-zA-Z0-9]\.).*(?=\()" );
   
    // find the matches
    var matcher = pattern.Matcher( element );
    // create an array to store the items in our matched set
    var tracer =[];
    // for each match, add to our temp array
    while( matcher.Find() ) {
        arrayAppend( tracer, matcher.group() );
    }
    if( arrayLen( tracer ) == 4 ) {
        arrayAppend( tracers, createObject( "java", "java.lang.StackTraceElement" ).init( tracer[1], tracer[2], tracer[3], tracer[4]) );
    }
    else {
        // do some kind of handling here
    }
}


Joel Watson

unread,
Oct 16, 2012, 10:11:03 AM10/16/12
to col...@googlegroups.com
Hmm, sorry, pattern should be:

pattern = CreateObject( "java", "java.util.regex.Pattern" ).Compile( "(?<=at ).*(?=\..*\()|(?<=:).*(?=\)$)|(?<=\().*(?=:)|(?<=[a-zA-Z0-9]\.).*(?=\()" );
Reply all
Reply to author
Forward
0 new messages