Monday, November 30, 2009

Accepting input from List based Forms using Struts

At times you may be required to get input from a list based form. A list based form can be well explained by taking an example of an object which may contain variable number of a list of items. An example being an invoice, which may contain 1 item, 2 items, 5 items or more. The number of items in an invoice are never fixed. You may write a JSP page and allow the user to add any number of items into a list and then finally submit the page to save the invoice.
A similar is the case with the items in a Gate Pass. A Gate Pass is a document which is produced every time whenever item(s) move out of an office. As an example consider the screenshot below:
gatePass 
In the above page (ActionForm) the user has an option to add as many items to the list as desired. Now if we map this page onto an ActionForm we need something in the ActionForm which can accept a list of items. The other fields will be mapped to String objects. An item consists of a code, description and quantity, which means an item is an object in itself, with the previously mentioned instance variables. Since, a Gate Pass will have a list of items you will need to map them to a Java Collections object which may be an ArrayList or a LinkedList. For this example, let us map the list of items on to a LinkedList object.
For the above example let us consider the following two classes:
import java.util.LinkedList; 
import Utility;
/** 
* @author Harkiran Singh 
* 
*/ 
public class GatePass implements java.io.Serializable 
{ 
    /** 
     * 
     */ 
    private static final long serialVersionUID = 1L; 
    private String gatePassNumber;
    private String financialYear; 
    private java.sql.Date gpDate = 
Utility.getSQLDateFromString(Utility.getDateToday()); 
    private String issuedTo; 
    private String gpType; 
    private String authorizedSignature; 
    private int isCanceled = 0; 
    private String cancelUser; 
    private LinkedList<GatePassItems&gt lstItems; 
    public GatePass() 
    { 
        lstItems = new LinkedList<GatePassItems&gt(); 
    }
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
.
(getter and setter methods for the instance variables)
}

/** 
* @author Harkiran Singh 
* 
*/ 
public class GatePassItems implements java.io.Serializable 
{ 
    /** 
     * 
     */ 
    private static final long serialVersionUID = 1L; 
    private String itemCode; 
    private String description; 
    private int quantity; 
    private String gatePassNo; 
    private java.sql.Date returnDate; 
    public GatePassItems(){} 
    public GatePassItems(String itemCode, String description, 
int quantity, String gatePassNumber) 
    { 
        this.itemCode = itemCode; 
        this.description = description; 
        this.quantity = quantity; 
        this.gatePassNo = gatePassNumber; 
    }
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
(getter and setter methods for the instance variables) 
}



Below is the ActionForm:


import java.util.LinkedList; 
import javax.servlet.http.HttpServletRequest; 
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping; 
/**
* @author Harkiran Singh
*
*/
public class GatePassForm extends ActionForm 
{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String gatePassNumber;
    private String financialYear;
    private String gpDate=Utility.getDateToday();
    private String issuedTo;
    private String gpType;
    private String authorizedSignature;
    private String isCanceled = "0";
    private String cancelUser;
    private LinkedList<GatePassItems&gt; lstItems;
    private String description;
    private String quantity;
    private String itemCode;
    private String button;
    private String noOfItems;
    public GatePassForm()
    {
        lstItems = new LinkedList<GatePassItems&gt;();
    }

public GatePassItems getItem(int index)
{
    return lstItems.get(index);
}
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
. 
(getter and setter methods for the instance variables) 
}



The above method in the above ActionForm “getItem(int index)” is the key which will allow access to each item of the LinkedList.


Now, lets also look at the extract from the JSP file.


