Chapter 9. Custom Components, Converters, and Validators

The Library

In this section, we turn the book viewer into a library, as shown in Figure 8-7.

Figure 8-7. Library implemented with JSF and tiles


The library application shown in Figure 8-7 contains a menu at the top of the page that lets you select a book, either Alice in Wonderland or Peter Pan. The rest of the application works like the book viewer we have discussed throughout this chapter.

The library employs two Tiles techniques that are of interest to us: nesting tiles and using tile controllers.

Nested Tiles

The library shown in Figure 8-7 contains a book viewer. So does the library tile:

  <definition name="book">      ...   </definition>   <definition name="library" path="/libraryLayout.jsp"         controller>      <put name="header" value="/bookSelector.jsp"/>      <put name="book" value="book"/>   </definition>

Notice the value for the book attribute it is a tile, not a JSP page. Using a tile name instead of a JSP page lets you nest tiles, as we did by nesting the book tile in the library.

Tile Controller

In our book viewer application, we had one managed bean named book (see "The Book Viewer" on page 318 for more information about the book bean). The library, on the other hand, must be aware of more than one book.

In this section with a sleight of hand we show you how to support multiple books without having to change the book viewer. The book viewer will continue to manipulate a book bean, but that bean will no longer be a managed bean. Instead, it will be the book that was last selected in the library's pull-down menu at the top of the page.

We accomplish that sleight of hand with a Tiles controller. Tiles lets you attach a Java object, called a tile controller, to a tile. That object's class must implement the org.apache.struts.tiles.Controller interface, which defines a single perform method. Tiles invokes that method just before it loads the controller's associated tile. Tile controllers have access to their tile's context, which lets the controller access the tile's attributes or create new attributes.

We attach a controller to the library tile. The controller looks for a library attribute in session scope. If the library is not there, the controller creates a library and stores it in session scope. The controller then consults the library's selectedBook property to see if a book has been selected. If so, the controller sets the value of the book session attribute to the selected book. If there is no selected book, the controller sets the book attribute to that for Peter Pan. Subsequently, when the library tile is loaded, the book viewer accesses the selected book. The controller is listed in Listing 8-20 on page 348.

Figure 8-8 shows the directory structure for the library application. For brevity, we left out the book HTML files.

Figure 8-8. Library directory structure


The files shown in Figure 8-8 are shown in Listing 8-13 through Listing 8-28, with the exception of the HTML files. As you look through those listings, note the effort required to add a new book. All you have to do is modify the constructor in Library.java see Listing 8-19 on page 346 to create your book and add it to the book map.

You could even implement the Library class so that it reads XML book definitions. That way, you could add books without any programming. Digesting XML is an easy task with Tiles's distant cousin, the Apache Commons Digester. See http://jakarta.apache.org/commons/digester/ for more information about the Digester.

Listing 8-13. library/web/library.jsp

  1. <html>   2.    <%@ taglib uri="http://java.sun.com/jsf/core"  prefix="f" %>   3.    <%@ taglib uri="http://java.sun.com/jsf/html"  prefix="h" %>   4.    <%@ taglib uri="http://jakarta.apache.org/tiles" prefix="tiles" %>   5.   6.    <f:view>   7.       <f:loadBundle basename="com.corejsf.messages" var="msgs"/>   8.       <head>   9.          <link href="styles.css" rel="stylesheet" type="text/css"/>  10.          <title><h:outputText value="#{msgs.libraryWindowTitle}"/></title>  11.       </head>  12.  13.       <body>  14.          <f:subview >  15.             <h:form>  16.                <tiles:insert definition="library" flush="false"/>  17.             </h:form>  18.          </f:subview>  19.       </body>  20.    </f:view>  21. </html>     

Listing 8-14. library/web/WEB-INF/tiles.xml

  1. <?xml version="1.0" encoding="ISO-8859-1" ?>   2.   3.  <!DOCTYPE tiles-definitions PUBLIC   4.   "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"   5.   "http://struts.apache.org/dtds/tiles-config_1_1.dtd">   6.   7. <tiles-definitions>   8.    <definition name="menu-header-content" path="/headerMenuContentLayout.jsp">   9.       <put name="gridClass"           value="headerMenuContent"/>  10.       <put name="headerClass"         value="header"/>  11.       <put name="menuColumnClass"     value="menuColumn"/>  12.       <put name="contentColumnClass"  value="contentColumn"/>  13.    </definition>  14.  15.    <definition name="book" extends="menu-header-content">  16.       <put name="header"  value="/bookHeader.jsp"/>  17.       <put name="menu"    value="/bookMenu.jsp"/>  18.       <put name="content" value="/bookContent.jsp"/>  19.    </definition>  20.  21.    <definition name="library" path="/libraryLayout.jsp"  22.          controller>  23.       <put name="header" value="/bookSelector.jsp"/>  24.       <put name="book" value="book"/>  25.    </definition>  26. </tiles-definitions>     

