How to handle values from dynamically generated elements in web page using struts2



Some time you will see the form containing the button "Add More" . This facility is provided for the user to get the values for unknown number of repeating for some information. for example when you are asking to get the projects details from user, you need to put the option to add the more project for the user since you don't known how many projects user have. In the HTML form, you repeat the particular section to get the multiple values for those elements.

In Html page , you can put the option to add new row of elements or text fields by writing the java script or using JQuery API.

Now, the question is that how to capture the values of dynamically generated text fields on the server. Using the servlet programming you can get the values by using getParameters() method that resultants the array of the parameter having the same name. But this limit you to naming the text fields in the HTML form. To ally this approach, you have to take the same name for the multiple input type fields those will have the similar values. After getting the server side, you need to process these type of fields manually using lots of programing approach. So it is not a feasible solution when there are other approaches available like using Struts2.

Here, I am explaining the approach for the getting over from this problem. We have struts2 MVC framework that has capability to intercept the request parameters submitted from HTML from. It maps the values to the action or bean properties automatically without writing much codes. You need to following some naming convention only. Struts mapping the values of the input type elements of the HTML form to the properties/variable of the action object automatically if you have kept the name of the input type fields and properties same. You can read the struts2 documentation to handle the something in multiple ways.

Now, if there is some multiple fields in the HTML form having repeatedly values, Struts maps those values to the Collection type properties in the Action Object. So to get the values of the field having multiple values but the same name, take the List type variable in Action class. If some properties of the action class pointing other object, struts2 handling it using the naming convention of the input type field.

<INPUT type="text" name="user.addresses.houseNum" />

At the server side, struts2 mappes value of this text filed using OGNL . In the above statement, user is the property of the actiion object and addresses it the property of the user object. Addresses object contains houseNum property in which the value of the above text field will be mapped.
If the User object has the List of Address object , Struts2 to automatically maps the values to this properties using the following naming convention.

<INPUT type="text" name="user.addresses[0].houseNum" />

The value of the text field will be mapped to the property of the first object of the address List contained by the user object.
Here is an application that has the form with id and name text field and option to adding more addresses. User can address any number of address row and all values are processed by server. Here, I am displaying the submitted values in result page but use can change the codding to persist them to database.


index.html
<HTML>
<HEAD>
<TITLE>Add/Remove dynamic rows in HTML table</TITLE>
<SCRIPT language="javascript">
    function addRow(tableID) {

        var table = document.getElementById(tableID);

        var rowCount = table.rows.length;
        var row = table.insertRow(rowCount);
        var counts=rowCount-1;
        var cell1 = row.insertCell(0);
        var houseNum = document.createElement("input");
        houseNum.type = "text";
        houseNum.name="user.addresses["+counts+"].houseNum";
        cell1.appendChild(houseNum);

        var cell2 = row.insertCell(1);
        var city = document.createElement("input");
        city.type = "text";
        city.name="user.addresses["+counts+"].city";
        cell2.appendChild(city);

        var cell3 = row.insertCell(2);
        var country = document.createElement("input");
        country.type = "text";
        country.name="user.addresses["+counts+"].country";
        cell3.appendChild(country);

    }
</SCRIPT>
</HEAD>
<BODY>

<form action="submit" method="post">ID : <INPUT type="text"    name="user.id" /><br />
Name :<INPUT type="text" name="user.name" /><br />
Addresses :
<TABLE id="addressesTable" width="350px" border="1">
    <TR>
        <TD>House No.</TD>
        <TD>City</TD>
        <TD>Country</TD>
    </TR>
    <TR>
        <TD><INPUT type="text" name="user.addresses[0].houseNum" /></TD>
        <TD><INPUT type="text" name="user.addresses[0].city" /></TD>
        <TD><INPUT type="text" name="user.addresses[0].country" /></TD>
    </TR>
