cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sylvain Wallez <>
Subject Re: Cocoon Stack Traces
Date Mon, 12 Jan 2004 09:06:56 GMT
Christopher Oliver wrote:

> I started looking into how I could get a meaningful stack trace (with 
> location information) spanning (possibly nested) invocations of the 
> sitemap, flowscript, and JXTemplateGenerator. Currently using the JVM 
> stack trace produces a poor result. Although location information is 
> available it isn't provided according to a consistent model. Rhino 
> stores a JS stack trace in a JavaScriptException. JXTemplateGenerator 
> stores its execution stack trace in a sequence of nested 
> SAXParseExceptions. The Sitemap processor currently doesn't seem to 
> produce an execution stack trace, but ProcessingNode's have location 
> information so it should be possible. In addition, 
> javax.xml.transform.TransformerException has location information. 
> o.a.c.ProcessingException gives special treatment to SAXParseException 
> and TransformerException and adds location information to its own 
> stack trace (but only for one level - it doesn't included nested 
> SAXParseException's, for example). There seem to be various other 
> hacks to attempt to include location information in the exception 
> message or stack trace.
> The idea is to allow a Cocoon processing element that operates on 
> source code (sitemap, flowscript, jxtemplate, etc...) to provide 
> location information about the execution stack of that processing 
> element when the exception occurred (see also  
> To accomplish this I chose not to use the JVM exception stack trace 
> but instead to store a "Cocoon" stack trace in the current object 
> model. I added the following to the class o.a.c.Cocoon:
> public class Cocoon {
>    ....
>    public interface StackTraceElement {
>        public String getComponent();
>        public String getMessage();
>        public String getMethod();
>        public String getURI();
>        public int getLineNumber();
>        public int getColumnNumber();
>    }
>    public static void addCocoonStackTrace(
>                                           Map objectModel,
>                                           String message,
>                                           String component,
>                                           String method,
>                                           String uri,
>                                           int lineNumber,
>                                           int columnNumber);
>    public static ArrayList /* of StackTraceElement */ 
> getStackTrace(Map objectModel)
> }
> I  added calls to addCocoonStackTrace() in JXTemplateGenerator, 
> FOM_JavaScriptInterpreter, and in and
> With a method like the following:
>   private static void dumpStackTrace(Map objectModel) {


> I was able to produce the following output:
> jxtemplate: No pointer for xpath: $blah (at 
> file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/screens/getNumberA.xml, 
> Line 26.13)
> sitemap: (mount at 
> file:/C:/cocoon4/build/webapp/samples/flow/sitemap.xmap:38:68)
> sitemap: (mount at 
> file:/C:/cocoon4/build/webapp/samples/sitemap.xmap:154:65)
> sitemap: (mount at file:/C:/cocoon4/build/webapp/sitemap.xmap:738:66)
> flowscript: (at 
> resource://org/apache/cocoon/components/flow/javascript/fom/fom_system.js, 
> Line 4)
> flowscript: (getNumber at 
> file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/../calc/calc.js, 
> Line 31)
> flowscript: (calculator at 
> file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/../calc/calc.js, 
> Line 11)
> sitemap: (call at 
> file:/C:/cocoon4/build/webapp/samples/flow/jxcalc/sitemap.xmap:48:42)
> sitemap: (mount at 
> file:/C:/cocoon4/build/webapp/samples/flow/sitemap.xmap:38:68)
> sitemap: (mount at 
> file:/C:/cocoon4/build/webapp/samples/sitemap.xmap:154:65)
> sitemap: (mount at file:/C:/cocoon4/build/webapp/sitemap.xmap:738:66)
> It seems straightforward to hook this into Cocoon's error reporter.

/me thinks it's great!

Some low-level remarks, however:

- we need a "popStackFrame()" method, since once a component has been 
executed successfully and execution continues in its following siblings, 
it should no longer appear in the stack trace

- is the "message" parameter really needed? It's only meaningful for the 
statement where the error occured, and will be present in the Java 
exception that is raised.

- consequently, to minimize performance overhead, I think it would be 
better to pass a single StackTraceElement parameter (or 
"CocoonStackFrame"?), since these objects can be pre-allocated at 
script/template/sitemap load time and are immutable afterwards.

- I don't like much putting this on the "Cocoon" class. What about 
creating a "org.apache.cocoon.util.debug" package holding the various 
classes that will certainly follow this first enhancement. I'm thinking 
to a global debugger that may be built using these stack frames.

> In the process of doing this, however, I found that pipeline 
> processing doesn't actually occur during sendPage*(). Instead, it 
> simply sets a flag to redirect to the passed uri and returns. Pipeline 
> processing actually occurs after the flowscript has completed. This is 
> also a problem for the solution proposed here to release components 
> after pipeline processing: 
> To solve both problems I modified the implementation of sendPage*() to 
> call the sitemap processor recursively instead. It seems to work. Does 
> anyone know of a problem with this approach?

Or we can also have internal redirects be handled at the location where 
they occur instead of raising this flag. The purpose of going through 
this flag was to both ensure a single handling location (this can be 
achieved by other means) and cut down the length of java stack traces.


Sylvain Wallez                                  Anyware Technologies 
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Orixo, the opensource XML business alliance  -

View raw message