Question

JSF spec 2.2 (2013-03-20) says in item 10.3.3.1 (Declaring a composite component library for use in a Facelet page):

If a facelet taglibrary is declared in an XHTML page with a namespace starting with the string “http://java.sun.com/jsf/composite/” (without the quotes), the remainder of the namespace declaration is taken as the name of a resource library [...]

If the substring following “http://java.sun.com/jsf/composite/” contains a “/” character, or any characters not legal for a library name the following action must be taken. If application.getProjectStage() is Development an informative error message must be placed in the page and also logged. Otherwise the message must be logged only.

So that means it's illegal to have the following folder structure:

resources
    components
        system
        something_specific
        something_even_more_specific

and refer to the library name “http://java.sun.com/jsf/composite/components/something_specific”? Is this correct?

That seems like a weird restriction. I want my sources structured, not mushed together in an enormous lump.

Such hierarchical library actually works in Wildfly 8.0.0.CR1, but I'm not sure if it's wise to rely on this behavior.

A "best practices" kind of answers are welcome.

Was it helpful?

Solution

I'll summarize my findings.

Sources: JSF spec issue 740, discussion preceding issue 740, another discussion, JSF spec issue 1141, discussion preceding issue 1141.

Slash in a library name is disallowed. Slash in a resource name is allowed.

In practice on Mojarra 2.2.5 composite component library just works both in a XHTML namespace declaration, and in taglib's <composite-library-name>components/system</composite-library-name>. I expect that could still break in future Mojarra and/or JSF spec versions. If you use this, you're at JSF spec/impl developers' mercy. Linked issues and discussions have shown them to be willing to preserve backwards compatibility even for unintended features.

In MyFaces there is a special setting, org.apache.myfaces.STRICT_JSF_2_ALLOW_SLASH_LIBRARY_NAME (MyFaces issue 3454). I expect that relying on a resource library with slashes in its name, using this setting, could break some functionality such as JSF resource versioning (how can it know what part is a library name and what part belongs to resource name?).

I think composite component library hierarchy may be implemented by importing components in a taglib one by one:

<tag>
    <tag-name>test</tag-name>
    <component>
      <resource-id>
          components/system/test.xhtml
      </resource-id>
    </component>
</tag>

Thus the library name effectively becomes "components" and the resource name becomes "system/test.xhtml".

Update: you need a hack to make this work with Mojarra.

/**
 * Allows nesting composite components deeper. E.g.:
 * <resource-id>system/components/package/anotherpackage/test.xhtml</resource-id>
 *
 * To structure your sources better. To document your components and their attributes in
 * taglib.xml for IDE content assist.
 *
 * So it purposefully violates the resource lookup algorithm described in JSF 2.2,
 * 2.6.1.3 Resource Identifiers.
 */
public class NestedCCResourceHandler extends ResourceHandlerWrapper {

    public NestedCCResourceHandler(final ResourceHandler resourceHandler) {
        super(resourceHandler);
    }

    @Override
    public Resource createResourceFromId(String resourceId) {
        // just treat the whole thing as resourceName, no libraries
        Resource resource = super.createResource(resourceId);
        // com.sun.faces.component.CompositeComponentStackManager#findCompositeComponentUsingLocation
        // expects to find libraryName in the resource path, so set it to empty string
        resource.setLibraryName("");
        return resource;
    }

}

And register it in faces-config.xml:

<application>
    <resource-handler>fully.qualified.name.NestedCCResourceHandler</resource-handler>
</application>

This could break libraries for CCs, maybe version contracts? Not sure, made this a long time ago. Definitely works with Mojarra 2.3.3.SP1.

OTHER TIPS

after some experiment, i think that these statements should be read:

  • the remainder of the namespace declaration is taken as the name of a resource library http://java.sun.com/jsf/composite/components/system must match /resources/components/system

  • any characters not legal for a library name

    if you declare http://java.sun.com/jsf/composite/components/system2 and /resources/components/system2 does not exists, take action

    Warning: This page calls for XML namespace http://java.sun.com/jsf/composite/components/system2 declared with prefix y but no taglibrary exists for that namespace.

so it is absolutely legal to declare

xmlns:x="http://java.sun.com/jsf/composite/components/system"

and any other folder structure that exists under /resources

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top