Wednesday, July 16, 2008

Post form to clean, a tutorial with JSP/Servlet and JavaScript

Delicious 0
Rewritten URLs are valuable because they increase website usability and improve search engine optimisation (SEO), in PHP with mod_rewrite, you can rewrite URL easily and simple, when using java, you can too, just follow this article. Well, but we have a problem: HTML forms and rewrite URL were not designed to work together. So, you have to use client-side(java script) to transfer page to result page wich rewrited URL. However, you can do it by server-side script by pre-processing input from HTML Forms and transfer to result page. In this tutorial, i'll guide you how to make it work by 2 way: Client-side and Server-side.
HTML forms only have two ways to pass variables to their target page: GET and POST methods.


POST Method:



Using POST method is sercured by empty URL in address bar. If the result page is result.jsp, URL when POST is only: result.jsp. Wow, nice URL, but, the visitor or user can not reuseable for this URL, and can not simply get the same value when re-access this URL. POST method is best for inserting record to database, but worth for searching or fetching records from HTML forms.


GET Method:



Forms using the GET method send data via the URL. This means that the URL can be copied and revisited at any time. The problem with this method is the format of the parameters. The values in the URL string are ugly, verbose and unfriendly; this is what we are trying to avoid. SEO with GET method is so bad. Almost search engineers like: Google, Yahoo, Live... not love URL generated by GET method.

The Client-Side Solution: Post by JavaScript to result page.

Using javascript with windows.location. In the HTML form, you will create new event for form. When the form is submitted, the function in javascript will be called and tranfer to new page. Script will be following codes:


function getKeyword(){
   q=document.getElementById('query').value;
   window.location = "http://localhost:8080/PostCleanTut/search/"+q;
}

document.getElementById('query').value used for getting value of textfiled inside your search form. After getting the keyword value, script will transfer you to result page(JSP/Servlet) which will be created and rewrited URL yourself. Now, create your new HTML Search form name as searchform.jsp, and it likes following codes:

<html> 
<head>
<title>Search Form</title>
</head>
<body>
     <form action="" onsubmit="getKeyword(); return false;" method="post" name="searchForm" id="searchForm">
        Query: 
        <input type="text" name="query" id="query">
        <input type="submit" name="btnSubmit" id="btnSubmit" value="Submit">
     </form>
</body>
</html>
onsubmit="getKeyword(); return false;" used to call getKeyword() funtion from javacript. When done all thing above, submit your form, data posted will be transfered to result page with example address: http://localhost:8080/PostCleanTut/search/yourkeyword.

The Server-side Solution: Pre-processed by a servlet or JSP self page and send redirect to Result page.

Simply processing with a single jsp or a servlet, you can POST to self jsp page include HTML Form, then send redirect to another page which will be rewrited URL. So, in this article, i will do it with a servlet page by doPost() method. In the pre-processing servlet, doPost() method gets parameter from HTML form, you can clean up by removing unwanted characters. However, this article just do simply to explaint what the servlet do with posting form to clean.
Create your new servlet, name as: SearchProcess.java, codes will be:

package prlamnguyen.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import prlamnguyen.util.StringUtil;
public class SearchProcess extends HttpServlet {
   /**
    * Constructor of the object.
    */
   public SearchProcess() {
      super();
   }

