Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

A first look at JavaServer Faces, Part 2

Explore JavaServer Faces components

Page 3 of 6

Listing 11. /WEB-INF/classes/com/sabreware/tags/ToggleGraphicTag.java

package com.sabreware.tags;
import javax.faces.webapp.FacesTag;
import javax.faces.component.UIComponent;
import javax.faces.component.UIGraphic;
import javax.faces.context.FacesContext;
import javax.faces.event.FacesEvent;
import javax.faces.event.RequestEventHandler;
import com.sabreware.components.UIToggleGraphic;
public class ToggleGraphicTag extends FacesTag {
   private String imageOne, imageTwo;
   public void setImageOne(String imageOne) {
      this.imageOne = imageOne;   
   }
   public void setImageTwo(String imageTwo) {
      this.imageTwo = imageTwo;   
   }
   public void overrideProperties(UIComponent component) {
      super.overrideProperties(component);
      component.setAttribute("imageOne", imageOne);
      component.setAttribute("imageTwo", imageTwo);
   }
   public UIComponent createComponent() {
      UIToggleGraphic comp = new UIToggleGraphic();
      comp.setURL(imageOne);
      return comp;
   }
   public String getRendererType() {
      return null;
   }
}


The preceding JSP custom tag extends the FacesTag class from the javax.faces.webapp directory. All custom tags that represent JSF components extend either FacesTag or, if the tag needs to manipulate its body content, FacesBodyTag.

Besides storing the component's images as class member variables, the preceding JSP custom tag also stores those images as properties of the tag's component in overrideProperties(). The createComponent() method, which is abstract and therefore must be implemented by all FacesTag extensions, creates a component and returns a reference to that component. In the preceding tag, that method also sets the component's original image by calling the component's setURL() method. Finally, the getRendererType() method, which is also abstract in FacesTag, returns a string constant that represents an identifier for the component's renderer. In this case, the component does not have a renderer; therefore, the getRendererType() method returns null.

The custom component is demonstrated in Listing 12.

Listing 12. /WEB-INF/classes/com/sabreware/components/UIToggleGraphic.java

package com.sabreware.components;
import javax.servlet.http.HttpServletRequest;
import javax.faces.component.UIGraphic;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.CommandEvent;
import javax.faces.event.FacesEvent;
public class UIToggleGraphic extends UIGraphic {
   // This component supports one command: click.
   private static String clickCommand = "click";
   // This method indicates whether this component renders itself
   // or delegates rendering to a renderer.
   public boolean getRendersSelf() { 
      return true; 
   }
   // This method, which is called during the Render Response phase,
   // generates the markup that represents the component.
   public void encodeEnd(FacesContext context) throws java.io.IOException {
      ResponseWriter writer = context.getResponseWriter();
      HttpServletRequest request = (HttpServletRequest)
                             context.getServletRequest();
      // Represent this component as an HTML anchor element with an
      // image. When the image is clicked, the current page is reloaded
      // with a request parameter named component whose value is this
      // component's ID.
      writer.write("<a href='?component=" + getComponentId() + "'>");
      writer.write("<img border='0' src='");
      writer.write(request.getContextPath() + (String)getURL() + "'/>");
      writer.write("</a>");
   }
   // This method, which is called during the Apply Request Values phase,
   // decodes request parameters.
   public void decode(FacesContext context) throws java.io.IOException {
      HttpServletRequest request = (HttpServletRequest)
                             context.getServletRequest();
      // If there's a request parameter named component whose value
      // matches this component's ID...
      if(getComponentId().equals(request.getParameter("component"))) {
         // ...enqueue a command event on the FacesContext event queue
         // for this component. The processEvent method, listed below,
         // processes that event.
         context.addRequestEvent(this, new CommandEvent(this, clickCommand));
      }
   }
   // This method, which is called during the Handle Request Events phase,
   // processes command events that were added to the FacesContext by
   // the decode method.
   public boolean processEvent(FacesContext context, FacesEvent event) {
      if(event instanceof CommandEvent) {
         CommandEvent cmdEvent = (CommandEvent)event;
         // If the event's command name equals "click"...
         if(clickCommand.equals(cmdEvent.getCommandName())) {
            // ...toggle the component's image.
            toggleImage();
         }
         return false; // Go directly to render phase.
      }
      return true; // Process request normally.
   }
   // This method returns a string representing the component's type.
   public String getComponentType() {
      return "com.sabreware.components.UIToggleGraphic";
   }
   // This private method toggles the component's image.
   private void toggleImage() {
      String     imageOne = (String)getAttribute("imageOne");
      String     imageTwo = (String)getAttribute("imageTwo");
      String currentImage = (String)getAttribute("image");
      if(imageTwo.equals(currentImage)) 
         setAttribute("image", imageOne);
      else                 
         setAttribute("image", imageTwo);
      // The setURL() method is defined in the superclass (UIGraphic).
      setURL((String)getAttribute("image"));
   }
}


The preceding custom component extends the UIGraphic class, a JSF standard component that displays an image that cannot be manipulated by a user. The UIToggleGraphic class overrides getRendersSelf to return true, meaning the component handles rendering and event handling on its own.

Rendering takes place in the encodeEnd() method, which generates markup for the component—that markup is an HTML anchor element. When that anchor is clicked, the current page is reloaded and a request parameter named component is created whose value is the component's ID. The encodeEnd() method is called by the JSF implementation during the JSF lifecyle's Render Response phase.

The decode() method is called by the JSF implementation during the Apply Request Values phase. That method looks for a request parameter named component, and if that request parameter's value matches the component's ID, the decode() method adds a request event to the JSF context.

< Prev | 1 | 2 | 3 | 4 | 5 | 6 |  Next >
Resources