Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Using JSF technology for XForms applications

Faheem Khan (fkhan872@yahoo.com), Software Consultant, Independent
Faheem Khan is an independent software consultant specializing in enterprise application integration (EAI) and B2B solutions.

Summary:  Interested in learning how JavaServer Faces and XForms technology can work together in a server-side application? This comprehensive hands-on tutorial by Java enterprise developer Faheem Khan examines how XForms authoring requirements fit into the JSF architecture. The author begins with a solid overview of JSF technology, then identifies the tasks you must perform if you plan to use JSF technology for XForms authoring, and demonstrates the development of a JSF tag library capable of authoring XForms markup. Throughout the tutorial, he guides your learning with a sample application to help you see the concepts put to work in a real-world application. Note: This tutorial is comprehensive and will take a significant time investment to complete.

Date:  03 Feb 2005
Level:  Introductory PDF:  A4 and Letter (1440 KB | 200 pages)Get Adobe® Reader®

Activity:  14509 views
Comments:  

XForms-JSF tag library

Completing the XForms-JSF tag library

In this section, we will complete the XForms-JSF tag library and demonstrate the development of each JSF component in it.

In the previous section, we demonstrated the development of xforms-jsf:model, xforms-jsf:commandButton, and xforms-jsf:selectOneRadio components in detail. Now, without going into too much detail, we will discuss the development of the remaining components. We will only stick to the behavior and implementation specific to the components we are developing.

The following components are XForms-JSF tag library components we will develop:

  • xforms-jsf:selectOneMenu
  • xforms-jsf:selectOneListbox
  • xforms-jsf:selectManyListbox
  • xforms-jsf:selectManyCheckbox
  • xforms-jsf:selectManyMenu
  • xforms-jsf:inputText
  • xforms-jsf:inputSecret
  • xforms-jsf:inputTextarea

We will explain these components in detail shortly, but first, we'll give a brief description of each component. We'll also discuss the markup generated by the component and the expected interpretation by the XForms browser for the markup, how the JSP author uses the component in the JSP page, and the possible entries for the JSF tag in the TLD file. Finally, we'll discuss the implementation of the tag handler class associated with the tag. After the development of the tag handler class, we will implement the component class for the tag.


Implementing the xforms-jsf:selectOneMenu component

The xforms-jsf:selectOneMenu component is similar to the xforms-jsf:selectOneRadio component we developed in Implementing the xforms-jsf:selectOneRadio tag. The only difference is in the graphical appearance of the components in the XForms browser. The remaining features are the same as the xforms-jsf:selectOneRadio tag.

In the case of the xforms-jsf:selectOneRadio tag, each choice appears with a radio button, while the xforms-jsf:selectOneMenu tag choices appear in a menu list.

The xforms-jsf:selectOneMenu component renders the following markup:

<xforms:select1 ref="selectedColor" model="optModel"
   appearance="minimal" 
xmlns:xforms="http://www.w3.org/2002/xforms">
   <xforms:label>Choose a Color</xforms:label>
   <xforms:item>
     <xforms:label>Red</xforms:label>
     <xforms:value>Red</xforms:value>
   </xforms:item>
   <xforms:item>
     <xforms:label>White</xforms:label>
     <xforms:value>White</xforms:value>
   </xforms:item>
</xforms:select1>

Notice the value of the appearance attribute in the above markup ("minimal"). In the markup of xforms-jsf:selectOneRadio, the value of the appearance attribute was "full."

In the XForms browser, the above markup looks like the following:

Screen Shot

The JSP author codes the following elements to use the component in the JSP page:

<xforms-jsf:selectOneMenu value="#{dataStore.selectedColor}"
  ref="selectedColor" model="optModel">
  <f:selectItems value="#{dataStore.colorsList}"/>
</xforms-jsf:selectOneMenu>

The explanation of this JSP code is the same as for the selectOneRadiotag in implementingthejsfselectoneradiotag.

Let's start implementing the selectOneMenu tag.

The first step is to make an entry in the TLD file. The entries in the TLD files are the same as for the selectOneRadio tag. The only difference is between the entry in the name element and in the tag-class element. Look at the TLD file for selectOneMenu:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib>
  ..... 
  <tag>
    <name>selectOneMenu</name>
    <tag-class>xforms_jsf.Select1MenuTag</tag-class>
    <!-- remaining is same as listed for selectOneRadio -->
  </tag>
  <!-- other tag instances-->
</taglib>

In this TLD file, we mentioned that the tag-class element contains the xforms_jsf.Select1MenuTag class. We will implement this tag handler class.

Except for the appearance property of the component, most of the features are the same as for selectOneRadio in implementingthejsfselectoneradiotag. We will extend the Select1MenuTag class from Select1RadioTag and override only the setProperties() method. The following code shows the implementation of the Select1MenuTag class:

public class Select1MenuTag extends Select1RadioTag{
  public void setProperties(UIComponent component){
    super.setProperties(component);
    UISelect1 uis = (UISelect1)component;
    uis.getAttributes().put("appearance", "minimal");
  }//setProperties
}//Select1MenuTag

We first make a call to the same method of its base class that will perform the default functionality of the setProperties() method defined in the base class. Then we override the appearance property of the component with the "minimal" value.

The JSF component class we will associate with the selectOneMenu is UISelect1. It is the same component class we developed for the selectOneRadio component in Implementing the UISelect1 component.


Implementing the xforms-jsf:selectOneListbox component

The behavior of the xforms-jsf:selectOneListbox tag is similar to the xforms-jsf:selectOneRadio component we developed in Implementing the xforms-jsf:selectOneRadio tag. The only difference is in the graphical appearance of the components in the browser. The remaining aspects are similar to the xforms-jsf:selectOneRadio component. In the case of xforms-jsf:selectOneRadio, each choice appears with a radio button. In the case of xforms-jsf:selectOneMenu, the choices appear in a list box.

