Simple Java based JSF custom component

4 September 2011, by: Development

Even though in JSF components have always been a central thing, actually creating them required a ridiculous amount of tedious work in JSF 1.x. Not only did you had to create the actual component, it also required you to:

  • Register the component in an XML file
  • Create a tag handler class, where you referenced the component by its registered name
  • Register the tag in .tld file.

You were also more or less supposed to create a separate renderer class, and although this actually has always been optionally, people seemed to interpret it as being a required part as well. Although none of this was really difficult, the sheer amount of work prevented everyone but component library builders from creating components.

JSF 2.0 addressed all of these concerns by introducing composite components, where you are able to create first-class components just by putting some existing components and/or markup in a Facelets file. For the majority of use cases where application builders needed their own customized components, this is actually all that’s needed.

For some cases however a Java based component is still a more natural fit. Although not as simple to create as composite components, creating Java based custom components has actually been simplified as well. Of the steps outlined above, only a registration for the tag is still required. The actual component can be rather simple:

components/CustomComponent.java

  1. @FacesComponent("components.CustomComponent")
  2. public class CustomComponent extends UIComponentBase {
  3.  
  4.     @Override
  5.     public String getFamily() {        
  6.         return "my.custom.component";
  7.     }
  8.  
  9.     @Override
  10.     public void encodeBegin(FacesContext context) throws IOException {
  11.  
  12.         String value = (String) getAttributes().get("value");
  13.  
  14.         if (value != null) {        
  15.             ResponseWriter writer = context.getResponseWriter();
  16.             writer.write(value.toUpperCase());
  17.         }
  18.     }
  19. }

Unfortunately, a registration in an XML file is still required in JSF 2.1 to use this as a tag (note, that in JSF 2.2 this isn’t required anymore):

META-INF/my.taglib.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <facelet-taglib 
  3.     xmlns="http://java.sun.com/xml/ns/javaee"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
  6.     version="2.0">
  7.  
  8.     <namespace>http://example.com/test</namespace>
  9.  
  10.     <tag>
  11.         <tag-name>customComponent</tag-name>
  12. 	<component>
  13.             <component-type>components.CustomComponent</component-type>
  14.         </component>
  15.     </tag>
  16.  
  17. </facelet-taglib>

The custom component can now be used on a Facelet as follows:

page.xhtml

  1. <html xmlns="http://www.w3.org/1999/xhtml"
  2.     xmlns:h="http://java.sun.com/jsf/html"
  3.     xmlns:test="http://example.com/test"
  4. >
  5.     <h:body>   		
  6.         <test:customComponent value="test"/>        
  7.     </h:body>
  8. </html>

As shown, creating a Java based JSF component that simply renders something is not that complicated. Although composite components should generally be preferred, Java based ones can come in handy and it’s an important extra tool.

It’s a shame perhaps the XML registration is still needed in JSF 2.1, but luckily there was a feature request in the JSF spec JIRA that made it largely unnecessary for JSF 2.2. Hopefully the actual Java code can also be further simplified if the family and component name would be defaulted in a future JSF version (the last e.g. to the fully qualified class name).


Arjan Tijms

10 comments to “Simple Java based JSF custom component”

  1. What’s new in JSF 2.2? | J-Development says:

    [...] JSF 2.0, creating (java based) custom components was a lot of work. The amount of required work was largely reduced in JSF 2.0, mainly because Facelets does not [...]

  2. Mehdi Heidarzadeh says:

    Thanks Arjan, nice article.
    Actually I have user case in this area, but I don’t know how to handle that!
    I’m using Primefaces and I have a Composite component with one chart and two datepickers it works well but know I want to write a rendere for this composite component then manipulate some parts of this component on server side using this rendere, so some parts of component will be rendered with composite component itself, and some parts will be manipulated or added with my Renderer.
    I don’t know how to that?
    I have searched a lot about this but could not find any solution, all examples in the internet are either pure facelet composite component or a custome component which is rendered just by a renderer!
    I think Richfaces CDK can do this but I’m using Primefaces!
    Any help will be really appraciated.

  3. Adeel says:

    You are missing the part you have to put in web.xml

  4. Arjan Tijms says:

    Adeel said:

    You are missing the part you have to put in web.xml

    Well yes and no ;)

    With the taglib file present in META-INF/my.taglib.xml (specifically in a .jar) then no entry in web.xml is required. Including the jar with the custom component on the classpath is enough.

    However, if the taglib file in put in the WEB-INF folder of a .war, then indeed an entry in web.xml is needed for JSF 2.1:

    <context-param>
        <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
        <param-value>/WEB-INF/my.taglib.xml</param-value>
    </context-param>

    Note that for simple cases, no taglib file is needed for either situation in JSF 2.2.

  5. Simple Java based JSF 2.2 custom component | J-Development says:

    [...] mentioned in a previous blog posting, creating custom components was a lot of effort in JSF 1.x, but became significantly easier in JSF [...]

  6. ichsan budiman says:

    i have error in facelets when i put
    xmlns:test=”http://example.com/test”
    no library found

  7. Arjan Tijms says:

    @ichsan budiman

    Did you register my.taglib.xml in web.xml as shown in the comments, OR did you put it into the META-INF/ folder of a jar?

  8. Damon says:

    Hi,

    I’m using JSF 2.2. I created a Java class with the annotation:

    @FacesComponent(namespace = “http://mynamespace”, tagName = “mytag”, createTag = true)

    and straight away it worked in my xhtml without any other configuration files.

    This is with the Java class in WEB-INF/classes.

    I then moved the class into a separate jar (i.e. WEB-INF/lib/myjar.jar) and now it doesn’t find the component. I just see the unexploded tag in my browser.

    Can you please tell me what I need to do to make it work when the component Java class is inside a jar file? Do I need some xml configuration file in this case?

    I’m running my app under Jetty 8 using jetty-maven-plugin.

    Thanks, Damon

  9. pallavaraju says:

    hello sir,

    iam using jsf1.2
    when i am displaying a table from mysql by using datatable tag, its working fine. but when i am refreshing the webpage using f5, again same table is added to webpage,it means new object is creating when i am refreshing .

    can u please solve my problem

  10. wirte-a-jsf-custom-component | mauroprogram's Blog says:

    [...] http://jdevelopment.nl/simple-java-based-jsf-custom-component/ [...]

Type your comment below:


5 − = four

css.php best counter