Listing 8-15. library/web/libraryLayout.jsp

  1. <%@ taglib uri="http://java.sun.com/jsf/core"  prefix="f" %>   2. <%@ taglib uri="http://java.sun.com/jsf/html"  prefix="h" %>   3. <%@ taglib uri="http://jakarta.apache.org/tiles" prefix="tiles" %>   4.   5. <h:panelGrid columns="1" style header>   6.    <f:facet name="header">   7.       <f:subview >   8.          <tiles:insert attribute="header" flush="false"/>   9.       </f:subview>  10.    </f:facet>  11.  12.    <f:subview >  13.       <tiles:insert attribute="book" flush="false"/>  14.    </f:subview>  15. </h:panelGrid>     

Listing 8-16. library/web/bookSelector.jsp

  1. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>   2. <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>   3.   4. <h:outputText value="#{msgs.selectABookPrompt}"/>   5.   6. &nbsp;&nbsp;   7.   8. <h:selectOneMenu onchange="submit()" value="#{library.book}"   9.       valueChangeListener="#{library.bookSelected}">  10.    <f:selectItems value="#{library.bookItems}"/>  11. </h:selectOneMenu>

Listing 8-17. library/src/java/com/corejsf/Library.java

  1. package com.corejsf;   2.   3. import java.util.*;   4. import javax.faces.model.SelectItem;   5. import javax.faces.event.ValueChangeEvent;   6.   7. public class Library {   8.    private Map<String,Book> bookMap = new HashMap<String,Book>();   9.    private Book initialBook = null;  10.    private List bookItems = null;  11.    private String book = null;  12.    private String selectedBook = null;  13.  14.    public Library() {  15.       Book peterpan = new Book();  16.       Book aliceInWonderland = new Book();  17.  18.       initialBook = peterpan;  19.  20.       aliceInWonderland.setDirectory("books/aliceInWonderland");  21.       aliceInWonderland.setTitleKey("aliceInWonderland");  22.       aliceInWonderland.setImage("books/aliceInWonderland/cheshire.jpg");  23.       aliceInWonderland.setNumChapters(12);  24.  25.       peterpan.setDirectory("books/peterpan");  26.       peterpan.setTitleKey("peterpan");  27.       peterpan.setImage("books/peterpan/peterpan.jpg");  28.       peterpan.setNumChapters(15);  29.  30.       bookMap.put("aliceInWonderland", aliceInWonderland);  31.       bookMap.put("peterpan", peterpan);  32.    }  33.    public void setBook(String book) { this.book = book; }  34.    public String getBook() { return book; }  35.  36.    public Map<String,Book> getBooks() {  37.       return bookMap;  38.    }  39.    public void bookSelected(ValueChangeEvent e) {  40.       selectedBook = (String) e.getNewValue();  41.    }  42.    public Book getSelectedBook() {  43.       return selectedBook != null ? bookMap.get(selectedBook) : initialBook;  44.    }  45.    public List getBookItems() {  46.       if(bookItems == null) {  47.           bookItems = new LinkedList();  48.           Iterator<Book> it = bookMap.values().iterator();  49.           while(it.hasNext()) {  50.              Book book = it.next();  51.              bookItems.add(new SelectItem(book.getTitleKey(),  52.                                           getBookTitle(book.getTitleKey())));  53.           }  54.       }  55.       return bookItems;  56.     }  57.     private String getBookTitle(String key) {  58.        return com.corejsf.util.Messages.  59.                         getString("com.corejsf.messages", key, null);  60.     }  61. }     

Listing 8-18. library/web/bookSelector.jsp

  1. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>   2. <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>   3.   4. <h:outputText value="#{msgs.selectABookPrompt}"/>   5.   6. &nbsp;&nbsp;   7.   8. <h:selectOneMenu onchange="submit()" value="#{library.book}"   9.       valueChangeListener="#{library.bookSelected}">  10.    <f:selectItems value="#{library.bookItems}"/>  11. </h:selectOneMenu>