The xforms-jsf:selectOneListbox component we are going to implement renders the following markup:

<xforms:select1 ref="selectedColor" model="optModel"
  appearance="compact" xmlns:xforms="http://www.w3.org/2002/xforms">
  <xforms:label>Choose a Color</xforms:label>
  <xforms:item>
    <xforms:label>Red</xforms:label>
    <xforms:value>Red</xforms:value>
  </xforms:item>
  <xforms:item>
    <xforms:label>White</xforms:label>
    <xforms:value>White</xforms:value>
  </xforms:item>
</xforms:select1>

Notice the value of the appearance attribute in the above markup ("compact"). In the markup of xforms-jsf:selectOneRadio, the value of the appearance attribute was "full."

In the XForms browser, the above markup looks like the following:

Screen Shot

The JSP author codes the following elements to use the component in the JSP file:

<xforms-jsf:selectOneListbox value="#{dataStore.selectedColor}"
  ref="selectedColor" model="optModel">
  <f:selectItems value="#{dataStore.colorsList}"/>
</xforms-jsf:selectOneListbox>

The TLD file entry for the selectOneListbox tag is similar to the selectOneRadio tag:

<tag>
  <name>selectOneListbox</name>
  <tag-class>xforms_jsf.Select1ListTag</tag-class>
  <!-- remaining is same as listed for selectOneRadio -->
</tag>

In the above TLD file entry, the tag-class element contains the Select1ListTag class, which is the name of the tag handler class for the selectOneListbox tag. We will now implement the Select1ListTag class.

Like the selectOneMenu tag, the selectOneListbox tag is similar to the selectOneRadio tag, except for the appearance property. We will extend the tag handler class for selectOneListbox from Select1RadioTag, as we did earlier for the selectOneMenu tag. The following code shows the implementation of the Select1ListTag class:

public class Select1ListTag extends Select1RadioTag{
  public void setProperties(UIComponent component){
    super.setProperties(component);
    UISelect1 uis = (UISelect1)component;
    uis.getAttributes().put("appearance", "compact");
  }//setProperties
}//Select1ListTag

The JSF component class we will associate with the selectOneListbox is UISelect1. It is the same class that we developed for the selectOneRadio component in Implementing the UISelect1 component. There is no need to develop a separate component class, as the behavior of both components is the same.


Implementing the xforms-jsf:selectManyListbox component

The xforms-jsf:selectManyListbox component provides users with an option to select multiple choices from a list of given choices in a list box. It renders the XForms select element's markup.

The xforms-jsf:selectManyListbox component renders the following markup:

<xforms:select ref="selectedColors" model="optModel" 
  appearance="compact" xmlns:xforms="http://www.w3.org/2002/xforms">
  <xforms:label>Choose a Color</xforms:label>
  <xforms:item>
    <xforms:label>Red</xforms:label>
    <xforms:value>Red</xforms:value>
  </xforms:item>
  <xforms:item>
    <xforms:label>White</xforms:label>
    <xforms:value>White</xforms:value>
  </xforms:item>
</xforms:select>

In the XForms browser, the above markup looks like this:

Screen Shot

The JSP author codes the following elements to use the component in the JSP file:

<xforms-jsf:selectManyListbox ref="selectedColors" model="optModel"
  value="#{dataStore.selectedColors}">
  <f:selectItems value="#{dataStore.colorsList}"/>
</xforms-jsf:selectManyListbox>

The details of the attributes of this component are the same as the xforms-jsf:selectOneRadio component in Implementing the xforms-jsf:selectOneRadio tag. The only difference is between the value attribute of selectManyListbox. As we explained, that value is used by the component to set or get the JavaBeans property. The property that the JSP author passes in the value attribute for the selectManyListbox tag should be an array of the string object in the model bean (while in the case of the selectOneRadio tag, it was simply a string type property).

Now we will implement the selectManyListbox tag by making an entry in the TLD file to declare it. The entry looks like this:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib>
  ......
  <tag>
    <name>selectManyListbox</name>
    <tag-class>xforms_jsf.SelectListBoxTag</tag-class>
    <!-- JSF Specific Attributes -->
    <attribute>
      <name>value</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>valueChangeListener</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>rendered</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>id</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>binding</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>immediate</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>required</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <!-- XForms Attributes -->
    <attribute>
      <name> model </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>label</name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> navindex </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> accesskey </name>
      <required>false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> bind </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> ref </name>
      <required> true </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> selection  </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> incremental </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
  </tag>
  <!-other tag instances-->
</taglib>

In the above TLD file, we mentioned the tag handler xforms_jsf.SelectListBoxTag class in the tag-class element. Now we will implement the SelectListBoxTag class:

public class SelectListBoxTag extends UIComponentTag{
  private String value               = null;
  private String required            = null;
  private String immediate           = null;
  private String valueChangeListener = null;
  
