Search code examples
javajsf-2custom-componentcomposite-componenttagfile

Proper using of Facelet templates & Composite Components


I'm still not sure about proper using of JSF Templates & Composite Components. I need create an enterprise web applications, which will have a lot of pages. Every page will have the same header, menu, footer and of course different content (= JSF template). The content on every pages will consist of reusable "boxes" (= JSF composite components). The boxes consist of some fileds, buttons etc. Is my solution proper? Or should I use other technology like , Custom Components, decorate ...?

layout.xhtml

<h:body>
    <ui:insert name="main_menu">
        <ui:include src="/xhtml/template/main_menu.xhtml"/>
    </ui:insert>
    <ui:insert name="header">
        <ui:include src="/xhtml/template/header.xhtml"/>
    </ui:insert>
    <ui:insert name="content"/>
    <ui:insert name="footer">
        <ui:include src="/xhtml/template/footer.xhtml"/>
    </ui:insert>
</h:body>

customer_overview.xhtml:

<html xmlns:cc="http://java.sun.com/jsf/composite/composite_component">
<h:body>
    <!-- Facelet template -->
    <ui:composition template="/xhtml/template/layout.xhtml">
        <ui:define name="content">
            <!-- Composite Components -->
            <cc:component_case_history
                caseList="#{customerOverviewController.cases}"
            />
            <cc:component_customer
                ....
            />
            ...
        </ui:define>
    </ui:composition>
</h:body>

component_case_history.xhtml

<html xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
    <composite:attribute name="cases" type="java.util.List"/>
</composite:interface>

<composite:implementation>
    <!-- using of "cases" -->
    ...
</composite:implementation>

CustomerOverviewController.java

@ManagedBean
@ViewScoped
public class CustomerOverviewController {
    public List<Case> getCases() {
        ...
    }
}

EDIT 2012-04-27

Based on: When to use <ui:include>, tag files, composite components and/or custom components?

I think that I should use rather Facelet templates + Facelet tag files instead of Facelet templates + Composite components.


Solution

  • Layout, templating

    layout.xhtml:

    Every page will have the same header, menu, footer ...

    In this case you can omit the ui:insert tags for header, menu, footer.

    <h:body>
        <ui:include src="/xhtml/template/main_menu.xhtml"/>
        <ui:include src="/xhtml/template/header.xhtml"/>
        <ui:insert name="content"/>
        <ui:include src="/xhtml/template/footer.xhtml"/>
    </h:body>
    

    You may also have a ui:insert without name, so if you want to further simplify:

    <h:body>
        <ui:include src="/xhtml/template/main_menu.xhtml"/>
        <ui:include src="/xhtml/template/header.xhtml"/>
        <ui:insert/>
        <ui:include src="/xhtml/template/footer.xhtml"/>
    </h:body>
    

    customer_overview.xhtml:

    If you have ui:insert without name in layout.xhtml, you don't need ui:define here:

    <ui:composition template="/xhtml/template/layout.xhtml">
            <!-- Composite Components -->
            <cc:component_customer/>
            <cc:component_case_history
                caseList="#{customerOverviewController.cases}"
            />
            ...
    </ui:composition>
    

    Also you should place your templates in a folder that users cannot access directly (WEB-INF).

    reusable "boxes"

    One of your composite component looks like this:

    <cc:component_customer/>
    

    A component without any attributes is very suspicious.

    • What does it do?
    • displays a username?
    • how does it get the username if you don't pass any attributes?

    A component should be self-contained, for other reusable parts use ui:insert instead.