9.2. Writing a Custom JSF ComponentUsing JavaServer Faces Technology with AJAX, by Greg Murray et al. (https://bpcatalog.dev.java.net/nonav/ajax/jsf-ajax/index.html) describes the three ways to use Ajax with a JavaServer Faces component:
In earlier chapters, we used servlets to service the backend requests. This time, we'll use a listener; our custom JSF component will be entirely encapsulated in the JSF lifecycle. To keep things simple, we'll stick with the same example used in the previous chapters: we'll use Ajax to populate city and state fields in an HTML form based on a user-entered zip code. Figure 9-2 shows where we're headed. Figure 9-2. Zip code lookup with JSF and AjaxWe could simply add a custom JSP tag to a JSF view and write a servlet to service the Ajax request. This is a quick way to inject Ajax into a JSF application; it's not fundamentally different from the techniques we've already covered. But if you want to use the JSF framework, you need to write a custom component. 9.2.1. Writing the JSP Page for the JSF ApplicationThe JSP page for this application (Example 9-1) uses JSF's core and HTML tag libraries. In addition to these libraries, we'll develop a new Ajax tag library in this chapter. Our library will contain only one tag: zipCode. Example 9-1. The view for the JSF application: index.jsp
The web application can't access this JSP directly by including a <welcome> element in the web.xml file. The JSF application must render this page through the JSF lifecycle, and that cannot happen if the web container accesses the page directly. Instead, the web application must access a JSP page that forwards to the JSF application. That JSP is forward.jsp. Here's how it's configured in web.xml: <web-app> ... <welcome-file-list> <welcome-file>forward.jsp</welcome-file> </welcome-file-list> ... </web-app> forward.jsp (Example 9-2) uses a <jsp:forward> tag to index.faces to render index.jsp from the JSF application lifecycle. Example 9-2. forward.jsp
It may seem odd that the page forwards to index.faces rather than to index.jsp itself, but that's how it works. The JSF application references each page with a .faces extension; the JavaServer Faces servlet, javax.faces.webapp.FacesServlet, strips off the .faces extension and loads the JSP file with the .jsp extension. 9.2.2. Configuring JSF: web.xml and faces-config.xmlThe configuration resource file is unique to JavaServer Faces. As you can see in Example 9-3, web.xml defines the javax.faces.CONFIG_FILES parameter to point to faces-config.xml. web.xml also configures the FacesServlet that runs the JSF environment, setting it to intercept any URL with a .faces extension. Example 9-3. web.xml
The faces-config.xml file controls much of the behavior of the JSF application. It configures the JSF lifecycle, any beans that will be used in the lifecycle, the renderers that will be used, and so on. Here is a list of elements that can be used in faces-config.xml:
Our faces-config.xml file is shown in Example 9-4. This simple application uses only the <render-kit>, <component>, and <lifecycle> elements. Example 9-4. faces-config.xml
The <lifecycle> element contains a <phase-listener> element, which defines a class that can be called at the end of each phase (in this case, ZipCodePhaseListener). The <render-kit> element in this configuration contains one <renderer> element, which is set to com.oreilly.ajax.ZipCodeRenderer. Render kits can contain one or more renderers. The default render kit contains renderers for HTML, but render kits can be developed for other markup languages. A renderer draws a specific component. For example, a form renderer in the HTML render kit renders the <form> element (more specifically, the renderer's encodeBegin( ) method renders the <form> tag, and the encodeEnd( ) method renders the closing </form> tag). The faces-config.xml file in Example 9-4 defines a renderer that uses the com.oreilly.ajax.ZipCodeRenderer class to build the HTML display and Ajax code that our JSF tag needs. The <component> element defines the JSF component that is used in the application. In this case, the com.oreilly.ajax.ZipCode class is a custom component; it is used to get the application's HTML input. Figure 9-3 models the configuration of our application. Bear in mind that this is a very basic example; a real-world application will almost certainly have a more complex configuration containing many other elements. Figure 9-3. JavaServer Faces configuration |