   /**
    * Pre-Processing of Search
    * @param request
    * @param response
    * @throws ServletException
    * @throws IOException
    */
   public void proccessRequest(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
      //Get parameter from HTML form
      String q = request.getParameter("query");

      // Clean up by removing unwanted characters if you want
      String newQ = StringUtil.searchInput(q);
      response.sendRedirect(request.getContextPath() + "/search/" + newQ);
   }
   /**
    * The doGet method of the servlet. <br>
    *
    * This method is called when a form has its tag value method equals to get.
    * 
    * @param request the request send by the client to the server
    * @param response the response send by the server to the client
    * @throws ServletException if an error occurred
    * @throws IOException if an error occurred
    */
   public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      proccessRequest(request, response);

   }
   /**
    * The doPost method of the servlet. <br>
    *
    * This method is called when a form has its tag value method equals to post.
    * 
    * @param request the request send by the client to the server
    * @param response the response send by the server to the client
    * @throws ServletException if an error occurred
    * @throws IOException if an error occurred
    */
   public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

      proccessRequest(request, response);

   }
   /**
    * Initialization of the servlet. <br>
    *
    * @throws ServletException if an error occure
    */
   public void init() throws ServletException {
      // Put your code here
   }
}
Above is java class which pre-process and transfer, new servlet which will display result and url will be rewriten have to be created such as name Search.java. Note: you can do it simply by a single jsp to handle and display result, but with a servlet, you can handle data easily by doPost() or doGet() methods, so, it's reason i'm using servlet for this tutorial.
Searching in website is not simply like: where id=?, title=? or onething=?. You should use Full-text Searching, a full-text search allows a search of multiple text columns. If you are setting up a search of a series of articles or a site with lots of product-related content, a MySQL FULLTEXT search can make it very easy to find articles or products related to the keywords used by a searcher. This search method does exactly what its name implies–it allows a full search of large text fields. If you're new to Full-text Search, please follow this link to know how MySQL does with Full-text search.
Following codes bellows are written almost important steps to make search works with URL Rewriter, something like database connection, JNDI...please do it yourself.

Codes of Search.java:


package prlamnguyen.servlet;
/**
* @author Nguyen Duy Lam
*/
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import prlamnguyen.connector.PrlConnection;
import prlamnguyen.model.Article;
public class Search extends HttpServlet {


    Connection con = null;
    PreparedStatement prst = null;
    ResultSet rs = null;
    //Here is my Connection class
    // please create your one class to get connection or write it inside this servlet
    PrlConnection prlcon = null;

    /**
    * Constructor of the object.
    */
    public Search() {
       super();
    }

    /**
    * 
    * @param request
    * @param response
    * @throws ServletException
    * @throws IOException
    */
    public void proccessRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        
        //Init my new connection
        prlcon = new PrlConnection();

        //Display articles in result list in result jsp page which will be created before
        try {
            //Get database connection
            con=prlcon.getConnection();
            //Prepare Statement with Full-text search query, i'm using MySQL.
            prst=con.prepareStatement("SELECT * FROM articles WHERE MATCH(article_title, article_desc, article_content) AGAINST (?)");
            //Get query parameter
            String keyword = request.getParameter("query");
            prst.setString(1, keyword);
            rs=prst.executeQuery();
            ArrayList<Article> articleList = new ArrayList<Article>();

            while(rs.next()){
                Article article = new Article(rs.getInt("article_ID"), rs.getString("article_title"), rs.getString("article_desc"), rs.getString("article_content"));
                articleList.add(article);
            }
            request.setAttribute("keyword", keyword);
            request.setAttribute("articles", articleList);
        } catch (ClassNotFoundException e) {
            
            e.printStackTrace();
        } catch (SQLException e) {
            
            e.printStackTrace();
        } catch (NamingException e) {
            
            e.printStackTrace();
        } finally {
            try {
                if(!con.isClosed()) {
                    con = prlcon.closeConnection(con, prst, rs);
                }
            } catch (SQLException e) {
                
                e.printStackTrace();
            }
        }

        ServletContext context = getServletContext(); 
        context.getRequestDispatcher("/result_search.jsp").forward(request, response); 
    }



    /**
    * The doGet method of the servlet. <br>
    *
    * This method is called when a form has its tag value method equals to get.
    * 
    * @param request the request send by the client to the server
    * @param response the response send by the server to the client
    * @throws ServletException if an error occurred
    * @throws IOException if an error occurred
    */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

        proccessRequest(request, response); 

    }


    /**
    * The doPost method of the servlet. <br>
    *
    * This method is called when a form has its tag value method equals to post.
    * 
    * @param request the request send by the client to the server
    * @param response the response send by the server to the client
    * @throws ServletException if an error occurred
    * @throws IOException if an error occurred
    */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    
        proccessRequest(request, response); 
    
    }



    /**
    * Initialization of the servlet. <br>
    *
    * @throws ServletException if an error occure
    */
    public void init() throws ServletException {
        // Put your code here
    }
}

To display data records, you have to have one data model class. Bellow is one use for above:


package prlamnguyen.model;
/**
* @author Nguyen Duy Lam
*/

public class Article {
    
    private int article_ID;
    private String article_title;
    private String article_desc;
    private String article_content;
    


    /**
    * @return the article_content
    */
    public String getArticle_content() {
        return article_content;
    }
    
    /**
    * @return the article_desc
    */
    public String getArticle_desc() {
        return article_desc;
    }
    
    /**
    * @return the article_ID
    */
    public int getArticle_ID() {
        return article_ID;
    }
    
    /**
    * @return the article_title
    */
    public String getArticle_title() {
        return article_title;
    }
    

    /**
    * @param article_content the article_content to set
    */
    public void setArticle_content(String article_content) {
        this.article_content = article_content;
    }
    
    /**
    * @param article_desc the article_desc to set
    */
    public void setArticle_desc(String article_desc) {
        this.article_desc = article_desc;
    }
    
    /**
    * @param article_ID the article_ID to set
    */
    public void setArticle_ID(int article_ID) {
        this.article_ID = article_ID;
    }
    
    /**
    * @param article_title the article_title to set
    */
    public void setArticle_title(String article_title) {
        this.article_title = article_title;
    }
    

    public Article() {

    }
    

    /**
    * Article model for search result
    * @param article_ID
    * @param article_title
    * @param article_desc
    */
    public Article(int article_ID, String article_title, String article_desc, String article_content) {
        this.article_ID=article_ID;
        this.article_title=article_title;
        this.article_desc=article_desc;
        this.article_content=article_content;
    }
}

Ok, almost important about bussiness logic are done, to be continue, create new JSP page to display search result. Search.java is a servlet, and when fetched data records, it forward to JSP result page name as result_search.jsp, you have to create this jsp page, something likes this:


<%@ page contentType="text/html; charset=utf-8" language="java" import="java.util.*" errorPage="" %>
<%@ page import="prlamnguyen.model.Article" %>

<% 
    ArrayList articleList = null;
    Iterator iterator;
    Article article;

%>
<html>
<head>
<title>Result search page</title>
</head>
<body>
<p>Search result for: <strong><%=request.getAttribute("keyword") %></strong></p>
<%
    if(request.getAttribute("articles")!=null) {
        articleList = (ArrayList)request.getAttribute("articles");
        request.removeAttribute("articles");
        iterator = articleList.iterator();
        if(articleList.isEmpty()) {
            out.print("<i>Found nothing, sorry ^^!</i>");
        } else {
            out.print("<ul>");
            while ( iterator.hasNext() ) { 
                article = (Article) iterator.next();
                out.print("<li><strong>" + article.getArticle_title() +"</strong><br />");
                out.print("<i>" + article.getArticle_desc() + "</i></li>");
            }
            out.print("</ul>");
        }
    }
%>
</body>
</html>


URL Rewrite


Follow this article to know how to rewrite URL in java, it will guide you step by step how to install URLRewriter and make it work in Java Web Application. When installed, insert into your urlrewrite.xml following codes to make URL rewrite work for search in this tutorial.
Add new rule somewhere between <urlrewrite>..</urlrewrite> tag

<rule enabled="true">
   <from>/search/([^/\.]+)</from>
   <to>/search?query=$1</to>
</rule>
All thing seem to be done, oh, please edit your HTML form. In the Client-side case, form was submitted by javascript, but in Server-side case, please remove onsubmit event, and point action of the form to "<%=request.getContextPath() %>/searchProcess". Example:

<%@ page language="java" pageEncoding="ISO-8859-1"%>

<html> 
<head>
<title>Search Form</title>
</head>
<body>
     <form action="<%=request.getContextPath() %>/searchProcess" method="post" name="searchForm" id="searchForm">
        Query: 
        <input type="text" name="query" id="query">
        <input type="submit" name="btnSubmit" id="btnSubmit" value="Submit">
     </form>
</body>
</html>
Ok, deploy your web application into web server, example url for testing will be http://localhost:8080/PostCleanTut/searchform.jsp
Note: when coding for a search, you have to handle data inputed from user, should replace Statement with PrepareStatement and set parameter for it to avoid SQL Injection
Best Rigard!

©2008 Lam Duy Nguyen

Related Posts:

Dont just read, download and go, a thank will be helpful for the author to keep going a good job.

Share this post to tell other people about its

blog comments powered by Disqus