14
I’ve been doing a fair amount of JSF component writing of late, and, invariably, I miss one or more “minor” details, causing my component to explode in spectacular fashion at runtime. What follows, then, is a check list for writing JSF components, with notes on the differences between the 1.1 and 1.2 versions of the specification.
Table of Contents
- Write the UIComponent Class
- Write the Renderer Class
- Write the Tag Class
- Write the Tag Library Description (.tld)
- Write the faces-config.xml Entries
- Write Facelets .taglib.xml File
- Conclusion
Write the UIComponent Class
- Extend the appropriate UIComponent class
- Define the following properties, changing the the package
com.footo your package, and the component name,Footo the name of your component:
- Define
public String getFamily () { return COMPONENT_TYPE; } - Define default constructor which calls
setRendererType(RENDERER_TYPE); - Define your properties and their getters and setters.
For 1.1:
For 1.2:
- Write the state saving and restoring code:
Write the Renderer Class
- Extend
Renderer - Implement
encodeBegin(), and/orencodeEnd(). Maybe others, depending on the component’s needs. All of my components, for example, have only need to extend one or the other.
Write the Tag Class
For 1.1
- Extend
UIComponentTag - Define all the properties as
String(?) - Define the following methods (where
Foois your component class):
For 1.2
- Extend
UIComponentElTag - Define properties as
ValueExpression - Define these methods (where Foo is your component class):
Write the Tag Library Description (.tld)
For 1.1:
For 1.2:
Write the faces-config.xml Entries
For 1.1:
For 1.2:
Write Facelets .taglib.xml File
Optional, but recommended
Name this /META-INF/<component-lib-name>.taglib.xml:
Conclusion
That, in a nutshell is what it takes to build a JSF component. I have left out, of course, many, many details in terms of “why” things should be done the way they are. I’m also cognizant that there are differing opinions on how to build a component (for instance, does every component need a separate Renderer? To date, all of my components do, but there’s no reason they have to). Once you throw Ajax into the mix, things get a bit more complicated. My hope is that this helps more people get started. Where there are omissions in these steps, my first suggestion is the excellent JSF: The Complete Reference by Chris Schalk and Ed Burns.
Popularity: 69% [?]
Thank you, this was very helpful to have everything in one place instead of searching everywhere else.
December 15th, 2006 | #
I hope it helps!
December 15th, 2006 | #
Hello,
This is great information. I am confused by your variable “bar” - I don’t see where that is declared.
Can you explain that?
Thanks.
December 26th, 2006 | #
DJF, Sorry about that. I hadn’t declared it (or, more accurately, just didn’t copy that from the component I was using as my model). In the component class in 1.1 and 1.2, “bar” would be of whatever type you intend it to be (String, Double, MyCustomClass, etc). In the tag, in 1.1, it’s always a String, and in 1.2, I always make it a ValueExpression. The conversion to the target type is done via the setProperties method for JSP (the tag class is ignored by Facelets, which sets properties on the component directly).
I’ve updated the sample code. I hope that helps!
December 26th, 2006 | #
Thanks - that helped clarify things. But I still am having issues getting my component spun up.
I am building a JAVA class that extends HtmlPanelGroup that will set properties on the children. I can’t seem to get this to load up? I don’t need a custom renderer and am only using the encodeBegin method. I am using facelets and don’t need JSP support
Do you have a sample JSF 1.2 custom component I could download to follow all the steps?
Thanks.
December 26th, 2006 | #
I think I have it working. I changed from where I was extending to simply be UIComponentBase and I think I am OK now.
Thanks
December 26th, 2006 | #
Good to hear. Currently, all my components are 1.1-compliant. I had planned to make them use the 1.2 API, but I had no technical reason to do so, so we decided to make them compatible with 1.1 and make them more widely usable.
Glad you got it working!
December 30th, 2006 | #
I am new to JSF, and custom JSF - is J2EE (Enterprise Edition) a requirement? I would like to run on Tomcat using J2SE if possible, but when I try to extend UIComponentTag I get compiler error “javax.servlet.jsp.tagext.JspIdConsumer cannot be resolved. It is indirectly referenced from required .class files”.
January 5th, 2007 | #
Brian, techincally, JSF 1.2, which you appear to be using is a part of the Java EE 5 spec. That does not mean, however, that EE is required. The error you are seeing is due to JSF 1.2’s dependence on the JSP 2.1 specification. Tomcat 5 only supports 2.0.
Off the top of my head, you have four options, two pretty easy, and two a little more drastic. The first of the easy ones is to use the JSF 1.1 jars. Since you’re extending UIComponentTag, and not UIComponentELTag, it appears you’re likely doing that anyway. The other easy option, if you want to stick with JSF 1.2, is to upgrade to Tomcat 6, which is still in beta, but supports JSP 2.1 and Servlet 2.5. I have no experience with Tomcat 6, so I can’t guess how successful that will be.
The other options are, as I noted, more drastic. The first would be to use Facelets for the view. Facelets does use JSP at all, so you completely avoid the issue you’re seeing. The downside is that you have to learn a new way to do your views, but, in my opinion, once you learn Facelets, you’ll never use JSP with JSF again. The second approach would be to use Glassfish as your application server. It’s the Java EE 5 Reference Implementation, so it comes with JSF 1.2 Servlet 2.5, JSP 2.1, etc. I think it’s pretty easy to set up and use, but your app server may be dictated to you, making the option unworkable. Personally, of all the options, I think I would go with Facelets. It’s a very nice technology.
I hope all that helped and wasn’t too confusing. If you need to know more, feel free to ask.
January 5th, 2007 | #
Hello Jason,
watz the best way to ensure that the script & link rel tags are placed in html head. My renderer helper method pushes them in the body. I wish to get those , etc in the HTML head , any ideas?
thanks
Satish
January 29th, 2007 | #
Satish,
The only place I’ve seen that done is in the jsf-extensions project. There, Ed created a component, something like
, that he then put in thesection of his page. That works, but I don’t like the extra set up step. That is, of course, just a personal taste.Shooting from the hip, you might also be able to override
setParent()in your component, and, in the method, recursively callgetParent()until you find the right place in the tree and insert a component that renders your script and link tags, but, beyond not really knowing if that would even work, could be quite messy. That approach just occurred to me as I was typing this, so it has not been tested or well thought out. Caveat emptor.January 30th, 2007 | #
Hello! the key points u have described there are simple… can you please tell something about creating custom controls with are inherited from UICommand class and details about implementing actionListener.
Thanks a lot!
February 6th, 2007 | #
Here i feel the document is Very help full for the Beginners who are involved in designing a new Components ! nice Work done by the Author
February 23rd, 2007 | #
Nice work.
One question tho, related to a previous one about Facelets is:
Great, I already use Facelets, but how the heck can I actually get my JSF 1.2 based component tag to compile at all? Clearly I’m missing a jar file here, but which one? Would it be the JSP 2.1 related one? If so do I get this from Glassfish or simply grab a copy of JEE 5 from javasoft?
Thanks
February 23rd, 2007 | #
Actually, a bit of digging into Facelets showed be how to create a TagLibrary implementation for my components to work without writing UIComponentELTag implementations.
February 23rd, 2007 | #
Andy,
For a Facelets, all you should need in most situations is the UIComponent and, if desired, a Renderer (otherwise, the UIComponent will have to handle that). In some more… esoteric cases, you may actually *need* the TagHandler, but I’ve not run into one yet, personally. Note, though, that if you don’t provide UIComponentTag/UIComponentElTag, then your components will not run in a JSP environment, which, to me, means the component’s not complete.
To solve the compilation issue, you might be able to get by with just javaee.jar.
February 23rd, 2007 | #
Hey Jason,
In your response to Brian, you mention that the “javax.servlet.jsp.tagext.JspIdConsumer cannot be resolved.” issue due to the dependency on JSP 2.1 would be resolved by using Facelets…
Even with facelets the error still occurs. Is there a simple way to modify the component to be independent of JSP? If im just using facelets that is.
March 20th, 2007 | #
HI,
i am trying to write a component for file Upload. The code developed complies with all the steps mentioned here with. But as i understand the setPorperties(..) of xxxTag sub class is not being called. Can you please help me with some check points etc.
The diffarent methods of UploadTag, Upload, UploadRenderer are getting called except the UploadTag.setProperties(..) which is being called when the page is getting loaded.
Please help me with what ever information you have.
Regards,
Ravi C
June 6th, 2007 | #