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.

Tuesday, November 24, 2009

Modular application development using Struts - SwitchAction

Action classes are the important part of the Struts framework. Action classes are where your presentation logic resides. Struts 1.1 (and higher) provides some types of Action out-of-the-box, so you don't have to build them from the scratch. The Actions provided by Struts are ForwardAction, IncludeAction, DispatchAction, LookupDispatchAction and SwitchAction. All these classes are defined in org.apache.struts.actions package. These built-in actions are very helpful to address some problems faced in day to day programming. Understanding them is the key to using them effectively. All of these the Actions are frequently used, except for IncludeAction.

The SwitchAction class allows you to configure multiple application modules. In Struts1.0 (and earlier), a single config file was supported. This file, normally called struts-config.xml, was specified in web.xml as an initialization parameter for the ActionServlet as follows:
<servlet>

    <servlet-name>mybank</servlet-name>  
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

    <init-param>  
        <param-name>config</param-name>

        <param-value>/WEB-INF/struts-config.xml</param-value>  
    </init-param>

</servlet>


The single configuration file is bottleneck in large projects as all developers had to contend to modify this resource. In addition managing a monolithic file is painful and error prone. With Struts1.1 (and higher) this problem has been resolved by the addition of multiple sub application support better known as application modules. You can now have multiple configuration files, one for each module or logical group of forms. The configuration files are specified in web.xml file using multiple <init-param> - initialization parameters.

An example of the how to do this in a web.xml file is as below:




<servlet> 
    <servlet-name>action</servlet-name>

    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>  
    <init-param>

      <param-name>config</param-name>  
      <param-value>/WEB-INF/struts-config.xml</param-value>

    </init-param>  
    <init-param>

      <param-name>config/views/module1</param-name>  
      <param-value>/WEB-INF/struts-config-module1.xml</param-value>

    </init-param>  
    <init-param>

      <param-name>debug</param-name>  
      <param-value>3</param-value>

    </init-param>  
    <init-param>

      <param-name>detail</param-name>  
      <param-value>3</param-value>

    </init-param>

    <load-on-startup>1</load-on-startup>  
</servlet>
<servlet-mapping>  
    <servlet-name>action</servlet-name>

    <url-pattern>*.action</url-pattern>  
</servlet-mapping>

The above web.xml defines the servlet mapping for the action servlet to all URL patterns that ends with ‘.action’, and /WEB-INF/struts-config.xml to be the struts configuration file. You might be wondering what does the below configuration do:




<init-param> 

      <param-name>config/views/Module1</param-name>  
      <param-value>/WEB-INF/struts-config-module1.xml</param-value>  
</init-param>

The above initialization parameter name begins with ‘config/’. ‘config/’ is treated as a keyword for defining a new module. It is interpreted as a configuration for a separate module. Its corresponding value – /WEB-INF/struts-config-module1.xml is the struts configuration file containing Form bean definitions and ActionMappings for the module module1. If the URLs in the default struts-config.xml were accessed as http://localhost:8080/App1/start.action, and the corresponding ActionMapping were moved to struts-module1-config.xml then the URL would be accessed as http://localhost:8080/App1/module1/start.action where App1 is the web application context. Notice that the application URL contains the module name after the web application context as if it is a sub directory name.

The benefits of application modules are immediately obvious. You can now split your monolithic struts application into logical modules thus making maintenance easier. It will cause less contention during development time as developers working on different modules get to work on their own struts configuration files. Each Struts Configuration file and hence each application module can choose its own RequestProcessor, MessageResources and PlugIn. You can now choose to implement one or more modules with Tiles. If you find this convenient and useful then you can migrate your application to Tiles or JSF or plug in any other Struts extensions for one module at a time.

Now, lets look like how the struts-config.xml and struts-config-module1.xml files look like. Below is an extract from the struts-config.xml file:




<struts-config>

    <global-forwards>  

        <forward name="Module1" 

            path="/switch.action? page=/CreateCertificate.action&amp;prefix=/views/module1" /> 

    </global-forwards>

    <action-mappings>

        <action path="/switch"  
            type="org.apache.struts.actions.SwitchAction" />

    </action-mappings>    
    <controller processorClass="org.apache.struts.action.RequestProcessor" /> 
</struts-config>


struts-config-module1.xml file:



<struts-config>  
    <form-beans>

        <form-bean name="Form1"  
                    type="com.example.Form1"/>

        <form-bean name="Form2"

                    type="com.example.Form2"/>  
    </form-beans>


    <global-forwards>

        <forward name="mainpage" path="/"/>  
    </global-forwards>

    <action-mappings>

         <action path="/switch"

                type="org.apache.struts.actions.SwitchAction" />

         <action path="/start"  
                type="com.example.Module1Start"

                name="Form2"  
                scope="request"

                validate="true"  
                input="/input.jsp">

            <forward name="success" path="/switch.action?page=/success.jsp&amp;prefix=/views/module1"></forward>

            <forward name="failure" path="/switch.action?page=/error.jsp&amp;prefix=/views/module1"></forward>

        </action>

You might have noticed that




<action path="/switch"  
                type="org.apache.struts.actions.SwitchAction" /> 

has been defined in both the configuration files. This is important for the code to work properly.


Note: Source of most of the content- Struts Survival Guide, Author: Srikanth Shenoy.

Monday, November 23, 2009

Fixing your Windows Vista Sidebar

Since last two weeks the vista sidebar wasn't loading on my computer. Searching for a solution on google wasn't easy. However, I found a solution today so I thought to save it in my blog.

The problem was resolved after following these steps:

Click Start, All Programs, Accessories, right-click Command Prompt and select "Run as administrator".

Type these commands one by one:
Regsvr32 atl.dll
Regsvr32 "%ProgramFiles%\Windows Sidebar\sbdrop.dll"
Regsvr32 "%ProgramFiles%\Windows Sidebar\wlsrvc.dll"

Tuesday, November 3, 2009

Ubuntu - How to change the Display Manager

A Display Manager provides a graphical login screen. Ubuntu comes with default GUI - Gnome and 'gdm' as Display Manager. You may also choose to install K.D.E on Ubuntu to get an option to login into one out of two different GUI's. K.D.E comes with 'kdm' as the display manager. When you install K.D.E you are asked if you want to change the display manager to 'kdm'. If later you want to switch to the other available display manager then you can do so by using the following command in a terminal window:

$ sudo dpkg-reconfigure gdm