This page shows the source for this entry, with WebCore formatting language tags and attributes highlighted.
Title
Missing ognl?
Description
<n>This article was originally published on the <a href="http://blogs.encodo.ch/news/view_article.php?id=19"><b>Encodo Blogs</b></a>. Browse on over to see more!</n>
<hr>
Every once in a while, when adding a new component to or changing an existing one on a Tapestry page, you'll make a mistake. Most of the time, the exception handler page is pretty good; sometimes the exception can be quite confusing. For example, suppose we have a custom component with a single property:
<code>
package com.encodo.blogs.samples;
class CustomComponent extends BaseComponent {
public abstract SomeObject getCustomParameter();
}
</code>
To use this component in a page, you just write the following:
<code>
</code>
This <i>looks</i> ok<fn>, but when loaded in a browser causes the following error:
<div class="error"><c>org.apache.tapestry.BindingException</c> Error converting value for template parameter customParameter: No type converter for type <c>com.encodo.blogs.samples.SomeObject</c> is available.</div>
With this kind of error message, you're ready to start imagining all sorts of horrible things:
<ul>
Is something declared with the wrong type? No ... there's no type declaration for properties; Tapestry reads the type from the class field.
Is there a data squeezer problem? Is this class not supported? Does it need to be <c>Serializable</c>?
Is Tapestry trying to store persist the property to the session or cookie? Not likely, but who knows?
</ul>
The missing magic in the above example is <c>ognl:</c>. Tapestry uses the <a href="http://www.ognl.org/">Object-Graph Navigation Language</a> to process references to Java code in its templates and page/component definitions. However, the default for HTML attributes is <c>literal:</c>, which performs no extra processing. Since <c>ognl:</c> is missing, <c>obj</c> is simply a string, which Tapestry cannot convert to <c>SomeObject</c>. To fix the problem, just add <c>ognl:</c> before the object reference, like this:
<code>
<span class="highlight">ognl:</span>obj"/>
</code>
This being such a common error, it would be nice if Tapestry could do some common-sense handling of it to help emit a better message. One simple way is to specify what, exactly, it was trying to convert to the target object. Compare to the following error message:
<div class="error"><c>org.apache.tapestry.BindingException</c> Error converting <span class="highlight">"obj" (interpreted as "literal:obj")</span> for template parameter customParameter: No type converter for type <c>com.encodo.blogs.samples.SomeObject</c> is available.</div>
Once the developer sees how Tapestry interpreted the component declaration, it's much easier to pinpoint the error. Now, for purely asthetic reasons, let's make this message more user-friendly:
<div class="error"><c>org.apache.tapestry.BindingException</c>: The value for template parameter "customParameter", given as "obj" and interpreted as "literal:obj", could not be converted to <c>com.encodo.blogs.samples.SomeObject</c>.</div>
That error message, at least, should no longer inspire panic and desperate restarts of the testing server.
<hr>
<ft>Unless you're an old Tapestry hand and have already spotted the error, in which case you should be <i>writing</i> these tips, not <i>reading</i> them.</ft>
<n>Using Java 1.5</n>