Listing 8-19. library/src/java/com/corejsf/Library.java

  1. package com.corejsf;   2.   3. import java.util.*;   4. import javax.faces.model.SelectItem;   5. import javax.faces.event.ValueChangeEvent;   6.   7. public class Library {   8.    private Map<String,Book> bookMap = new HashMap<String,Book>();   9.    private Book initialBook = null;  10.    private List bookItems = null;  11.    private String book = null;  12.    private String selectedBook = null;  13.  14.    public Library() {  15.       Book peterpan = new Book();  16.       Book aliceInWonderland = new Book();  17.  18.       initialBook = peterpan;  19.  20.       aliceInWonderland.setDirectory("books/aliceInWonderland");  21.       aliceInWonderland.setTitleKey("aliceInWonderland");  22.       aliceInWonderland.setImage("books/aliceInWonderland/cheshire.jpg");  23.       aliceInWonderland.setNumChapters(12);  24.  25.       peterpan.setDirectory("books/peterpan");  26.       peterpan.setTitleKey("peterpan");  27.       peterpan.setImage("books/peterpan/peterpan.jpg");  28.       peterpan.setNumChapters(15);  29.  30.       bookMap.put("aliceInWonderland", aliceInWonderland);  31.       bookMap.put("peterpan", peterpan);  32.    }  33.    public void setBook(String book) { this.book = book; }  34.    public String getBook() { return book; }  35.  36.    public Map<String,Book> getBooks() {  37.       return bookMap;  38.    }  39.    public void bookSelected(ValueChangeEvent e) {  40.       selectedBook = (String) e.getNewValue();  41.    }  42.    public Book getSelectedBook() {  43.       return selectedBook != null ? bookMap.get(selectedBook) : initialBook;  44.    }  45.    public List getBookItems() {  46.       if(bookItems == null) {  47.           bookItems = new LinkedList();  48.           Iterator<Book> it = bookMap.values().iterator();  49.           while(it.hasNext()) {  50.              Book book = it.next();  51.              bookItems.add(new SelectItem(book.getTitleKey(),  52.                                           getBookTitle(book.getTitleKey())));  53.           }  54.      }  55.      return bookItems;  56.   }  57.   private String getBookTitle(String key) {  58.      return com.corejsf.util.Messages.  59.                       getString("com.corejsf.messages", key, null);  60.   }  61. }     

Listing 8-20. library/src/java/com/corejsf/LibraryTileController.java

  1. package com.corejsf;   2.   3. import java.io.IOException;   4. import javax.servlet.ServletContext;   5. import javax.servlet.ServletException;   6. import javax.servlet.http.HttpServletRequest;   7. import javax.servlet.http.HttpServletResponse;   8. import javax.servlet.http.HttpSession;   9. import org.apache.tiles.ComponentContext;  10. import org.apache.tiles.Controller;  11.  12. public class LibraryTileController implements Controller {  13.    public void execute(ComponentContext tilesContext,  14.                  HttpServletRequest request,  15.                  HttpServletResponse response,  16.                  ServletContext context)  17.                  throws IOException, ServletException {  18.      HttpSession session = request.getSession();  19.  20.      String chapter = (String) request.getParameter("chapter");  21.      session.setAttribute("chapter", chapter == null || "".equals(chapter) ?  22.                           "chapter1" : chapter);  23.  24.      Library library = (Library) session.getAttribute("library");  25.  26.      if(library == null) {  27.         library = new Library();  28.         session.setAttribute("library", library);  29.      }  30.  31.      Book selectedBook = library.getSelectedBook();  32.      if(selectedBook != null) {  33.         session.setAttribute("book", selectedBook);  34.      }  35.    }  36.    public void perform(ComponentContext tilesContext,  37.                  HttpServletRequest request,  38.                  HttpServletResponse response,  39.                  ServletContext context)  40.                  throws IOException, ServletException {  41.       HttpSession session = request.getSession();  42.       execute(tilesContext, request, response, context);  43.    }  44.  }     