</TABLE>
<INPUT type="button" value="Add More" onclick="addRow('addressesTable')" />
<input type="submit" value="SUBMIT"/>
</form>
</BODY>
</HTML>
result.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h1>User information</h1>
Name :<s:property value="user.name" /><br/>
Addresses :
<s:iterator value="user.addresses">
    <br />
    <s:property/>
</s:iterator>
</body>
</html>
web.xml
<web-app> 
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app> 

struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUB
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />
    <package name="/" extends="struts-default">
        <action name="submit" class="UserAction">
            <result name="input">index.jsp</result>
            <result name="success">result.jsp</result>
        </action>
    </package>
</struts>
UserAction.java

import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
    data.User user;
    public data.User getUser() {
        return user;
    }
    public void setUser(data.User user) {
        this.user = user;
    }
    public String execute(){
        return "success";
    }
}

User.java

package data;

import java.util.Collection;

public class User {
    int id;
    String name;
    Collection <Address> addresses;
    public Collection<Address> getAddresses() {
        return addresses;
    }
    public void setAddresses(Collection<Address> addresses) {
        this.addresses = addresses;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + ", addresses=" + addresses
                + "]";
    }
    
}

Address.java
package data;

public class Address {
    private int houseNum;
    private String city;
    private String country;

    public int getHouseNum() {
        return houseNum;
    }

    public void setHouseNum(int houseNum) {
        this.houseNum = houseNum;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Address [houseNum=" + houseNum + ", city=" + city
                + ", country=" + country + "]";
    }

}



Download source

HSQLDB - Handling Database Programatically (In-Process and Server Mode at a time )


HSQLDB database it a very small database that can be controlled from you application. you can start and stop the database by writing the programming statement. This feature enable to use this database in your application with programmatic control. You can handle the database by writing some java codes.

When you use the database with In-Process mode, you will not able to access it other ways. In the In-Process mode, database become the part of your application and it does not run as server on other port number. So using the database In-Process mode is good when you are going to deploy the webapplication on the live server but at the time of development you have to avoid it. At the time of development, you need to look into database table so queckly to see the changes after executing any functionalityies. So you require the way to access the same dtabase from datbase client. But, if the database is running in the in-process mode, it doesn't open any port to access via database client. To access same database from database client, you need to run the database in Server mode.

But, if you are handling the daabase programmaticlly, you can access it from database client outside from you application.

Here is a example that shows how to use the HSQLDB programmaticlly
 Download Source Code

DatabaseSetup.java :
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.hsqldb.server.Server;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DatabaseSetup extends HttpServlet {
    Connection con;
    Server server;

    public void init() throws ServletException {
        server = new Server();
        server.setAddress("localhost");
        server.setDatabaseName(0"mydb1");
        server.setDatabasePath(0"file:E:/hsqldb_databases/db");
        server.setPort(1234);
        server.setTrace(true);
        server.setLogWriter(new PrintWriter(System.out));
        server.start();
        try {
            Class.forName("org.hsqldb.jdbc.JDBCDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace(System.out);
        }
        try {
            con = DriverManager.getConnection(
                    "jdbc:hsqldb:hsql://localhost:1234/mydb1""SA""");
            con.createStatement()
                    .executeUpdate(
                            "create table contacts (name varchar(45),email varchar(45),phone varchar(45))");
            ServletContext context = getServletContext();
            context.setAttribute("con", con);
        } catch (SQLException e) {
            e.printStackTrace(System.out);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        String reqCommand = req.getParameter("command");
        if (reqCommand.equalsIgnoreCase("info")) {
            out.write("<br/>Address : " + server.getAddress());
            out.write("<br/>Database Name : " + server.getDatabaseName(0true));
            out.write("<br/>DatabasePath : " + server.getDatabasePath(0true));
            out.write("<br/>Port : " + server.getPort());
            out.write("<br/>DefaultWebPage : " + server.getDefaultWebPage());
            out.write("<br/>ProductName : " + server.getProductName());
            out.write("<br/>ProductVersion : " + server.getProductVersion());
            out.write("<br/>Protocol : " + server.getProtocol());
            out.write("<br/>ServerId : " + server.getServerId());
            out.write("<br/>State : " + server.getState());
            out.write("<br/>StateDescriptor : " + server.getStateDescriptor());
            out.write("<br/>WebRoot : " + server.getWebRoot());
        }
        if (reqCommand.equalsIgnoreCase("stop")) {
            server.setLogWriter(out);
            server.shutdown();
            out.write("Database has been stopped.");
        } if (reqCommand.equalsIgnoreCase("start")) {
            server.setLogWriter(out);
            server.start();
            out.write("Database has been started.");
        }else {
            out.write("No command matched");
        }
        out.write("<br/><a href='ViewRecords'>View Records</a>");
        out.write("<br/><a href='index.html'>Home</a> ");
    }
}

Register.java
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Register extends HttpServlet {
    Connection con;
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out=response.getWriter();
        String name=request.getParameter("name");
        String email=request.getParameter("email");
        String phone=request.getParameter("phone");
        try {
            ServletContext context=getServletContext();
            con=(Connection)context.getAttribute("con");
            PreparedStatement pst=con.prepareStatement("insert into contacts values(?,?,?)");
            pst.clearParameters();
            pst.setString(1, name);
            pst.setString(2, email);
            pst.setString(3, phone);
            int i=pst.executeUpdate();
            out.write(i+" records inserted, <a href='ViewRecords'>View Records</a>");
        } catch (SQLException e) {
            e.printStackTrace(System.out);
        }
    }
}


ViewRecords.java

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ViewRecords extends HttpServlet {
    Connection con;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out=response.getWriter();
        try {
            ServletContext context=getServletContext();
            con=(Connection)context.getAttribute("con");
            PreparedStatement pst=con.prepareStatement("select * from contacts");
            pst.clearParameters();
            ResultSet rs=pst.executeQuery();
            while(rs.next()){
                out.write("<br/>"+rs.getString(1));
                out.write(", "+rs.getString(2));
                out.write(", "+rs.getString(3));
            }
            out.write("<hr/><a href='index.html'>Home</a> ");
        } catch (SQLException e) {
            e.printStackTrace(System.out);
        }
    }

}
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <display-name>UsingHsqldb1</display-name>
 <servlet>
  <display-name>Register</display-name>
  <servlet-name>Register</servlet-name>
  <servlet-class>Register</servlet-class>
 </servlet>
 <servlet>
  <display-name>ViewRecords</display-name>
  <servlet-name>ViewRecords</servlet-name>
  <servlet-class>ViewRecords</servlet-class>
 </servlet>
 <servlet>
  <display-name>DatabaseSetup</display-name>
  <servlet-name>DatabaseSetup</servlet-name>
  <servlet-class>DatabaseSetup</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>Register</servlet-name>
  <url-pattern>/Register</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>ViewRecords</servlet-name>
  <url-pattern>/ViewRecords</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>DatabaseSetup</servlet-name>
  <url-pattern>/DatabaseSetup</url-pattern>
 </servlet-mapping>
</web-app>

index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
  <head>
    <title>Using Hsqldb</title>
  </head>
  <body>
  <p>
  
  </p>
  
  <h4><a href='DatabaseSetup?command=info'>Database Information</a></h4>
  <h4><a href='DatabaseSetup?command=start'>Start Database</a></h4>
  <h4><a href='DatabaseSetup?command=stop'>Stop Database</a></h4>
  <hr/>
  <h2>Add records:</h2>
   <form method = "post" action = "Register">
    User Name<br/>
    <input type = "text" name = "name"/>
    <br/>
    Email<br/>
    <input type = "text" name = "email"/>
    <br/>
    Phone no<br/>
    <input type = "text" name = "phone"/>
    <br/>
    <input type = "submit" values = "Submit"/>
    </form>
  </body>
</html>

See also : 

In Process Mode of HSQLDB in web application.

Using HyperSQL (HSQLDB)

 


Popular Posts