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.