Sunday June 19, 2005 As JSF is gaining popularity, more JSF components are being written. In fact TopCoder is running a competition on writing components. (Sun is a sponsor.)
However, some of the components written work, but do not work well in tools like Creator, or do not work well when used in conjunction with CSS. In this blog entry I will provide some hints that will make sure your components do not fall in that category.
How to actually write a JSF component is covered in many places; it's not hard. You need to write 3-4 classes, plus write a .tld file and a faces-config file with some information about your component.
Here's a document which takes you through this process.
However, there are some additional Rules You Should Follow when you write your component.
These rules serve two purposes:
Here they are:
startElement,
endElement and writeAttribute methods. Do NOT
write out markup by simply streaming out HTML bytes linearly using the
write method. There is one minor exception to this rule: some components
need to emit HTML provided by the user, such as the HtmlOutputText
component when its Escape property is set to false. In this limited
scenario you should use write.
ResponseWriter. E.g. if your UIComponent is a PanelGrid,
and you want to emit <table><tr><td>... you would
use
writer.startElement("table", gridpanel);
writer.startElement("tr", gridpanel);
writer.startElement("td", gridpanel);
style property, which will render
to a style attribute on the rendered HTML markup.
This will allow tools like Creator to position and size the component (using CSS).
It is vital that you remember to replicate this style attribute on your top level
rendered HTML tag. However, there are some complications...
<h:commandButton style="width: 100px"/> in the
JSP, you would render <input type="submit" style="width: 100px"/>
<script> tag before it renders its one visual
element, <table>, and then perhaps another non visual element, an
<input> of type hidden.
In this case, simply emit the <script>, then emit the
<table> with the style property value from the JSF component,
and finally emit the hidden <input>.
<span>
or a <div>. (Use span only if all the children being rendered are
inline elements.) The style property should be placed only on this outer, wrapping
<span> or <div>.
value is a required
property, don't throw a configuration exception just because it's null when you're rendering!
If you really want your component to alert the user to the problem, I suppose it's okay to
throw an exception when the component is used at runtime, but at designtime, it's quite normal
for a component not to be correctly configured yet - after all, the user may just have dropped
the component and is about to configure it. If necessary, you can have code in your renderer which
checks if the component renderer is being used at designtime:
if (java.beans.Beans.isDesignTime()) {
// Designtime - better render error handling here
...
} else {
// Runtime - throw your exceptions if you must
...
}
One thing you might consider doing is having the component render exactly the problem message
to the user. As an example, in Creator, if you drop the Message component, it will
tell you if it is not bound to anything (since the for property is null, so the
component is not yet configured.)
Once you have written your component you should package it up such that it can easily be imported into Creator and used out of the box by your users. That is also covered in the component library article I linked to earlier.
Please let me know if you develop components that work well with Creator!
(2005-06-19 12:07:31.0) Permalink Comments [1]
Posted by Abdurrahman on October 05, 2005 at 12:30 PM PDT #