免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 891 | 回复: 0
打印 上一主题 下一主题

Building Custom JSF UI components [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-02-12 11:00 |只看该作者 |倒序浏览

                                                Overview
One of the key strengths of JavaServer Faces (JSF) is that not only does it
  provide substantial technology for easy, out of the box component based J2EE
  Web applications assembly, but it also is a very flexible API which allows for
  a wide breadth of customizations in numerous and innovative ways. This article
  introduces and explores the component developer's experience of building custom
  JSF user interface (UI) components.
Intended Audience
First off, this article is intended for component developers who already
  have an understanding of the overall JSF application development process but
  want to learn how to start developing their own custom JSF UI components. For
  those who are still new to JSF development, readers are highly recommended to
  first consult JSF application tutorials such as Rick Hightower's article on
  basic JSF development:
http://www-106.ibm.com/developerworks/library/j-jsf1/

Or my earlier JavaPro article, which also introduces JSF:
http://www.fawcette.com/javapro/2004_01/magazine/features/cschalk/
In contrast to those introductory JSF articles, this article introduces the
  more advanced task of building custom JSF UI components by first explaining
  all of the "moving parts" associated with custom UI Components starting
  with a simple custom "HelloWorld" UI Component as an example.
The article then shows how to extend the simple "HelloWorld" component
  into more useful examples that show live stock quote information using a Web
  service. At the end of the article readers will have an appreciation of what
  exactly are the key tasks associated with building custom UI Components along
  with a full understanding of all the various sub-components that make up a typical
  "JSF UI Component".
When to Customize JSF
Before jumping into custom JSF component development just for the sake of it,
  some research should be done on whether custom development is necessary at all
  and at what level it is needed. As mentioned before, JavaServer Faces' base
  UI component library actually provides a modest amount of practical UI and non-UI
  components in its specification. In addition to visible components such as input/output
  fields, menu components and form buttons the JSF specification also has non-UI
  components which handle things like basic validation and/or data conversion.
  In many cases a developer may find that he/she may only need to customize a
  specific sub-component such as a new validation method as opposed to building
  an entirely new UI Component.
An easy
google
search or browsing through sites
  such as
jsfcentral.com
many usable and often
  free component libraries (and implementations) that can be experimented with.
  Some of the more popular and powerful ones include:
  • MyFaces - A general purpose and open source component library
        and implementation. -
    http://myfaces.apache.org

      
  • Oracle's ADF Faces - A rich library of useful JSF UI Components
        -
    http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/jsf/index.html
  • JScape's WebGalileo Faces -
    http://www.jscape.com/webgalileofaces/
       
      

    Once the decision has been made to build some custom components as opposed
      to just using some existing ones, here's how to get started.
    The "Moving Parts" of a JSF UI Component
    The term "JSF UI Component" is generally used to describe a set of
      sub-components which each which perform their own specific task such as rendering
      the component, validating its input, and/or performing any data conversions
      (such as a String to a Date conversion). This may often give the impression
      to a novice JSF developer that JSF component development is fairly complicated
      and possibly tedious, but this is also JSF's strength in that each UI Components'
      sub-components can be individually customized and re-configured into new and
      varied combinations. In fact it is JSF's flexible API and it's "pluggable
      renderering" technology which allows UI Components to written for multiple
      Web clients thus drastically decreasing the complexity for the Web developer
      of assembling multi-client Web applications. Let's review the various "moving
      parts" of what constitutes a JSF UI Component.
    The general term "JSF UI Component" refers to a collection of the
      following:
  • UIComponent Class - A Java class derived from either the UIComponentBase
        or extended from an existing JSF UIComponent such as outputText. This is the
        actual Java class representing the core logic of the component. It can optionally
        contain the logic to "render" itself to a client, or rendering logic
      can be separated into a separate "renderer" class.
  • Renderer Class - This is a class that only contains code to render
        a UIComponent. Rendering classes can provide different renderings for a UI
        Component. For such as either a button or hyperlink for the UICommand component.
        Renderers can also provide different rendering options for the same UI Component
        on different client types such as browsers, PDAs etc. This allows JSF
        the ability to run on any client device providing a corresponding set of renderer
      classes are built for the specific client type.
  • UI Component Tag Class - This is a JSP tag handler class that allows
        the UI Component to be used in a JSP. It can also associate a separate renderer
        class with a UIComponent class. (Note: The UI Component Tag handler class
        is only required for usage in a JSP deployment environment. Keep in mind that
      UI Components can also be used in non-JSP environments.)
  • Tag Library Descriptor File - This is a standard J2EE JSP tag library
        descriptor (tld) file which associates the tag handler class with a usable
      tag in a JSP page. (Required only For JSP usage only.)
  • Associated helper classes - These include a collection of standard
        (included in JSF RI) or custom helper classes such as Converters, Validators,
        ActionListeners etc., that can be programmatically bound to UI Components.
        For example a JSF UI Input Field component can be associated with a built-in
        number range Validator which ensures that an entered number is within a certain
        range. These helper classes can also be customized to perform any type of
        validation not provided out of the box with the JSF RI. For example a custom
        credit card Validator could be used with a JSF Input field to validate credit
        card numbers or a custom Converter could be used to convert currencies.

    A Simple "HelloWorld" Custom UI Component Example
    Before showing how to build a "Hello World" custom component, let's
      review quickly how to use it. To invoke the component we have a JSF enabled
      JSP page with an extra taglib directive specifying a custom tag library (tld)
      which contains the custom tag, "jsfhello", which is associated
      with our custom UI Component. To use the jsfhello tag, we simply place it into
      the body of the JSP and set an optional "hellomsg" attribute.
      
       

      
       
          
       
       
         
               
         A simple HelloWorld Custom Component:
                            
         The HelloWorld UI Component:
         
       
          
         
       
      
      
    When the page is run, the JSF UI Component displays the "Hello World"
      message provided in the "hellomsg" attribute along with the current
      date and time. We'll review the details of the tag library and how the tag handler
      class invokes the UI Component shortly, but first let's review how to build
      the core UI Component class.
    Building the"HelloWorld" Custom UI ComponentStep 1: Creating a UIComponent Class
    For our HelloWorld example, our UIComponent will extend the UIComponentBase
      abstract class, which is provided in the JSF specification, and render a formatted
      HelloWorld message. Note: We could have also based our new UI Component class
      on the concrete UIOutput base class which is basically the same as the UIComponentBase
      with the exception that it has a "value" attribute. Since we aren't
      using one, we'll simply base it on the UIComponentBase abstract class.
      
      
       
    package tss.hello;
    import java.util.Date;
    import javax.faces.component.UIComponentBase;
    import javax.faces.context.FacesContext;
    import java.io.IOException;
    import javax.faces.context.ResponseWriter;
    public class HelloUIComp extends UIComponentBase
    {
      public void encodeBegin(FacesContext context) throws IOException
      {
       ResponseWriter writer = context.getResponseWriter();
       String hellomsg = (String)getAttributes().get("hellomsg");
       
       writer.startElement("h3", this);
       if(hellomsg != null)
         writer.writeText(hellomsg, "hellomsg");
       else
         writer.writeText("Hello from a custom JSF UI Component!", null);           
       writer.endElement("h3");   
       writer.startElement("p", this);
       writer.writeText(" Today is: " + new Date(), null);
       writer.endElement("p");   
      }
    public String getFamily()
    {
      return "HelloFamily";
    }
    }  
           
           
    As you can see, this custom UI Component renders a formatted Helloworld message
      using and encodeBegin()getFamily(). This is actually required for UI Components that extend
      UIComponentBase since it could come from any component family. Since in our
      example we won't be creating a new family of components, we can just return
      any String value such as "HelloFamily". Before examing the code further,
      a quick note on encoding and decoding. method. Also notice that we have defined a method
      
    A Quick Note on Encoding Methods
    UI Components and/or associated renderer classes use encode*() methods
      display themselves to a client. The above HelloWorld example simply renders
      an HTML header (h3) with the custom hello message (if supplied) along with a
      paragraph containing the current date and time. For this component a single
      encodeBegin() (or encodeEnd() ) method is all that is needed to render the complete
      tag since it does not contain any children. The encodeBegin actually renders
      the beginning or the complete (bodiless) tag. UI Components with children tags/components
      will override encodeChildren() along with encodeEnd(). The encodeChildren()
      method allows children components to be rendered and encodeEnd() renders the
      closing parent tag.
    A Closer Look at the encodeBegin() Method
    Upon closer examination of the encodeBegin() method, we see that it receives
      the FacesContext as an argument. An extension to the servlet and JSP context,
      the FacesContext provides access to the many useful objects for JSF/JSP/Servlet
      development. In this example, we simply extract a "writer" object
      in order to "write" our rendered response back to the client.
      
       
          
           public void encodeBegin(FacesContext context) throws IOException { ResponseWriter
      writer = context.getResponseWriter();
       
      
    Next we get the value of the attribute "hellomsg" which is passed
      from the tag from our JSP page using getAttributes(). The getAttributes method
      comes from the UIComponentBase class which is the base class for all UI Components.
      
       
          String hellomsg = (String)getAttributes().get("hellomsg");
       
      
    Rendering the HTML message is done using the writer methods in the code:
      
       
          writer.startElement("h3", this);
       if(hellomsg != null)
         writer.writeText(hellomsg, "hellomsg");
       else
         writer.writeText("Hello from a custom JSF UI Component!", null);           
    writer.endElement("h3");   
    writer.startElement("p", this);
    writer.writeText(" Today is: " + new Date(), null);
    writer.endElement("p");   
      
    which when executed displays a formatted HTML "HelloWorld" message
      to the client.
    Note: You'll notice that when the attribute (hellomsg) or "property"
      is written to the client, an additional String value representing the name of
      the property "hellomsg" is also included as an argument to the writeText()
      method. The idea behind this is to provide development tools environments the
      ability to display the name of the property in a visual editor. Leaving the
      second argument null is also acceptable and will not harm the execution
      of the component.
    Step 2. Registering the custom UI Component in Faces-config.xml
    Before moving on to building a JSP tag handler and a TLD file, we'll add a
      required entry for our custom component in the faces-config.xml file. The syntax
      for adding our custom UI component is:

      
        ...
      
       tss.hello.JsfHello
       tss.hello.HelloUIComp
      

       ...
      
    The component-type is the "JSF recognized" name of our custom component:
      "tss.hello.JsfHello". (We'll refer to this later in our tag handler.)
      The component-class is the actual class path address of our UI Component.
    Step 3. Building a Custom JSP Tag Library
    In order to be able to use our custom component in a JSP, we need a custom
      tag library comprised of a tag library descriptor file (TLD) along with references
      to taghandlers classes. (This example uses just a single tag handler.)
    Building the Tag Handler
    For JSF component development, the JSP taghandler class is derived from javax.faces.webapp.UIComponentTag.
      It's main purpose is to:
  • Associate a JSP callable tag (handler class) with the UI Component.
  • Associate a separate renderer class (if needed) to the UI Component.
  • Set the properties from the submitted tag attribute values to the UI Component.
    Here is the source code for our tag handler class:
      
        package tss.hello;
    import javax.faces.application.Application;
    import javax.faces.webapp.UIComponentTag;
    import javax.faces.component.UIComponent;
    import javax.faces.el.ValueBinding;
    import javax.faces.context.FacesContext;
    public class FacesHelloTag extends UIComponentTag
    {
      // Declare a bean property for the hellomsg attribute.
      public String hellomsg = null;
      // Associate the renderer and component type.
      public String getComponentType() { return "tss.hello.JsfHello"; }
      public String getRendererType() { return null; }
      protected void setProperties(UIComponent component)
      {
        super.setProperties(component);
       
        // set hellomsg
        if (hellomsg != null)
        {
          if (isValueReference(hellomsg))
          {
            FacesContext context = FacesContext.getCurrentInstance();
            Application app = context.getApplication();
            ValueBinding vb = app.createValueBinding(hellomsg);
            component.setValueBinding("hellomsg", vb);                  
          }
          else
            component.getAttributes().put("hellomsg", hellomsg);
        }                        
      }
      public void release()
      {
        super.release();
        hellomsg = null;
      }
      public void setHellomsg(String hellomsg)
      {
        this.hellomsg = hellomsg;
      }
    }
      
    The first thing to note is the "hellomsg" bean property of type String
      along with its associated getter and setter methods at the bottom of the class.
      The hellomsg bean property, "hellomsg", is also an attribute in the
      JSP tag. ()
    Next we see two methods which associate this tag handler with our registered
      UI Component: "tss.hello.JsfHello" as well as associate the renderer.
      Since we don't have a separate renderer class, this statement returns a null
      value.
      
          
    // Associate the renderer and component type.
      public String getComponentType() { return "tss.hello.JsfHello"; }
      public String getRendererType() { return null; }
      
    The next method, setProperties(), sets the incoming values from the JSP tag
      by first calling the parent class' setProperties method along with custom code
      to set the value from the hellomsg tag attribute. Notice that a check is first
      done to see if the incoming attribute is a "ValueReference", which
      takes the form of a JSF EL expression: #{Bean.Property}. If a "ValueReference"
      is detected, it uses slightly different logic to set the application's value
      binding.
      
      
       
          protected void setProperties(UIComponent component)
      {
        super.setProperties(component);
       
       
        // set hellomsg
        if (hellomsg != null)
        {
          if (isValueReference(hellomsg))
          {
            FacesContext context = FacesContext.getCurrentInstance();
            Application app = context.getApplication();
            ValueBinding vb = app.createValueBinding(hellomsg);
            component.setValueBinding("hellomsg", vb);                  
          }
          else
            component.getAttributes().put("hellomsg", hellomsg);
        }         
      }
      
    Asides from the hellomsg getter and setter methods the only method required
      in the taghandler class is the release() method which resets the bean properties
      back to an unused state.
      
      
        public void release()
    {
    super.release();
    hellomsg = null;
    }
      
    and that's it for our tag handler class. Next we'll quickly review the JSP
      Tag Library Descriptor (TLD) required for this tag.
    Step 4. Building the Tag Library Descriptor File
    In order for us to use our custom JSP tag handler class, we need to create
      an associated TLD file which contains the tag entry associated with the tag
      handler class. Here is an example of the TLD file needed for this tag. The TLD
      associates the tag name, "jsfhello" with the tag class "tss.hello.FacesHelloTag"
      along with it's associated attributes. For our tag, we include our custom attribute,
      "hellomsg", along with the superclass' core attributes: "id",
      "binding" and "rendered".
      
      
       
    0.01
    1.2
    simple
    http://theserverside.com/simplefacescomponents
    This tag library contains simple JSF Component examples.
      
    jsfhello
    tss.hello.FacesHelloTag

    binding
    A value binding that points to a bean property


    id
    The client id of this component


    rendered
    Is this component rendered?

    hellomsg
    a custom message for the Component
      
    Following standard J2EE architecture, the custom TLD file is placed in the
      /WEB-INF/. sub-directory of the J2EE Web Module containing the application.
    Running the simple HelloWorld Example
    Just to review, our custom JSF component java classes must be compiled and
      available on the classpath of a J2EE Web Module. The Web Module must also have
      in it's class path the required JSF runtime jar files which include: jsf-api.jar,
      jsf-impl.jar along with the commons jar files (commons-beanutils.jar,
      commons-collections.jar, commons-digester.jar, commons-logging.jar).
      The other two required jar files come from JSTL (jstl.jar and standard.jar).
      
      For more info on the Commons and JSTL libraries refer to the Jakarta Apache
      Project website:
    http://jakarta.apache.org/

      .) For a runtime deployment, all the required jar files must be placed in the
      /WEB-INF/lib subdirectory of your J2EE Web Module.
    Assuming your runtime environment is properly configured, you can test the
      simple JSF Hello World custom component by first creating a JSF enabled JSP
      page and then adding the taglib directive and dropping the tag into your page.
      (As explained before..)
    When the JSF page is run, you will see the execution of your HelloWorld JSF
      Custom Component!

    Extending the HelloWorld Custom Component
    Now that we've created a simple HelloWorld component, we can now expand upon
      this very easily. One straightforward extension would be to make the HelloWorld
      component call a Web service for a specific stock symbol and print out it's
      value. So instead of providing a hellomsg, our tag/component attribute will
      contain a stock symbol. The renderer code will then query a stock quote Web
      service (made available to us via another class) with the symbol provided by
      the tag and print the current price in the response.
    Here's how to modify the HelloWorld Custom Component to display a live stock
      quote using a Web service.
    Create a Web Service Proxy Client
    In order to call a Web service from java, you'll need to create a proxy java
      client which enables any other Java class the ability to call a stock Web service.
      Many free stock quote Web services are available on the Internet. This example
      uses the "Delayed Stock Quote Service" available from Xmethods.com.
      The actual Web Proxy creation step is left to the reader to implement since
      it is out of the bounds of JSF development however several Java Integrated Development
      Environments such as Oracle JDeveloper, can automatically generate the necessary
      client code which enables communication to a Web service.

      Oracle JDeveloper 10.1.3 Preview's Web Service Proxy Wizard
    Once a Web service Proxy class is created, we'll modify our hellomsg attribute
      to become a stock symbol attribute and call the Web service with this value
      and then print it out. This involves the following changes:
    Create or Modify the HelloWorld UIComponent Class to Work with "Symbol"
      Attribute
    Change or create a new UIComponent class which refers to a stock symbol attribute,
      "symbol", instead of the "hellomsg".
      
      
        public class StockUIComp extends UIComponentBase
    {
      public void encodeEnd(FacesContext context) throws IOException
      {
       ResponseWriter writer = context.getResponseWriter();
       String symbol = (String)getAttributes().get("symbol");
    ...
      
    Note: If you create a new UI Component such as StockUIComp, don't forget to
      register it in your faces-config file ( You could use the name: "tss.hello.JsfStock"
      mapped to the classpath address "tss.hello.StockUIComp").
    Once you've retrieved the attribute value for the stock symbol, you can call
      your Web service proxy class to get the current price:
      
      
         //get stock price using generated Web service Proxy
      String stockprice = NetXmethodsServicesStockquoteStockQuotePortClient.getStockPrice(symbol);
      
    Rendering the the stock price is easily done with the following code:
      
          writer.startElement("p", this);
      if(symbol != null)
       writer.writeText("The stock price for " + symbol + " is: " + stockprice + ".", null);
      else
       writer.writeText("You must provide a Stock Symbol by setting the symbol attribute.", null);
      writer.endElement("p");
      
    The changes to the tag handler and TLD is a trivial search and replace of "hellomsg""
      with "symbol". Your tag handler class will also have to refer to the
      different Stock UI Component: "tss.helloJsfStock", but the remaining
      code in the taghandler is basically the same as before with the "symbol"
      attribute replacing the "hellomsg" attribute:
      
      
        public class StockTag extends UIComponentTag
    {
    public String symbol = null;
    public String getRendererType() { return null; }
    public String getComponentType() { return "tss.hello.JsfStock"; }
    protected void setProperties(UIComponent component)
      {
       super.setProperties(component);
       
      // set symbol
      if (symbol != null)
       {
        if (isValueReference(symbol))
         {
          FacesContext context = FacesContext.getCurrentInstance();
          Application app = context.getApplication();
          ValueBinding vb = app.createValueBinding(symbol);
          component.setValueBinding("symbol", vb);
         }
        else
         component.getAttributes().put("symbol", symbol);
    }
    ...
      
    Once you've updated your TLD with a new tag "simplestock" mapped
      to the taghandler "StockTag", you can then add the new tag to your
      JSP:
      
      
         The SimpleStock UI Component:
      
      
      
    Here's the output for the HelloWorld Component along with the new Stock UI
      Component:


    Extending the Stock UI Component Further
    Now that we've extended the HelloWorld UI Component into something useful,
      let's further extend the stock component to make it more user friendly. Our
      modified stock component will now render an input field along with a submit
      button. This will allow users to enter a new stock symbol at runtime as opposed
      to hardcoding the attribute value in the JSP source.

    This modification will introduce how to build a decode()encode()
      
    method to now render in input field along with a submit button. method which
      is used to "decode" the incoming form field values as opposed to simply
      retrieving tag attribute values. We will also extend our simple
    Back to the UI Component
    This time we'll name the UI Component "HtmlInputStock" following
      the JSF specification's naming convention. This time we'll extend extend the
      class from the UIInput component since it will be accepting input.
      
      
        public class HtmlInputStock extends UIInput
    {
    ...
      
    This component will have a more detailed encode() method. This time our encodeBegin()
      method will call separate encode methods to render the differerent elements:
      an input field, a submit button, and an output field which displays the returned
      price of the stock. Notice that I've add the identifiers ".inputbutton"
      and ".submitbutton" to the clientIds respectively when calling the
      encode methods. This will ensure that the names of the rendered HTML: fields
      will be unique on the client. In general this is good practice should you need
      to refer to the rendered name of the HTML field.
    The encodeBegin() method is as follows:
      
        public void encodeBegin(FacesContext context) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        String clientId = getClientId(context);
        encodeInputField(writer, clientId+".inputbutton");
        encodeSubmit(writer, clientId+".submitbutton");
        encodeOutputField(context);   
       }
      
    The encodeInputField() method is as follows:
      
         private void encodeInputField(ResponseWriter writer, String clientId)  throws IOException {
          // render a standard HTML input field
          writer.startElement("input", this);
          writer.writeAttribute("type", "text", null);
          writer.writeAttribute("name", clientId, "clientId");
          Object v = getValue();
          if (v != null)
             writer.writeAttribute("value", v.toString(), "value");
             
          writer.writeAttribute("size", "6", null);
          writer.endElement("input");
       }
      
    Notice the name of the input field is assigned the clientId. We'll use this
      later to identify the field when we decode the input.
    The encodeSubmit() is rendered with:
      
        private void encodeSubmit(ResponseWriter writer, String clientId)  throws IOException {
          // render a submit button
          writer.startElement("input", this);
          writer.writeAttribute("type", "Submit", null);
          writer.writeAttribute("name", clientId, "clientId");
          writer.writeAttribute("value", "Enter Stock Symbol", null);   
          writer.endElement("input");
       }
      
    And finally the encodeOutputField() which is similar to before:
      
        public void encodeOutputField(FacesContext context) throws IOException
      {
       
       ResponseWriter writer = context.getResponseWriter();
       String symbol = (String)getAttributes().get("value"); // The "value" attribute is used to pass the stock symbol.
       
       //get stock price
       String stockprice = NetXmethodsServicesStockquoteStockQuotePortClient.getStockPrice(symbol);
       
       writer.startElement("p", this);
       if(symbol != null)
         writer.writeText("The current price for " + symbol + " is: " + stockprice + ".", null);
       else
         writer.writeText("", null);        
       writer.endElement("p");   
      }
      
    Now let's move on to the decode() method who's job is to parse the incoming
      field values and act upon it.
      
      
         public void decode(FacesContext context) {
          Map requestMap = context.getExternalContext().getRequestParameterMap();
          String clientId = getClientId(context);
          try {
                   
          String string_submit_val = ((String) requestMap.get(clientId+".inputfield"));  
          setSubmittedValue(string_submit_val);  
          setValid(true);
          }
          catch(NumberFormatException ex) {
             // let the converter take care of bad input, but we still have
             // to set the submitted value, or the converter won't have
             // any input to deal with
             setSubmittedValue((String) requestMap.get(clientId));
          }
             
    }
      
    Let's review some of the key statements in our decode() method. First our decode()
      method obtains a requestMap from the JSF Context.
          Map requestMap = context.getExternalContext().getRequestParameterMap();
    The requestMap is a container which allows us to access the values submitted
      in the http request.
    The next statement extracts the clientId which is the unique identifier of
      the client issuing the request. (i.e. submitting the form)
      
      
              String clientId = getClientId(context);
      
    With the unique client identifier we can obtain the value of the submitted
      value contained in the requestMap for this client. We can then set the submittedValue
      to the value submitted in the form. Note: For this example, we are simply setting
      the value that was submitted as is, but in other cases we may wish to perform
      a conversion or validation on the submitted value before setting the value as
      "valid".
      
      
              try {               
          String string_submit_val = ((String) requestMap.get(clientId));      
          setSubmittedValue(string_submit_val);  
          setValid(true);
          }
          catch(NumberFormatException ex) {
             setSubmittedValue((String) requestMap.get(clientId));
          }
      
    That takes care of our new and improved UIComponent rendering (encoding and
      decoding). I'll leave out the step of registering this component in the faces-config
      and highlight the remaining trivial code modifications in the tag handler and
      the TLD.
    For the tag handler we have only minor changes. This tag handler as before
      extends from the same UIComponentTag but will have a bean property of "value"
      instead of "symbol". The "value" property is the value submitted
      in the input field and is handled exactly in the same manner before as the symbol.
      The only other difference from before is that our tag handler is now registered
      with the StockInput UI Component Class.
      
      
          public String getComponentType() { return "tss.hello.StockInput"; }
      
    The setProperties method is basically the same as before but operating on the
      "value" instead "symbol":
      
      
         protected void setProperties(UIComponent component)
      {
      super.setProperties(component);
      if (value != null)
        {
         if (isValueReference(value))
          {
            FacesContext context = FacesContext.getCurrentInstance();
            Application app = context.getApplication();
            ValueBinding vb = app.createValueBinding(value);
            component.setValueBinding("value", vb);                  
          }
          else
            component.getAttributes().put("value", value);
        }
      
    Updating the TLD
    Similar to before, the new TLD tag entry can be as follows:
      
        ...
    stockinput
    tss.hello.StockInputTag

    binding
    A value binding that points to a bean property


    id
    The client id of this component


    rendered
    Is this component rendered?

    value
    A value for submitted stock symbol..
    ....
      
    Running the Stock Input Component
    Invoking this component is done in a similar fashion as before where we simply
      add the tag to the page:
      
      
         
      
    Notice that we can leave the value attribute blank but specify it later when
      we run it. Once the page is running, enter a test stock symbol such as ORCL
      or AMZN and check out the result!

    Summary
    As you can see, building custom JSF UI Component is a fairly straightforward
      process. Once you understand the mechanism detailed in the encode() and decode()
      methods in the rendering code, the rest is a fairly trivial process of providing
      the necessary "plumbing" with tag handlers as such to enable usage
      in a typical client such as a JSP based client.
    Future articles on JSF Component development will also build upon these simple
      examples and show how to build other non visual JSF components such as Validators
      and Converters.
    Biography
    Chris Schalk is a Principal Product Manager and Evangelist for Oracle JDeveloper
      and is responsible for the Web application development features within JDeveloper.
      Prior to product management, Chris held positions in both software development
      and technical marketing at Oracle. Before Joining Oracle, he worked at IBM as
      a software developer. Chris holds a Bachelor's of Science in Applied Mathematics
      with a specialization in Computer Science from the University of California
      at Los Angeles.
    Chris has written numerous samples and articles for various publications including
      Javapro, Oracle Magazine and also maintains a popular Blog on J2EE Web development
    at:
    http://jroller.com/page/cschalk
    .

                   
                   
                   
                   
                   
                   
                   
                   
                   

    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/24141/showart_246374.html
  • 您需要登录后才可以回帖 登录 | 注册

    本版积分规则 发表回复

      

    北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
    未成年举报专区
    中国互联网协会会员  联系我们:huangweiwei@itpub.net
    感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

    清除 Cookies - ChinaUnix - Archiver - WAP - TOP