Cocoon is a powerful framework that allows you to quickly write sophisticated web applications without writing a single line of Java.
Now the problem is that errors that appear in a Cocoon applications produce Java exceptions, which must then be correlated to the non-Java source file that led the error to appear: XSLT, sitemap, templates, form definition, JavaScript code for the flowscript, etc.
Up to now, this wasn't always an easy task, and that made Cocoon look like a complicated beast. These times are over: I've started adding " Cocoon stacktraces" to the beast last monday!
Here's what the Cocoon error page provided in the sample webapp looks like now (in this sample, an unknow form widget is referenced in a page template):
But wait, there's more! This kind of error page should not be deployed in production, as it's very unfriendly to application users. Now won't we loose this precious information? No, because it's also in the Java stacktrace!
The located exceptions in Cocoon print hybrid stacktraces, starting with file locations and then the regular Java method call stack:
org.apache.cocoon.util.location.LocatedRuntimeException: Repeater "contacts contains no widget with id "first-name".All this stuff relies on a few new classes to handle locations, locatable objects and located exceptions.
at file:/Users/sylvain/dev/apache.org/cocoon/branches/BRANCH_2_1_X/build/webapp/samples/blocks/forms/forms/dynamicrepeater.xml:27:32
at resource://org/apache/cocoon/forms/generation/jx-macros.xml:60:117
at file:/Users/sylvain/dev/apache.org/cocoon/branches/BRANCH_2_1_X/build/webapp/samples/blocks/forms/forms/dynamicrepeater_template.xml:59:85
at resource://org/apache/cocoon/forms/generation/jx-macros.xml:231:26
at file:/Users/sylvain/dev/apache.org/cocoon/branches/BRANCH_2_1_X/build/webapp/samples/blocks/forms/forms/dynamicrepeater_template.xml:50:34
at resource://org/apache/cocoon/forms/generation/jx-macros.xml:34:23
at file:/Users/sylvain/dev/apache.org/cocoon/branches/BRANCH_2_1_X/build/webapp/samples/blocks/forms/forms/dynamicrepeater_template.xml:41:97
at org.apache.cocoon.forms.formmodel.Repeater.generateWidgetLabel(Repeater.java:332)
at org.apache.cocoon.forms.generation.JXMacrosHelper.generateRepeaterWidgetLabel(JXMacrosHelper.java:185)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.apache.commons.jexl.util.introspection.UberspectImpl$VelMethodImpl.invoke(UberspectImpl.java:268)
at org.apache.commons.jexl.parser.ASTMethod.execute(ASTMethod.java:61)
at org.apache.commons.jexl.parser.ASTReference.execute(ASTReference.java:68)
at org.apache.commons.jexl.parser.ASTReference.value(ASTReference.java:50)
at org.apache.commons.jexl.ExpressionImpl.evaluate(ExpressionImpl.java:86)
at org.apache.cocoon.generation.JXTemplateGenerator.getNode(JXTemplateGenerator.java:896)
at org.apache.cocoon.generation.JXTemplateGenerator.getNode(JXTemplateGenerator.java:854)
at org.apache.cocoon.generation.JXTemplateGenerator.execute(JXTemplateGenerator.java:2810)
...
Nice, isn't it? Bertrand likes it, and so does Ugo :-)