Listing 8-21. library/src/java/com/corejsf/Book.java

  1. package com.corejsf;   2.   3. import java.util.LinkedList;   4. import java.util.List;   5.   6. public class Book {   7.    private String titleKey;   8.    private String image;   9.    private String directory;  10.    private int numChapters;  11.    private List<String> chapterKeys = null;  12.  13.    // PROPERTY: titleKey  14.    public void setTitleKey(String titleKey) { this.titleKey = titleKey; }  15.    public String getTitleKey() { return titleKey; }  16.  17.    // PROPERTY: image  18.    public void setImage(String image) { this.image = image; }  19.    public String getImage() { return image; }  20.  21.    // PROPERTY: numChapters  22.    public void setNumChapters(int numChapters) { this.numChapters = numChapters;}  23.    public int getNumChapters() { return numChapters; }  24.  25.    // PROPERTY: directory  26.    public void setDirectory(String directory) { this.directory = directory;}  27.    public String getDirectory() { return directory; }  28.  29.    // PROPERTY: chapterKeys  30.    public List<String> getChapterKeys() {  31.       if(chapterKeys == null) {  32.          chapterKeys = new LinkedList<String>();  33.          for(int i=1; i <= numChapters; ++i)  34.             chapterKeys.add("chapter" + i);  35.       }  36.       return chapterKeys;  37.    }  38. }     

Listing 8-22. library/web/bookHeader.jsp

  1. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>   2. <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>   3.   4. <h:panelGrid columns="1" style>   5.    <h:graphicImage value="#{book.image}"/>   6.    <h:outputText value="#{msgs[book.titleKey]}" style/>   7.    <hr>   8. </h:panelGrid>     

Listing 8-23. library/web/bookMenu.jsp

  1. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>   2. <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>   3.   4. <h:dataTable value="#{book.chapterKeys}" var="chapterKey"   5.         style columnClasses="linksColumn">   6.    <h:column>   7.       <h:commandLink>   8.          <h:outputText value="#{msgs[chapterKey]}"/>   9.          <f:param name="chapter" value="#{chapterKey}"/>  10.       </h:commandLink>  11.    </h:column>  12. </h:dataTable>

Listing 8-24. library/web/bookContent.jsp

  1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>   2.   3. <c:import url="${book.directory}/${chapter}.html"/>

Listing 8-25. library/web/styles.css

  1. .library {   2.    vertical-align: top;   3.    width: 100%;   4.    height: 100%;   5. }   6. .libraryHeader {   7.    width: 100%;   8.    text-align: left;   9.    vertical-align: top;  10.    background-color: #ddd;  11.    font-weight: lighter;  12.    border: thin solid #777;  13. }  14. .bookHeader {  15.    width: 100%;  16.    text-align: center;  17.    background-color: #eee;  18.    border: thin solid CornflowerBlue;  19. }  20. .bookTitle {  21.    text-align: center;  22.    font-style: italic;  23.    font-size: 1.3em;  24.    font-family: Helvetica;  25. }  26. .menuColumn {  27.    vertical-align: top;  28.    background-color: #eee;  29.    border: thin solid #777;  30. }  31. .chapterColumn {  32.    vertical-align: top;  33.    text-align: left;  34.    width: *;  35.    padding: 3px;  36. }  37. .contentColumn {  38.    vertical-align: top;  39.    text-align: left;  40.    width: *;  41. }  42. .links {  43.    width: 85px;  44.    vertical-align: top;  45.    text-align: center;  46. }  47. .linksColumn {  48.    vertical-align: top;  49.    text-align: center;  50. }     

Listing 8-26. library/web/WEB-INF/faces-config.xml

 51. <?xml version="1.0"?>  52. <faces-config xmlns="http://java.sun.com/xml/ns/javaee"  53.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  54.    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  55.       http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"  56.    version="1.2">  57. </faces-config>

Listing 8-27. library/web/WEB-INF/web.xml

  1. <?xml version="1.0"?>   2. <web-app xmlns="http://java.sun.com/xml/ns/javaee"   3.    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   4.    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   5.       http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"   6.    version="2.5">   7.    <servlet>   8.       <servlet-name>Tiles Servlet</servlet-name>   9.       <servlet-class>org.apache.tiles.servlets.TilesServlet</servlet-class>  10.       <init-param>  11.          <param-name>definitions-config</param-name>  12.          <param-value>/WEB-INF/tiles.xml</param-value>  13.       </init-param>  14.       <load-on-startup>2</load-on-startup>  15.    </servlet>  16.  17.    <servlet>  18.       <servlet-name>Faces Servlet</servlet-name>  19.       <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>  20.       <load-on-startup>1</load-on-startup>  21.    </servlet>  22.  23.    <servlet-mapping>  24.       <servlet-name>Faces Servlet</servlet-name>  25.       <url-pattern>*.faces</url-pattern>  26.    </servlet-mapping>  27.  28.    <welcome-file-list>  29.       <welcome-file>index.html</welcome-file>  30.    </welcome-file-list>  31. </web-app>     

Listing 8-28. library/src/java/com/corejsf/messages.properties

  1. libraryWindowTitle=Gutenberg Library   2. aliceInWonderland=Alice in Wonderland   3. peterpan=Peter Pan   4. selectABookPrompt=Select a book   5.   6. chapter1=Chapter 1   7. chapter2=Chapter 2   8. chapter3=Chapter 3   9. chapter4=Chapter 4  10. chapter5=Chapter 5  11. chapter6=Chapter 6  12. chapter7=Chapter 7  13. chapter8=Chapter 8  14. chapter9=Chapter 9  15. chapter10=Chapter 10  16. chapter11=Chapter 11  17. chapter12=Chapter 12  18. chapter13=Chapter 13  19. chapter14=Chapter 14  20. chapter15=Chapter 15



Core JavaServerT Faces
Core JavaServer(TM) Faces (2nd Edition)
ISBN: 0131738860
EAN: 2147483647
Year: 2004
Pages: 84

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net