  private String ref            = null;
  private String bind           = null;
  private String model          = null;
  private String label          = null;
  private String navindex       = null;
  private String accesskey      = null;
  private String selection      = null;
  private String incremental    = null;
  public String getRendererType(){
    return null;
  }
  public String getComponentType(){
    return "Select";
  }
  public void setValue(String valueRef) {
    this.value = valueRef;
  }
  public void setRequired(String required) {
    this.required = required;
  }
  public void setImmediate(String immediate) {
    this.immediate = immediate;
  }
  public void setValueChangeListener(String valueChangeListener) {
    this.valueChangeListener = valueChangeListener;
  }
  public void setRef(String ref) {
    this.ref = ref;
  }
  public void setBind(String bind) {
    this.bind = bind;
  }
  public void setModel(String model) {
    this.model = model;
  }
  public void setLabel(String label) {
    this.label = label;
  }
  public void setNavindex(String navindex) {
    this.navindex = navindex;
  }
  public void setAccesskey(String accesskey) {
    this.accesskey = accesskey;
  }
  public void setSelection(String selection) {
    this.selection = selection;
  }
  public void setIncremental(String incremental) {
    this.incremental = incremental;
  }
  public void setProperties(UIComponent component) {
    super.setProperties(component);
    UISelect uis = (UISelect)component;
    FacesContext fc = FacesContext.getCurrentInstance();
    Application app = fc.getApplication();
    if(required != null){
      if(UIComponentTag.isValueReference(required)){
        ValueBinding vb = app.createValueBinding(required);
        uis.setValueBinding("required", vb);
      } 
      else{
        boolean boolRequired = (new Boolean(required)).booleanValue();
        uis.setRequired(boolRequired);
      }
    }
    if(valueChangeListener != null){
      if(UIComponentTag.isValueReference(valueChangeListener)) {
        Class args[] = {
          javax.faces.event.ValueChangeEvent.class
        };
        MethodBinding mb =
          app.createMethodBinding(valueChangeListener, args);
        uis.setValueChangeListener(mb);
      } 
    }  
    if(immediate != null) {
      if(UIComponentTag.isValueReference(immediate)) {
        ValueBinding vb = app.createValueBinding(immediate);
        uis.setValueBinding("immediate", vb);
      } 
      else{
        boolean boolImmediate = 
          (new Boolean(immediate)).booleanValue();
        uis.setImmediate(boolImmediate);
      }
    }
    if(value != null) {
      if(UIComponentTag.isValueReference(value)) {
        ValueBinding vb = app.createValueBinding(value);
        uis.setValueBinding("value", vb);
      } 
        uis.setValue(value);
    }
    if(ref != null)
      uis.getAttributes().put("ref", ref);
    if(bind != null)
      uis.getAttributes().put("bind", bind);
    if(label != null)
      uis.getAttributes().put("label", label);
    if(model != null)
      uis.getAttributes().put("model", model);
    if(navindex != null)
      uis.getAttributes().put("navindex", navindex);
    if(accesskey != null)
      uis.getAttributes().put("accesskey", accesskey);
    if(selection != null)
      uis.getAttributes().put("selection", selection);
    if(incremental != null)
      uis.getAttributes().put("incremental", incremental);
    uis.getAttributes().put("appearance", "compact");
  }//setProperties
}//SelectListBoxTag

This code is exactly like the code used in Implementing the xforms-jsf:model component, so we won't explain it here.

Now we'll discuss the JSF component class associated with the xforms-jsf:selectManyListbox tag.

UISelect is the component class we will associate with the xforms-jsf:selectManyListbox tag. The UISelect component is similar to the UISelect1 component discussed in Implementing the UISelect1 component. We extended the UISelect class from UISelect1, which is part of the JSF's HTML tag library.

The following code shows the methods in the UISelect class:

public class UISelect extends UISelect1{
  public void encodeEnd(FacesContext fc)
    throws IOException{
  }
  private String[] getNewValues(Document doc, String tag){
  }
}//UISelect

The UISelect class overrides the encodeEnd() method and implements a new helper method named getNewValues().

The encodeEnd() method is similar to the same method in the UISelect1 class, except that it renders a different markup.

The getNewValues() helper method returns the values selected by the user, after fetching from the XML request. We need this method because the values selected by the user come as an array of strings in which each individual string is separated from the other by a space. The getNewValues() method parses the user's data and returns it in the form of a String[].

The decode() method calls the getNewValues() method, passing it the Document object (that contains the request) and the name of the XML tag that wraps values selected by the user:

private String[] getNewValues(Document doc, String tag){
  String[] newValues = null;
  NodeList nl = doc.getElementsByTagName(tag);
  if (nl != null){
    Node tags = null;
    int length = nl.getLength();
    for(int i=0; i<length ; i++){
      tags = nl.item(i);
      NodeList children = tags.getChildNodes();
      if (children == null)
        break;
      if(children.item(i) == null)
        break;
      String values = children.item(i).getNodeValue();
      if(values == null)
        break;
      int spaceCounter = 0;
      int j = -1;
      while(true) {
        j = values.indexOf(" ", j + 1);
        if(j == -1){
          spaceCounter++;
          break;
        }
        else
          spaceCounter++;
      }
      newValues = new String[spaceCounter];
      int index = 0;
      for(int k = 0 ; values.length() > 0 ; k++){
        k = values.indexOf(" ");
        if(k != -1){
          newValues[index++] = values.substring(0,k);
          values = values.substring(k+1);
        }
        else{
          newValues[index] = values.substring(0);
          break;
        }
      }//for(int k = 0 ; values.length() > 0 ; k++)
    }//for(int i=0; i<length ; i++)
  }//if (nl != null)
  return newValues;
}//getNewValues

Notice the following points in this code:

  1. It retrieves the node (from the Document) that wraps the new values.

  2. It retrieves the contents of the node fetched in step 1 (the list of choices selected by the user).

  3. Because this component lets users select more than one choice at a time, a space separates each choice in the node fetched in step 2.

  4. The getNewValues() method extracts each choice and places it in an array of string type, then returns the array.

Now look at the following code, which shows the decode method implementation:

public void decode(FacesContext fc) {
  if(fc == null)
     throw new NullPointerException();
  String tag      = null;
  String[] newValue = null;
  String ref      = (String) getAttributes().get("ref");
  String bind     = (String) getAttributes().get("bind");
  String clientId = getClientId(fc);
  if(bind == null)
    tag = ref;
  else
    tag = bind;
  Document doc = (Document) getModelBeanObject
     ("#{incomingXMLInstanceRequest.DOMDocument}", fc);
  if(doc != null) {
    newValue = getNewValues(doc, tag);
  }
  if(newValue == null)
    setSubmittedValue(new String[0]);
  else
    setSubmittedValue(newValue);
  setValid(true);
}//decode

Now you can use this component with any JSF application after making an entry in the faces-config.xml file:

<component>
  <component-type>Select</component-type>
  <component-class>xforms_jsf.UISelect</component-class>
</component>


Implementing the xforms-jsf:selectManyCheckbox component

The behavior of the xforms-jsf:selectManyCheckbox component is similar to selectManyListbox. The only difference is between the appearances of both the components. This component provides users with an option to select one or more check boxes from a list of check boxes (each check box represents a choice).

The xforms-jsf:selectManyCheckbox tag renders the following markup:

<xforms:select ref="selectedColors" model="optModel" 
  appearance="full" xmlns:xforms=  "http://www.w3.org/2002/xforms">
  <xforms:label>Choose a Color</xforms:label>
  <xforms:item>
    <xforms:label>Red</xforms:label>
    <xforms:value>Red</xforms:value>
  </xforms:item>
  <xforms:item>
    <xforms:label>White</xforms:label>
    <xforms:value>White</xforms:value>
  </xforms:item>
</xforms:select>

The only difference between the markups of the xforms-jsf: selectManyCheckbox and xforms-jsf:selectManyListbox tags is the appearance attribute.

In the XForms browser, the above markup looks like the following:

Screen Shot

The JSP author codes the following elements to use the tag in the JSP file:

<xforms-jsf:selectManyCheckbox ref="selectedColors"
  value="#{dataStore.selectedColors}" model="optModel">
  <f:selectItems value="#{dataStore.colorsList}"/>
</xforms-jsf:selectManyCheckbox>

Now let's start implementing the selectManyCheckbox tag. Its TLD entry:

<tag>
  <name>selectManyCheckbox</name>
  <tag-class>xforms_jsf.SelectCheckListTag</tag-class>
  <!-- remaining is same as listed for selectManyListbox -->
</tag>

In the above TLD file, we mentioned <tag-class>xforms_jsf.SelectCheckListTag</tag-class>. We will implement this tag handler class.

As explained earlier, the selectManyCheckbox and selectManyListbox components are similar. The only difference is the appearance of the components, which are controlled by the appearance property of the component.

We extend the tag handler class for this component from SelectListBoxTag, which is the tag handler class for the selectManyListbox component (explained in the previous section), and override the setProperties() method, which only sets the appearance property for the component.

The following code shows the implementation of the SelectCheckListTag class, which represents the selectManyCheckbox tag:

public class SelectCheckListTag extends SelectListBoxTag{
  public void setProperties(UIComponent component){
    super.setProperties(component);
    UISelect uis = (UISelect)component;
    uis.getAttributes().put("appearance", "full");
 }
}//SelectCheckListTag

In the setProperties() method, we first make a call to the same method of its base class that performs the default functionality of the setProperties() method defined in the base class, then we override the appearance property of the component with "full."

The component class for this JSF tag is UISelect, the same as for selectManyListbox.


Implementing the xforms-jsf:selectManyMenu component

The xforms-jsf:selectManyMenu component provides users with an option to select check boxes from a tree of check boxes (in the tree, each node has a check box and a label. Each node represents a choice).

The xforms-jsf:selectManyMenu component renders the following markup:

<xforms:select ref="selectedColors" model="optModel" 
  appearance = "minimal" 
xmlns:xforms="http://www.w3.org/2002/xforms">
  <xforms:label>Choose a Color</xforms:label>
  <xforms:item>
    <xforms:label>Red</xforms:label>
    <xforms:value>Red</xforms:value>
  </xforms:item>
  <xforms:item>
    <xforms:label>White</xforms:label>
    <xforms:value>White</xforms:value>
  </xforms:item>
</xforms:select>

If you compare the markups generated by the xforms-jsf:selectManyMenu and xforms-jsf:selectManyListbox components, you will see that the difference is only in the value of the appearance attribute.

In the XForms browser, the above markup looks like the following:

Screen Shot

The JSP author codes the following elements to use the component in the JSP file:

<xforms-jsf:selectManyMenu  value="#{dataStore.selectedColors}"
  ref="selectedColors" model="optModel">
  <f:selectItems value="#{dataStore.colorsList}"/>
</xforms-jsf:selectManyMenu>

The TLD file entry for the selectManyMenu tag:

<tag>
  <name>selectManyCheckbox</name>
  <tag-class>xforms_jsf.SelectMenuTag</tag-class>
  <!-- remaining is same as listed for selectManyListbox -->
</tag>

In the above TLD file, we mentioned <tag-class>xforms_jsf.SelectMenuTag</tag-class>. Now we will implement this tag handler class.

The following code shows the implementation of the SelectMenuTag class, which represents the selectManyMenu tag:

public class SelectMenuTag extends SelectListBoxTag{
  public void setProperties(UIComponent component){
    super.setProperties(component);
    UISelect uis = (UISelect)component;
    uis.getAttributes().put("appearance", "minimal");
  }
}//SelectMenuTag

In the setProperties() method, we first make a call to the same method of its base class, which performs the default functionality of the setProperties() method defined in the base class. We then override the appearance property of the component with "minimal."

As before, we can use the UISelect component class for this tag.


Implementing the xforms-jsf:inputText component

The xforms-jsf:inputText component provides the user with an input box to enter text into it. In addition, xforms-jsf:inputText renders the following markup:

<xforms:input ref="name" model="optModel" 
  xmlns:xforms=  "http://www.w3.org/2002/xforms">
  <xforms:label>Name</xforms:label>
  <xforms:hint>Please enter your name.</xforms:hint>
</xforms:input>

In the above markup, the XForms hint element is used. In the hint element, you can wrap a description about the text to enter. For example, in the markup shown above, the label is "Name." When the user rolls the mouse on the input box, the hint is displayed to the user.

In the XForms browser, the above markup looks like the following:

Screen Shot

The JSP author codes the following elements to use the component in the JSP file:

<xforms-jsf:inputText value="#{customerData.name}" ref="name" 
  model="optModel">
</xforms-jsf:inputText>

The component saves the user data in the bean property passed in the value attribute.

Let's start implementing the xforms-jsf:inputText component. The first step is to make a new tag entry in the TLD file. The tag entry in the TLD file for xforms-jsf:inputText looks like the following:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib>
  ..... 
  <tag>
    <name>inputText</name>
    <tag-class>xforms_jsf.InputBoxTag</tag-class>
    <!-- JSF Specific Attributes -->
    <attribute>
      <name>value</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>valueChangeListener</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>rendered</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>id</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>binding</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>immediate</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>required</name>
      <required>false</required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
  <!-- XForms Attributes --> 
    <attribute>
      <name> model </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name>label</name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> navindex </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> accesskey </name>
      <required>false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> bind </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> hint </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> ref </name>
      <required> true </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> inputmode  </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> incremental </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
    <attribute>
      <name> appearance </name>
      <required> false </required>
      <rtexprvalue> false </rtexprvalue>
    </attribute>
  </tag>
  <!-other tag instances-->
</taglib>

In the above TLD file, we mentioned <tag-class>xforms_jsf.InputBoxTag</tag-class>. Now let's implement this tag handler class.

The following code shows the implementation of the InputBoxTag class:

public class InputBoxTag extends UIComponentTag{
  protected String value               = null;
  protected String required            = null;
  protected String immediate           = null;
  protected String valueChangeListener = null;
  
  protected String ref            = null;
  protected String bind           = null;
  protected String hint           = null;
  protected String model          = null;
  protected String label          = null;
  protected String navindex       = null;
  protected String accesskey      = null;
  protected String inputmode      = null;
  protected String appearance     = null;
  protected String incremental    = null;
  public String getRendererType(){
    return null;
  }
  public String getComponentType(){
    return "InputBox";
  }
  public void setRef(String ref){
    this.ref = ref;
  }
  public void setBind(String bind){
    this.bind = bind;
  }
  public void setHint(String hint){
    this.hint = hint;
  }
  public void setModel(String model){
    this.model = model;
  }
  public void setLabel(String label){
    this.label = label;
  }
  public void setValue(String valueRef){
    this.value = valueRef;
  }
  public void setNavindex(String navindex){
    this.navindex = navindex;
  }
  public void setAccesskey(String accesskey){
    this.accesskey = accesskey;
  }
  public void setInputmode(String inputmode){
    this.inputmode = inputmode;
  }
  public void setAppearance(String appearance){
    this.appearance = appearance;
  }
  public void setIncremental(String incremental){
    this.incremental = incremental;
  }
  public void setProperties(UIComponent component){
    super.setProperties(component);
    UIInputBox uib = (UIInputBox)component;
    FacesContext fc = FacesContext.getCurrentInstance();
    Application app = fc.getApplication();
    if(required != null) {
      if(UIComponentTag.isValueReference(required)) {
        ValueBinding vb = app.createValueBinding(required);
        uib.setValueBinding("required", vb);
      } 
      else{
        boolean boolRequired = (new Boolean(required)).booleanValue();
        uib.setRequired(boolRequired);
      }
    }
    if(valueChangeListener != null){
      if(UIComponentTag.isValueReference(valueChangeListener)){
        Class args[] = {
           javax.faces.event.ValueChangeEvent.class
        };
        MethodBinding mb =
           app.createMethodBinding(valueChangeListener, args);
        uib.setValueChangeListener(mb);
      } 
    }  
    if(immediate != null){
      if(UIComponentTag.isValueReference(immediate)){
        ValueBinding vb = app.createValueBinding(immediate);
        uib.setValueBinding("immediate", vb);
      } 
      else{
        boolean boolImmediate = 
          (new Boolean(immediate)).booleanValue();
        uib.setImmediate(boolImmediate);
      }
    }
    if(value != null){
      if(UIComponentTag.isValueReference(value)){
        ValueBinding vb = app.createValueBinding(value);
        uib.setValueBinding("value", vb);
      } 
      else
        uib.setValue(value);
    }
    if(ref != null)
      uib.getAttributes().put("ref", ref);
    if(bind != null)
      uib.getAttributes().put("bind", bind);
    if(hint != null)
      uib.getAttributes().put("hint", hint);
    if(label != null)
      uib.getAttributes().put("label", label);
    if(model != null)
      uib.getAttributes().put("model", model);
    if(navindex != null)
      uib.getAttributes().put("navindex", navindex);
    if(accesskey != null)
      uib.getAttributes().put("accesskey", accesskey);
    if(inputmode != null)
      uib.getAttributes().put("inputmode", inputmode);
    if(appearance != null)
      uib.getAttributes().put("appearance", appearance);
    if(incremental != null)
      uib.getAttributes().put("incremental", incremental);
  }//setProperties
}//InputBoxTag

Now let's implement the JSF component class associated with xforms-jsf:inputText.

The UIInputBox is the component class we associate with xforms-jsf:inputText. We extend UIInputBox from UISelect1:

public class UIInputBox extends UISelect1{
  public void encodeEnd(FacesContext fc) throws IOException{
    if(fc == null)
      throw new NullPointerException();
    if(!isRendered())
      return;
    String ref         = (String) getAttributes().get("ref");
    String bind        = (String) getAttributes().get("bind");
    String hint        = (String) getAttributes().get("hint");
    String model       = (String) getAttributes().get("model");
    String label       = (String) getAttributes().get("label");
    String navindex    = (String) getAttributes().get("navindex");
    String inputmode   = (String) getAttributes().get("inputmode");
    String accesskey   = (String) getAttributes().get("accesskey");
    String appearance  = (String) getAttributes().get("appearance");
    String incremental = (String) getAttributes().get("incremental");
    ResponseWriter out = fc.getResponseWriter();
    out.write("<xforms:input ref=\"" + ref +"\"");
    if(bind != null)
      out.write(" bind=\""+ bind + "\"");
    if(model != null)
      out.write(" model=\""+ model + "\"");
    if(navindex != null)
      out.write(" navindex=\""+ navindex + "\"");
    if(inputmode != null)
      out.write(" inputmode=\""+ inputmode + "\"");
    if(accesskey != null)
      out.write(" accesskey=\""+ accesskey + "\"");
    if(appearance != null)
      out.write(" appearance=\""+ appearance + "\"");
    if(incremental != null)
      out.write(" incremental=\""+ incremental + "\"");
    out.write(" xmlns:xforms=\"http://www.w3.org/2002/xforms\">");
    if(label != null)
      out.write("<xforms:label>" + label + 
"</xforms:label>");
    else
      out.write("<xforms:label>" + "Enter data  " + 
"</xforms:label>");
    if(hint != null)
      out.write("<xforms:hint>" + hint + "</xforms:hint>");
    out.write("</xforms:input>");
  }//encodeEnd
}//UIInputBox

The UIInputBox class only overrides the encodeEnd() method of the UISelect1 class to render its own markup. The reason is because the markup rendered is different from the parent class, but the behavior of the tag is not different. It has to manage only one string coming from the user.

Now you can use this component with any JSF application after an entry in the faces-config.xml file:

<component>
  <component-type>InputBox</component-type>
  <component-class>xforms_jsf.UIInputBox</component-class>
</component>


Implementing the xforms-jsf:inputSecret component

The xforms-jsf:inputSecret component provides the user with an input box to enter text in a nonreadable form.

The xforms-jsf:inputSecret renders the following markup:

<xforms:secret ref="password" model="optModel" 
  xmlns:xforms=  "http://www.w3.org/2002/xforms">
  <xforms:label>Password</xforms:label>
  <xforms:hint>Pls. Enter password here.</xforms:hint>
</xforms:secret>

In the XForms browser, the above markup looks like the following:

Screen Shot

The JSP author codes the following elements to use the component in the JSP file.

<xforms-jsf:inputSecret value="#{customerData.pwd}" ref="password" 
  model="optModel">
</xforms-jsf:inputSecret>

The component saves the user's password in the bean property passed in the value attribute.

The TLD file for xforms-jsf:inputSecret looks like the following:

<tag>
  <name>inputSecret</name>
  <tag-class>xforms_jsf.InputSecretTag</tag-class>
  <!-- Remaining is same as implemented for inputText-->
</tag>

In the above TLD file, we mentioned <tag-class>xforms_jsf.InputSecretTag</tag-class>. Now let's implement this tag handler class.

Next, we'll implement the tag handler class for xforms-jsf:inputSecret. The attributes for the inputSecret tag are the same as were defined for the inputText tag. We extended the tag handler class for inputSecret from InputBoxTag that is implemented for the inputText tag in the previous topic. The following code shows the implementation of the InputSecretTag class:

public class InputSecretTag extends InputBoxTag{
  public String getComponentType(){
    return "InputSecret";
  }
  public void setProperties(UIComponent component){
    super.setProperties(component);
    UIInputSecret uis = (UIInputSecret)component;
    FacesContext fc = FacesContext.getCurrentInstance();
    Application app = fc.getApplication();
    if(required != null) {
      if(UIComponentTag.isValueReference(required)) {
        ValueBinding vb = app.createValueBinding(required);
        uis.setValueBinding("required", vb);
      } 
      else{
        boolean boolRequired = (new Boolean(required)).booleanValue();
        uis.setRequired(boolRequired);
      }
    }
    if(valueChangeListener != null) {
      if(UIComponentTag.isValueReference(valueChangeListener)){
        Class args[] = {
           javax.faces.event.ValueChangeEvent.class
        };
        MethodBinding mb = 
          app.createMethodBinding(valueChangeListener, args);
        uis.setValueChangeListener(mb);
      } 
    }  
    if(immediate != null) {
      if(UIComponentTag.isValueReference(immediate)) {
        ValueBinding vb = app.createValueBinding(immediate);
        uis.setValueBinding("immediate", vb);
      } 
      else{
        boolean boolImmediate = 
          (new Boolean(immediate)).booleanValue();
        uis.setImmediate(boolImmediate);
      }
    }
    if(value != null) {
      if(UIComponentTag.isValueReference(value)) {
        ValueBinding vb = app.createValueBinding(value);
        uis.setValueBinding("value", vb);
      } 
      else
        uis.setValue(value);
    }
    if(ref != null)
      uis.getAttributes().put("ref", ref);
    if(bind != null)
      uis.getAttributes().put("bind", bind);
    if(hint != null)
      uis.getAttributes().put("hint", hint);
    if(label != null)
      uis.getAttributes().put("label", label);
    if(model != null)
      uis.getAttributes().put("model", model);
    if(navindex != null)
      uis.getAttributes().put("navindex", navindex);
    if(accesskey != null)
      uis.getAttributes().put("accesskey", accesskey);
    if(inputmode != null)
      uis.getAttributes().put("inputmode", inputmode);
    if(appearance != null)
      uis.getAttributes().put("appearance", appearance);
    if(incremental != null)
      uis.getAttributes().put("incremental", incremental);
  }//setProperties
}//InputSecretTag

The InputSecretTag class overrides the getComponentType() and setProperties() methods of the InputBoxTag class. The getComponentType() method returns the type of component associated with the xforms-jsf:inputSecret tag.

Now we will discuss the JSF component class associated with xforms-jsf:inputSecret.

UIInputSecret is the component class we associated with xforms-jsf:inputSecret. We extended the UIInputSecret class from the UIInputBox class:

public class UIInputSecret extends UIInputBox{
  public void encodeEnd(FacesContext fc) throws IOException{
    if(fc == null)
       throw new NullPointerException();
    if(!isRendered())
      return;
    String ref         = (String) getAttribute("ref");
    String bind        = (String) getAttribute("bind");
    String hint        = (String) getAttribute("hint");
    String model       = (String) getAttribute("model");
    String label       = (String) getAttribute("label");
    String navindex    = (String) getAttribute("navindex");
    String accesskey   = (String) getAttribute("accesskey");
    String inputmode   = (String) getAttribute("inputmode");
    String appearance  = (String) getAttribute("appearance");
    String incremental = (String) getAttribute("incremental");
    ResponseWriter out = fc.getResponseWriter();
    out.write("<xforms:secret ref=\"" + ref +"\"");
    if(bind != null)
       out.write(" bind=\""+ bind + "\"");
    if(model != null)
       out.write(" model=\""+ model + "\"");
    if(navindex != null)
       out.write(" navindex=\""+ navindex + "\"");
    if(inputmode != null)
       out.write(" inputmode=\""+ inputmode + "\"");
    if(accesskey != null)
       out.write(" accesskey=\""+ accesskey + "\"");
    if(appearance != null)
       out.write(" appearance=\""+ appearance + "\"");
    if(incremental != null)
       out.write(" incremental=\""+ incremental + "\"");
    out.write(" xmlns:xforms=\"http://www.w3.org/2002/xforms\">");
    if(label != null)
       out.write("<xforms:label>" + label + 
"</xforms:label>");
    else
       out.write("<xforms:label>"+"Enter Secret:"+ 
"</xforms:label>");
    if(hint != null)
       out.write("<xforms:hint>" + hint + 
"</xforms:hint>");
    out.write("</xforms:secret>");
  }//encodeEnd
}//UIInputSecret

The UIInputSecret class extends the UIInputBox class and overrides the encodeEnd() method, which renders the markup for the XForms secret element.

After implementing the UIInputSecret class, you can use this component with any JSF application after an entry in the faces-config.xml file:

<component>
  <component-type>InputSecret</component-type>
  
<component-class>xforms_jsf.UIInputSecret</component-class>
</component>


Implementing the xforms-jsf:inputTextarea component

The xforms-jsf:inputTextarea component provides the user with an edit box to enter multiple lines of text and renders the following markup:

<xforms:textarea ref="comments" model="optModel" 
  xmlns:xforms=  "http://www.w3.org/2002/xforms">
  <xforms:label>Comments</xforms:label>
  <xforms:hint>Please enter your comments.</xforms:hint>
</xforms:textarea>

In the XForms browser, the above markup looks like the following:

Screen Shot

The JSP author codes the following elements to use the component in the JSP page.

<xforms-jsf:inputTextarea value="#{customerData.comments}" 
  ref="comments" model="optModel">
</xforms-jsf:inputTextarea>

The component saves the text entered by the user in the model bean property passed in the value attribute.

The TLD file entry for the xforms-jsf:inputTextarea tag looks like the following markup:

<tag>
  <name>inputTextarea</name>
  <tag-class>xforms_jsf.InputTextAreaTag</tag-class>
  <!-- Remaining is same as implemented for inputText-->
</tag>

In the above TLD file, we mentioned <tag-class>xforms_jsf.InputTextAreaTag</tag-class>. Now let's implement this tag handler class.

The attributes for the inputTextarea tag are the same as defined for inputText. We extended the InputTextAreaTag tag handler class from the InputBoxTag class implemented for the inputText tag. The following code shows the implementation of the InputTextAreaTag class:

public class InputTextAreaTag extends InputBoxTag{
  public void setProperties(UIComponent component){
    super.setProperties(component);
    UIInputTextArea uita = (UIInputTextArea)component;   
    FacesContext fc = FacesContext.getCurrentInstance();
    Application app = fc.getApplication();
    if(required != null) {
      if(UIComponentTag.isValueReference(required)) {
        ValueBinding vb = app.createValueBinding(required);
        uita.setValueBinding("required", vb);
      } 
      else{
        boolean boolRequired = (new Boolean(required)).booleanValue();
        uita.setRequired(boolRequired);
      }
    }
    if(valueChangeListener != null) {
      if(UIComponentTag.isValueReference(valueChangeListener)){
        Class args[] = {
           javax.faces.event.ValueChangeEvent.class
        };
        MethodBinding mb = 
          app.createMethodBinding(valueChangeListener, args);
        uita.setValueChangeListener(mb);
      } 
    }  
    if(immediate != null) {
      if(UIComponentTag.isValueReference(immediate)) {
        ValueBinding vb = app.createValueBinding(immediate);
        uita.setValueBinding("immediate", vb);
      } 
      else{
        boolean boolImmediate = 
         (new Boolean(immediate)).booleanValue();
        uita.setImmediate(boolImmediate);
      }
    }
    if(value != null) {
      if(UIComponentTag.isValueReference(value)) {
        ValueBinding vb = app.createValueBinding(value);
        uita.setValueBinding("value", vb);
      } 
      else
        uita.setValue(value);
    }
    if(ref != null)
      uita.getAttributes().put("ref", ref);
    if(bind != null)
      uita.getAttributes().put("bind", bind);
    if(hint != null)
      uita.getAttributes().put("hint", hint);
    if(label != null)
      uita.getAttributes().put("label", label);
    if(model != null)
      uita.getAttributes().put("model", model);
    if(navindex != null)
      uita.getAttributes().put("navindex", navindex);
    if(accesskey != null)
      uita.getAttributes().put("accesskey", accesskey);
    if(inputmode != null)
      uita.getAttributes().put("inputmode", inputmode);
    if(appearance != null)
      uita.getAttributes().put("appearance", appearance);
    if(incremental != null)
      uita.getAttributes().put("incremental", incremental);
  }//setProperties
}//InputTextAreaTag

Now let's discuss the UIInputTextArea component class associated with xforms-jsf:inputTextarea:

public class UIInputTextArea extends UIInputBox{
  public void encodeEnd(FacesContext fc) throws IOException{
    if(fc == null)
       throw new NullPointerException();
    if(!isRendered())
      return;
    String ref         = (String) getAttributes().get("ref");
    String bind        = (String) getAttributes().get("bind");
    String hint        = (String) getAttributes().get("hint");
    String model       = (String) getAttributes().get("model");
    String label       = (String) getAttributes().get("label");
    String navindex    = (String) getAttributes().get("navindex");
    String inputmode   = (String) getAttributes().get("inputmode");
    String accesskey   = (String) getAttributes().get("accesskey");
    String appearance  = (String) getAttributes().get("appearance");
    String incremental = (String) getAttributes().get("incremental");
    ResponseWriter out = fc.getResponseWriter();
    out.write("<xforms:textarea ref=\"" + ref +"\"");
    if(bind != null)
       out.write(" bind=\""+ bind + "\"");
    if(model != null)
       out.write(" model=\""+ model + "\"");
    if(navindex != null)
       out.write(" navindex=\""+ navindex + "\"");
    if(inputmode != null)
       out.write(" inputmode=\""+ inputmode + "\"");
    if(accesskey != null)
       out.write(" accesskey=\""+ accesskey + "\"");
    if(appearance != null)
       out.write(" appearance=\""+ appearance + "\"");
    if(incremental != null)
       out.write(" incremental=\""+ incremental + "\"");
    out.write(" xmlns:xforms=\"http://www.w3.org/2002/xforms\">");
    
    if(label != null)
       out.write("<xforms:label>" + label + 
"</xforms:label>");
    else
       out.write("<xforms:label>"+" Enter Message 
"+"</xforms:label>");
    if(hint != null)
       out.write("<xforms:hint>" + hint + 
"</xforms:hint>");
    out.write("</xforms:textarea>");
  }//encodeEnd
}//UIInputTextArea

The UIInputTextArea class extends the UIInputBox class. The UIInputTextArea class only overrides the encodeEnd() method, which renders the markup for the XForms text area element.

The UIInputBox class renders a text box, which takes a single line string as input. On the other hand, the UIInputTextArea class renders a text area, which can take multiple lines of text as input. Whether it is a single line or a number of lines, it is always a string (a multiple line string contains "\r" and "\n" characters at the end of each line). We can treat both types of strings the same. That's why the UIInputTextArea class does not override the decode() method of the parent class.

Now we can use the UIInputTextArea component with any JSF application after including the component entry in the faces-config.xml file:

<component>
  <component-type>InputSecret</component-type>
  
<component-class>xforms_jsf.UIInputSecret</component-class>
</component>

By implementing the UIInputTextArea component, our XForms-JSF tab library is complete. In the next section, we will see how to compile a tag library in a JAR file.


How to distribute tag libraries

To distribute a tag library, you have to compile its components in a JAR file. The JAR file (compiled tag library) should contain the following information:

  • The compiled tag handler, component, and model bean classes of a tag library in their respective packages

  • The configuration files (faces-config.xml) and TLD file in a folder named META-INF

To create the JAR file, place the compiled classes and META-INF folder in a single folder (such as the XForms-JSF folder, which you will find when you unzip the section7.zip file; see Resources.

Run the following command in the command prompt:

  d:\XForms-JSF>jar cvf xforms-jsf.jar *.*

This command creates a JAR file named xforms-jsf.jar, which contains the META-INF folder (which in turn contains the TLD and configuration files) and the class files available in the XForms-JSF folder.

The xforms-JSF.jar file is available in the section7.zip file; see Resources.

Now the tag library is ready to be used with any JSF application. Place this JAR file in the WEB-INF\lib folder of your application. In the next section, we will develop a sample application to show you how to use the JAR file in a JSF application.


A sample JSP page to try the XForms-JSF tag library

To show how to use the tag library in an application, I have written a simple JSP page, which includes different components from our tag library:

<?xml version="1.0" encoding="iso-8859-1"?>
<html
  xmlns:ev="http://www.w3.org/2001/xml-events" 
  xmlns:xforms="http://www.w3.org/2002/xforms">
 <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
 <%@ taglib uri=" http://afictitiousshoppingcart.com/XForms-JSF"
  prefix="xforms-jsf" %>
 <f:view>
  <head>
    <xforms-jsf:model value="#{customerData.model}"/>
  </head>
  <body>
   <h1>Customer Information</h1>
   <xforms-jsf:inputText ref="login" value="#{customerData.login}" 
     label="Login" hint="Please enter your login name."/>
   <xforms-jsf:inputSecret ref="password" 
value="#{customerData.password}" 
     label="Password" hint="Please enter your password."/>
   <xforms-jsf:inputText ref="name" value="#{customerData.name}" 
label="Name" 
     hint="Please enter your full name."/>
   <xforms-jsf:textarea ref="address" 
value="#{customerData.address}" 
     label="Mailing Address" hint="Please enter your address."/>
   <xforms-jsf:commandButton label="  Finish  ">
   </xforms-jsf:commandButton>
  </body>
 </f:view>
</html>

The output of the above JSP page is shown in the following screenshot:

Screen Shot

To try the XForms-JSF tag library and JSP page, unzip the section7.zip file in the source code download for this tutorial; see Resources.

The section7.zip file contains two folders named Demo1 and src, and a couple of files named xforms-jsf.jar and Demo1.war. The Demo1 folder contains the sample JSP page, and the src folder contains the complete source code for our XForms-JSF tag library we created in this section.

Now simply deploy the Demo1.war file in your application server. Be sure to use following URL in the address bar of your XForms browser:

  http://localhost:8080/Demo1

As a result, the JSP page shown in the above screenshot displays in your XForms browser.

7 of 12 | Previous | Next

Comments



static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=131918
TutorialTitle=Using JSF technology for XForms applications
publish-date=02032005
author1-email=fkhan872@yahoo.com
author1-email-cc=jaloi@us.ibm.com