<c:set var="ctr" value="0"/>

    <table border="1" cellspacing="1" cellpadding="1" width="80%" align="center"&gt;


        <tr>


            <td width="5%" class="tablebgdark" align="right"&gt;<font class="fontwhite">S.No</font></td>

            <td width="20%" class="tablebgdark" align="center"&gt;<font class="fontwhite">Code</font></td>

            <td width="60%" class="tablebgdark" align="center"&gt;<font class="fontwhite">Description</font></td>

            <td width="10%" class="tablebgdark" align="center"&gt;<font class="fontwhite">Qty</font></td&gt;

            <td width="10%" class="tablebgdark">& </td>

        </tr>

        <logic:iterate id="item" name="GatePassForm" property="lstItems">

            <tr>

                <td align="right" class="tablebglight">

                    <c:set var="ctr" value="${ctr + 1}"/>

                    <font class="fontdark">${ctr }.</font>

                </td>

                <td>

                    <html:text name="item" property="itemCode" style="width:98%" indexed="true"&gt;</html:text>

                </td>

                <td>

                    <html:text name="item" property="description" style="width:98%" indexed="true"&gt;</html:text>

                    <html:hidden name="item" property="gatePassNo" value="${sessionScope.GatePassForm.gatePassNumber}" indexed="true"/>

                </td>

                <td>

                    <html:text name="item" property="quantity" style="text-align: right;width:98%" indexed="true"&gt;</html:text>

                </td>

                <td class="tablebglight">

                    <font class="fontdark">

                        <html:link page="/switch.action?prefix=/views/gatepass&&&page=/DeleteGatePassItem.action?index=${ctr-1}">Delete</html:link>

                    </font>

                </td>

            </tr>

        </logic:iterate>

        <tr>

            <td colspan="5" class="tablebgdark"><font class="fontwhite">New Item</font&gt;</td>

        </tr>

        <tr>

            <td class="tablebglight">&nbsp;</td>

            <td class="tablebglight">

                <html:text property="itemCode" style="width:98%" value="">&lt;/html:text>

            </td>

            <td class="tablebglight">

                <html:text property="description" style="width:98%" value="">&lt;/html:text>

            </td>

            <td class="tablebglight">

                <html:text property="quantity" style="text-align: right;width:98%" value="">&lt;/html:text>

                <html:hidden property="noOfItems" value="${ctr }"/>

            </td>

            <td class="tablebglight">&nbsp;</td>

        </tr>

        <tr>

            <td class="tablebglight">

                <html:submit property="button">Add Item</html:submit>

            </td>

            <td class="tablebglight">&nbsp;</td>

            <td class="tablebglight">&nbsp;</td>

            <td class="tablebglight">&nbsp;</td>

            <td class="tablebglight">&nbsp;</td>

        </tr>    
    </table>

The above JSP code in the iteration will be translated to HTML code which will access the LinkedList objects using the “getItem()” method.

The below line:

<html:text name="item" property="description" style="width:98%" indexed="true"&gt;</html:text> 

will get translated into following HTML:

<input type=”text” name=”item[0].description” >

and so on.

This will call the method “lstItems.getItems(0).getDescription()”,

“lstItems.getItem(0).setDescription(…)” and so on.

You will need to save the ActionForm in the session scope so that the previously entered objects are available until the form is submitted to save the Gate Pass in the database.

Also, you will need to add the code for adding the item into the LinkedList in the appropriate Action class which handles the form submission. Your Action class may look like:

public class AddGatePassItemAction extends Action 
{

 /* (non-Javadoc)
  * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
  */
 @Override
 public ActionForward execute(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response)
   throws Exception 
       {
    // TODO Auto-generated method stub
    
    GatePassForm gpForm = (GatePassForm) form;
  
    String description, quantity, gatePassNumber, itemCode;
    LinkedList lstItems = gpForm.getLstItems();
  
    description = gpForm.getDescription();
    quantity = gpForm.getQuantity();
    gatePassNumber = gpForm.getGatePassNumber();
    itemCode = gpForm.getItemCode();
  
    int qty = Integer.parseInt(quantity);
    GatePassItems item = new GatePassItems(itemCode, description, qty, gatePassNumber);
    
    lstItems.add(item);
    gpForm.setLstItems(lstItems);
   
    request.getSession().setAttribute("GatePassForm", gpForm);
  
    return mapping.findForward("success");
      }
}

With all the code and configuration entries in right place you will get a dynamically created LinkedList in your JSP page.

1 comments:

Rahul said...

thnx !

Post a Comment