jsf-2.2composite-componentcustom-tag

How can I create a clean tag library (.jar) containing custom tags and composite components in JSF 2.2?


I've read the various blog posts and stackoverflow posts on how to create a composite components and custom tags within a web app and have gotten things to work just fine. I'm now trying to move everything into a reusable JAR file.

mylib.jar hierarchy:

src/main/java
    com.example.MyComposite.java
src/main/resources/
    META-INF
        faces-config.xml
        my.taglib.xml
    META-INF/resources/components
        myComposite.xhtml
    META-INF/tags
        myTag.xhtml

my.taglib.xml:

<facelet-taglib version="2.2"
            xmlns="http://xmlns.jcp.org/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd">

    <namespace>http://www.example.com/components</namespace>

    <tag>
        <tag-name>myTag</tag-name>
        <source>
                tags/myTag.xhtml
        </source>
    </tag>

    <tag>
        <tag-name>myComposite</tag-name>
        <component>
            <resource-id>
                components/myComposite.xhtml
            </resource-id>
        </component>
    </tag>
</facelet-taglib>

I've built this as a jar and used it in my web-app and both the custom tag and composite component work great. It took me trying 100 different combinations of hierarchy to get it to work though.

My problem is that I don't like how I seem to have to put custom tags in one place (/tags) and composite components in another (/resources/components). In addition, I have to reference custom tags with the source tag and composite components with a component/resource-id tag. For example, I tried putting the myTag.xhtml into /resources/components and referencing it with a resource-id but I got NPE's when I tried to use it.

So do tags and components have to be in different directories? Do I just have to live with this hierarchy?


Solution

  • You can use <composite-library-name> alone for composites to reduce unnecessary <tag> boilerplate for composites. As to tagfiles, you could just put them in /resources/tags and alter <source> accordingly so the folder structure is more uniform.

    src/main/java
     `-- com/example/MyComposite.java
    
    src/main/resources
     `-- META-INF
          |-- resources
          |    |-- components
          |    |    `-- myComposite.xhtml
          |    `-- tags
          |         `-- myTag.xhtml
          |-- faces-config.xml
          `-- my.taglib.xml
    
    <facelet-taglib version="2.2"
                xmlns="http://xmlns.jcp.org/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd">
    
        <namespace>http://www.example.com/components</namespace>
        <composite-library-name>components</composite-library-name>
    
        <tag>
            <tag-name>myTag</tag-name>
            <source>resources/tags/myTag.xhtml</source>
        </tag>
    </facelet-taglib>
    

    See also: