Search code examples
jsf-2facelets

Custom component in JSF2 not being called


I'm creating a custom tag in my application but for some reason it's not working, I followed this tutorial (which is the clearest one that I found to put here as reference) but, like other tutorials that I did, my custom tag ins not called.

WEB-INF/example.taglib.xml

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib
    xmlns="http://java.sun.com/xml/ns/javaee"
    version="2.0">
    <namespace>http://example.com/facelettags</namespace>
    <tag>
        <tag-name>hello</tag-name>
        <handler-class>example.MenuTagHandler</handler-class>
    </tag>
</facelet-taglib>

My tag handler class

package example;

public class MenuTagHandler extends TagHandler {

    private String name = "Anonymous";

    public MenuTagHandler(TagConfig config) {
        //other constructor stuff
        Logger.getLogger(MenuTagHandler.class).info("aaaa");
        //other constructor stuff
    }

    @Override
    public void apply(FaceletContext context, UIComponent parent) throws IOException {
        Logger.getLogger(MenuTagHandler.class).info("aaaa");
        UIComponentBase c = new UIComponentBase() {
            @Override
            public void encodeEnd(FacesContext ctx) throws IOException {
                ResponseWriter w = ctx.getResponseWriter();
                w.write(String.format(
                        "<p>Hello %s! I am FaceletTag.</p>",
                        name));
            }

            // abstract method in base, must override
            @Override
            public String getFamily() {
                return "com.example.facelettag.test";
            }
        };
        parent.getChildren().add(c);
    }
}

My .xhtml file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:exampler="http://example.com/facelettags" >
        <example:hello />
</ui:composition>

The rendered result is

<example:hello></example:hello>

Unfortunately nothing is printed in the log, does anyone have any idea on why it is not calling the tag handler?


Solution

  • If the *.taglib.xml file is not inside the /META-INF of a JAR file which is placed in /WEB-INF/lib and thus won't be automatically detected and registered (like as in case of all those 3rd party JSF component libraries like PrimeFaces, RichFaces, etc), then you'd need to manually register it in webapp's web.xml as follows:

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

    Unrelated to the concrete problem, please note that what you've so far is not a custom component. This is a custom taghandler which in turn creates an anonymous instance of UIComponentBase. This is not necessarily the "best" practice. If you do not need to perform any actions related to the component tree during view build time, then you do not need the taghandler part at all. Just create a fullworthy @FacesComponent class instead.

    See also: