Version 6

    Reusable CRUD Action Buttons through Facelets Composition

     

     

    This article will follow you through reducing the seam gen'd Action Buttons for CRUD operations into a single reusable tag.

     

     

     

    Original xhtml

    <div class="actionButtons">
                <h:commandButton id="save" 
                              value="Save" 
                             action="#{customerHome.persist}"
                           rendered="#{!customerHome.managed}"></h:commandButton>  
                                               
                <h:commandButton id="update" 
                              value="Save" 
                             action="#{customerHome.update}"
                           rendered="#{customerHome.managed}"></h:commandButton>
                                             
                <h:commandButton id="delete" 
                              value="Delete" 
                             action="#{customerHome.remove}"
                           rendered="#{customerHome.managed}"></h:commandButton>
                        
                <s:button id="done" 
                       value="Done"
                 propagation="end"
                        view="/customerList.xhtml"
                    rendered="#{customerHome.managed}"></s:button>
                    
                <s:button id="cancel" 
                       value="Cancel"
                 propagation="end"
                        view="/customerList.xhtml"
                    rendered="#{!customerHome.managed}"></s:button>          
    </div>

     

     

     

    New xhtml

    <my:actionButtons backingBean="#{customerHome}" searchPage="/customerList.xhtml" ></my:actionButtons>
    • It can't get much easier than this, for use on another CRUD based page just replace the values of the backingBean and searchPage attributes.

     

     

     

    Use - customer.xhtml

    • Add xmlns:my="http://my.com/jsf/my" to your namespace definitions

    • Replace the original xhtml with the new xhtml and change the backingBean and searchPage where necessary

     

     

     

    Facelets Composition source - actionButtons.xhtml

     

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:c="http://java.sun.com/jstl/core"
          xmlns:s="http://jboss.com/products/seam/taglib">
        
        <ui:composition>
            
            <c:if test="${empty create}">
                <c:set var="create" value="persist" ></c:set>
            </c:if>
            <c:if test="${empty update}">
                <c:set var="update" value="update" ></c:set>
            </c:if>
            <c:if test="${empty delete}">
                <c:set var="delete" value="remove" ></c:set>
            </c:if>
            <c:if test="${empty managed}">
                <c:set var="managed" value="managed" ></c:set>
            </c:if>
            
            <div class="actionButtons">
                
                <h:commandButton id="create" 
                                 value="Create" 
                                 action="#{backingBean[create]}"
                                 rendered="#{!backingBean[managed]}"></h:commandButton>  
                
                <h:commandButton id="update" 
                                 value="Update" 
                                 action="#{backingBean[update]}"
                                 rendered="#{backingBean[managed]}"></h:commandButton>
                
                <h:commandButton id="delete"
                                 value="Delete" 
                                 action="#{backingBean[delete]}"
                                 rendered="#{backingBean[managed]}"></h:commandButton>
                
                <s:button id="done" 
                          value="Done"
                          propagation="end"
                          view="#{searchPage}"
                          rendered="#{backingBean[managed]}"></s:button>
                
                <s:button id="cancel" 
                          value="Cancel"
                          propagation="end"
                          view="#{searchPage}"
                          rendered="#{!backingBean[managed]}"></s:button>
                
            </div>
            
        </ui:composition>
        
    </html>
    
    • The c:if's allow me to eliminate a lot of the otherwise necessary attributes for my:actionButtons.  This way I can define default behavior following the most common usage.

     

     

     

    Wiring

    These files live in WEB-INF.

     

     

    facelets taglib - my.taglib.xml

    <!DOCTYPE facelet-taglib PUBLIC 
      "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
      "http://java.sun.com/dtd/faces-taglib_1_0.dtd">
    
    <facelet-taglib>
       <namespace>http://my.com/jsf/my</namespace>
       <tag>
          <tag-name>actionButtons</tag-name>
          <source>actionButtons.xhtml</source>
       </tag>
    </facelet-taglib>

     

     

    Web.xml - web.xml

    ...
       <context-param>
          <param-name>facelets.LIBRARIES</param-name>
          <param-value>/WEB-INF/my.taglib.xml</param-value>
       </context-param>
    ...