OOP-ResearchMake It Simpler by Object Oriented Programming

FormGenerator Part 2 : How to check inputs from CGI FORM / XHTML, WML or SVG by JSP / Japanese Shift_JIS, Chinese BIG5, GB2312 or Russian KOI8-R

How to check input of CGI FORM by JSP/Servlet on Apache Tomcat. XHTML, HDML/WML (WAP) or SVG by XML. Ready for Japanese Shift_JIS, Chinese BIG5, GB2312 or Russian KOI8-R. Better than JSP or XSLT.
Within the XML, you can write the code fragments for HTML, XHTML, HDML/WML (WAP phone) or SGV. Once the XML is parsed by this Java API, JSP/Servlet on Apache Tomcat can insert the arbitrary Strings into these code fragments. Then, this API merges them all and returns the concatenated String.

The code fragments in the XML are cached and re-used, i.e. the same XML will never been read more than once. This pooling mechanism results in the significant performance improvement.
Because of its high performance and simplicity, this API can be alternative to JSP or XSLT.

This is the Part 2 of FormGenerator. If you are not familiar with this Java API, please read from the previous page.

Related Pages:


Very basic concept:

In this section, we will show you the very basic of this Java API. To make the things easier, the example in this section is meaningless. But, please don't be impatient. Later, you will see more interesting features.

Basically, the intended response from JSP/Servlet can be divided into the 2 categories. They are:

  • static code fragment
  • String to be inserted
While the first one is always same regardless of the request, the latter should vary with the request.

In the JSP/Servlet programming by this Java API, the static code fragments can be written to the XML. Then, you can insert the arbitrary String between the code fragments. By d.value element in the XML, you can specify where to insert the String.
Code fragments and where to insert the String

The XML must comply with: . This DTD is abstract enough to store the code fragments for any type of mark up language, such as HTML, XHTML, HDML, WML and SVG. Please place the XML under:
  • (docBase)/WEB-INF/classes
with the sub-directory tree if you wish. For example, the path to the XML for your web application can either be:
  • (docBase)/WEB-INF/classes/hello.xml
  • (docBase)/WEB-INF/classes/test/hello.xml
The XML can be parsed by:
  • getForm(String)
on the instance of FormGenerator, where its parameter specifies the relative path to the XML under:
  • (docBase)/WEB-INF/classes
As for the above example, this parameters will be either of:
  • hello.xml
  • test/hello.xml
correspondingly. Anyway, this method returns the instance of Form, which includes all the information from the XML. Once the instance of Form is available for processing the HTTP request, your JSP/Servlet can work with it to get the intended result. For example, to insert Hello between the 2 code fragments in the above XML, your JSP/Servlet can call:
  • setDefaultValue("item","Hello")
on the instance of Form. Then, the concatenated HTML tags can be retrieved by:
  • getMerged( )
on the instance of Form. As you easily guess, the returned value will be:
  • <ul><li>Hello</li></ul>
in this example. After JSP/Servlet finishes working on the instance of Form, please push it back to the pool by:
  • reuseForm(Form)
on the instance of FormGenerator. Then, the same instance of Form can be used by the subsequent HTTP request. For example, the very simple source code for the Servlet is listed below:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import com.oopreserch.web.*;

/**
 * @author Jun Inamori
 */
public class Hello extends HttpServlet{

    private static FormGenerator gen=null;

    public void init()
	throws ServletException{
	try{
	    gen=FormGenerator.getInstance();
	}
	catch(Exception ex){
	    ex.printStackTrace();
	    throw (new ServletException(ex));
	}
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException,IOException{
	try{
	    Form input=gen.getForm("test/hello.xml");
	    input.setDefaultValue("hello","Hello World");
	    String tag=input.getMerged();
	    gen.reuseForm(input);
	    req.setAttribute("tag",tag);
	    (req.getRequestDispatcher("hello.jsp")).forward(req,res);
	}
	catch(Exception ex){
	    throw (new ServletException(ex));
	}
    }

} //End of : Hello


In the above example, the HTTP request is forwarded to another JSP along with the request-scope attribute. On the destination JSP, the generated HTML tag is available and can be merged into its own response.

This is just the very basic of this Java API. In the subsequent sections, we will describe the powerful features of this Java API.

Go Site Map

One more basic:

Please be patient for a bit while. This section describes another basic of this Java API. It is...

  • You can write the 2 set of code fragments into XML
one for the valid case, another for the invalid case. Please look into the source XML listed below:
Code fragments and where to insert the String

For example, to insert Hello between the 2 code fragments for valid case, JSP/Servlet can call:
  • setDefaultValue("item","Hello",true)
on the instance of Form. As you easily guess,
  • <ul><li>Hello</li></ul>
will be returned by:
  • getMerged( )
What will be returned?, if JSP/Servlet calls:
  • setDefaultValue("item","Hello",false)
instead (note the last parameter). The concatenated String will be:
  • <ul><li><font color="#ff0000">Hello</font></li></ul>
As you see, the enclosing tags are the code fragments for the invalid case. Thus, the instance of Form selects the appropriate set of code fragments, based on the validity of the String to be inserted. At glance, this feature may not look so attractive. But, in the next section, you will be surprised at how useful it is.

Go Site Map

How to check input from CGI FORM:

First of all, the code fragment for the intended CGI FORM can be written in the XML. In the departing JSP, the tags for the CGI FORM will look like:

HTML tags for CGI FORM

If the user types "123" and sends the request to the Servlet, the input is invalid. And the tags for the CGI FORM like below should be generated, as the response from the destination Servlet:
HTML tags for CGI FORM

As shown in the previous section, the arbitrary String can be inserted into the code fragments. Moreover, the 2 set of code fragments can be written in the XML, one for the valid case and another for the invalid case. So, the following XML will be enough for generating both of the above HTML tags:
Code fragments for CGI FORM

Because the above CGI FORM includes only one text field, the destination Servlet can easily check the validity of the parameter value. Then, you can guess the remaining tasks of the destination Servlet. (If you cannot, please read the previous section again.) But, the CGI FORM in the real world includes more than one text field. Don't worry. This Java API takes care of you.

As you know, the java.util.Map interface includes a set of key-value pairs. Similarly, each instance of HttpServletRequest has a set of the HTTP request parameters from the departing CGI FORM. From the instance of HttpServletRequest, you can get the parameter value for the specified parameter name.
Form class implements the very useful method. It is:
  • setRequest(HttpServletRequest)
By this method, JSP/Servlet can insert all the parameter values into the code fragments at a time. At the same time, the validities of all the parameter values can be determined at a time. Let's look into the details.

First, this methods list all the character data within d.value elements of the intended XML. In this method, each character data within d.value element is considered as the parameter name of the HTTP request. In this step, the duplicate parameter name will be ignored.
Then, for each parameter name, it tries to find the corresponding parameter value in the given instance of HttpServletRequest. If found, the parameter value will be inserted into the code fragments.
In this step, the validity of the parameter value is determined. By verify.type attribute of that d.value element, you can specify which type of parameter value is valid. Please look into the source XML listed below:
Code fragments and where to insert the String

In this example, the parameter value only with a-z or A-Z can be treated as valid. For example, if the parameter value includes any of 0-9, it is treated as invalid. Based on the validity of the parameter value, this method selects the appropriate code fragments.

In case that the parameter value is not found in the HttpServletRequest, the empty String will be inserted into the code fragments. The validity of this empty String depends on not.null attribute, i.e. if YES is specified there, the empty String will be treated as invalid.

After the above method, JSP/Servlet can see if all the parameter value are valid or not, just by:
  • isAllValid( )
If any of them is invalid, this method returns false. Otherwise, true will be returned. Based on the result of this method, JSP/Servlet can decide what to do.

In case that every parameter value is valid, JSP/Servlet should proceed to the next step. JSP/Servlet may save the parameter values into SQL table through JDBC PreparedStatement, or it may send the e-mail by JavaMail API. It fully depends on your web application.

On the contrary, most of the JSP/Servlet should do the same thing, if any of the parameter value is invalid. Yes, JSP/Servlet should show the same CGI FORM again to ask the user to enter the correct input. It is desirable for this CGI FORM to include all the previous input as the default values. In addition, this CGI FORM should indicate which text field include the invalid input. Then, the users can easily fix some of their previous inputs and send them again.

The good news is...
The HTML tags for such a complex CGI FORM is already available on your hand! All you have to is to call:
  • getMerged( )
The returned String is what you want. For example, the destination Servlet will be something like:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import com.oopreserch.web.*;

/**
 * @author Jun Inamori
 */
public class CgiCheck extends HttpServlet{

    private static FormGenerator gen=null;

    public void init()
	throws ServletException{
	try{
	    gen=FormGenerator.getInstance();
	}
	catch(Exception ex){
	    ex.printStackTrace();
	    throw (new ServletException(ex));
	}
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException,IOException{
	try{
	    Form input=gen.getForm("xml/cgi.xml");
	    input.setRequest(req);
	    if(!input.isAllValid()){

		// The tags for CGI FORM is available.
		// It includes all the parameter values
		// within the code fragments for the
		// invalid case.
		String tag=input.getMerged();

		// Don't forget this!
		gen.reuseForm(input);

		// The CGI FORM will be merged into the
		// response from another JSP...
		req.setAttribute("tag",tag);
		(req.getRequestDispatcher("again.jsp")).forward(req,res);
	    }
	    // Don't forget this!
	    gen.reuseForm(input);

	    // Then, this Servlet can do its own tasks.
	    // What it does depends on your web application...
	    .....
	    .....
	}
	catch(Exception ex){
	    throw (new ServletException(ex));
	}
    }

} //End of : CgiCheck


Thus, a few lines of code are enough for checking all the inputs from the CGI FORM.

The implementation of FormValueVerifier interface is responsible for checking the validity of the input from the CGI FORM. Its fully qualified class name must be listed in:
  • FormValueVerifierFactory.properties
as the property value. Each key in this property resource file can be the arbitrary String. Then, you can specify it as the value of verify.type attribute within the source XML. As default, the following implementations are included in the distribution:
API DocSource
IsAlphabet[View source code]
IsAlphabetLower[View source code]
IsAlphabetUpper[View source code]
IsBasicLatin[View source code]
IsDigit[View source code]
IsDigitOrAlphabet[View source code]
IsEmailAddress[View source code]
IsTelephone[View source code]
IsJpFullWidth[View source code]
IsJpFullWidthKatakana[View source code]
IsJpHalfWidth[View source code]
IsJpHalfWidthKatakana[View source code]
IsJpHiragana[View source code]
IsJpPostalAddress[View source code]
IsJpPostalCode[View source code]

To satisfy your requirement, you can easily define your own implementation of FormValueVerifier interface.
Please look into the source code listed above. Because a lot of frequently used methods are already defined in the abstract class (AbstractVerifier), all you have to do is to call some of them within your subclass.
In case of JDK 1.4 (J2SDK 1.4), thing can be much easier by the benefits of java.util.regex package (the new API for pattern matching by regular expressions). For example, a few lines of codes are enough for IsEmailAddress and IsJpPostalCode.

Go Site Map

XML selection based on Locale:

Most web browsers (or WAP browsers) allows the users to select their preferable languages. When the web browser (or WAP browser) sends the HTTP request, the language preference is also sent as one of the header information. On the server side, this language preference can be used to send back the localized contents. For example, Apache HTTPD server (so called Apache web server) implements content negotiation, which selects the localized HTML file based on the language preference.

The language preference is also available for JSP/Servlet programming. From the given instance of HttpServletRequest, JSP/Servlet can get the instance of java.util.Locale. And the instance of Locale tells the JSP/Servlet which language the user likes. For example, in the MVC (model-view-controller) design, the following Servlet switches the HTTP request to the Localized JSP:


import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * @author Jun Inamori
 */
public class Switch extends HttpServlet{

    public void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException,IOException{
	Locale loc=req.getLocale();
	String lang=loc.getLanguage();
	if(lang!=null && lang.equalsIgnoreCase("fr")){
	    (req.getRequestDispatcher("french.jsp")).forward(req,res);
	    return;
	}
	(req.getRequestDispatcher("english.jsp")).forward(req,res);
    }

} //End of : Switch


If the user prefers French language, the HTTP request will be forwarded to the JSP in French language. Otherwise, the JSP in English will be shown. If you'd like to add the localized contents in Japanese language, what do you do? Please note the next source does not work:

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * @author Jun Inamori
 */
public class BadSwitch extends HttpServlet{

    public void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException,IOException{
	Locale loc=req.getLocale();
	String lang=loc.getLanguage();
	(req.getRequestDispatcher("result_"+lang+".jsp")).forward(req,res);
    }

} //End of : BadSwitch


Because you cannot prepare the JSP for all the possible languages in the real world, the above Servlet may result in 404 (not found) error. Yes, whenever the additional localized contents is added, you will need to slightly modify the above source. Or, you should list all the available JSP in the property file, with the corresponding language code as the key.

With this Java API, the things can be much simpler. Form class implements:
  • getForm(String,Locale)
which selects the appropriate XML for the Locale. The first parameter of this method is the relative path to the intended XML. The path should be relative under:
  • (docBase)/WEB-INF/classes
But, it must not end with .xml suffix.
All you have to do is to prepare the XML for the expected Locales. You should take the great care for the file name of XML, because this method tries to find the XML based on:
  • language code
  • country code
which can be retrieved from the given instance of Locale, the second parameter of the above method.

The language code is lower-case 2-letter code as defined by ISO-639. You can find a full list of these codes at a number of sites, such as:
The country code is upper-case 2-letter codes as defined by ISO-3166. You can find a full list of these codes at a number of sites, such as:
For example, if the first parameter of this method is foo and the second one (the instance of Locale) indicates:
  • language code is ja
  • country code is JP
this method searches the XML in the following order:
  • foo_ja_JP.xml
  • foo_ja.xml
  • foo.xml
If the first XML is not found, this API tries to find the second one. And if the second one is not found, the last XML will be selected. Please note the file name of the last XML in the above list. It is not followed by any language code and country code. You can think of it as the default XML. Because you can not prepare the XML for all the possible languages (and countries), don't forget to prepare the default XML.
Let's look into the Servlet below:

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * @author Jun Inamori
 */
public class GoodSwitch extends HttpServlet{

    private static FormGenerator gen=null;

    public void init()
	throws ServletException{
	try{
	    gen=FormGenerator.getInstance();
	}
	catch(Exception ex){
	    ex.printStackTrace();
	    throw (new ServletException(ex));
	}
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException,IOException{
	Locale loc=req.getLocale();
	Form form=gen.getForm("hello",loc);
	String html=form.getMerged();

	// Each XML can specify the Content-Type
	// followed by the appropriate charset extension.
	String type=form.getContentType();

	// Don't forget this!
	gen.reuseForm(form);

	// Set the Content-Type header with
	// the appropriate charset extension.
	res.setContentType(type);

	//HTTP 1.1
	res.setHeader("Cache-Control","no-cache");
	//HTTP 1.0
	res.setHeader("Pragma","no-cache");
	//prevents caching at the proxy server
	res.setDateHeader ("Expires", 0);

    }

} //End of : GoodSwitch


Assuming that you'd like to prepare the localized contents for French and English, you will need to write the following XML:
  • hello_fr.xml
  • hello_en.xml
  • hello.xml
Because the contents in English can be shown on most web browsers, the last one (you can think of it as the default XML) equals with the second one in the usual case.
As you see in the above source code, the XML can have the element for Content-Type. For example, the first XML in the above list may look like this:
Code fragments and where to insert the String

And the second one (and the last one) will be:
Code fragments and where to insert the String

Because the contents both in French and English can be represented by ISO-8859-1 charset, these 2 XML has the same content.type element, which specifies the Content-Type header followed by the charset extension for ISO-8859-1. But, if you'd like to add the Japanese contents, its source XML (hello_jp.xml) will be something like:
Code fragments and where to insert the String

Please note the content.type element in this XML. The character data within this element is the Content-Type header, which is followed by the charset extension for Shift_JIS.

By the way, if your boss suddenly asks you to add the Japanese contents, what do you do? All you have to do is to place the above XML. You need not touch your existing source code at all, and can have a nice week end.

Thus, this JSP/Servlet API makes your web application truly internationalization (i18n) ready.

Go Site Map

How to escape the special characters:

As described in the previous sections, you can insert the arbitrary String into the pre-defined code fragments. Then, the instance of Form can merge them all and return the concatenated String.

Please consider what will happen if the String to be inserted includes the special characters such as < or >. The concatenated String will be invalid as the HTML (or HDML/WML in case of WAP phone) code, which will result in the corrupted String on the web browser.

To avoid such a problems, the String to be inserted should be escaped, i.e. all the special characters within the original String should be replaced with the corresponding escaped characters. And this is the responsibility of the implementation of FormValueEscaper interface.

The implementation of this interface will be used by the instance of Form to escape the String to be inserted. The list of the available implementations should be listed in:

  • FormValueEscaperFactory.properties
where the value of each property is the fully qualified class name of the implementation of this interface. The key in this property resource file can be specified as the value of escape.type attribute of d.value element in the XML.
Code fragments and where to insert the String

Then, the corresponding implementation will be used to escape the String to be inserted.

The implementation of this interface must implement:
  • no-argument public constructor
  • getEscaped(String)

The special characters to be escaped differ with the mark-up-languages. In case of HTML, at least the following characters should be escaped:
Original Character Escaped Character
< &lt;
> &gt;
& &amp;

In addition, " and $ should be also replaced with &quot; and &dol; in HDML.

In XML, the following characters should be escaped:
Original Character Escaped Character
< &lt;
> &gt;
& &amp;
" &quot;
' &apos;

As for WML, $ should also be replaced with $$. (See Page 6 of WML Language Reference which is available at OpenWave's web site.)

Anyway, the 4 implementations are included in this package. They are: So, please feel free to use any of them. Or, if you need additional features, you can define your own implementation which satisfies your requirement. In this case, please add the fully qualified class name of your implementation to:
  • FormValueEscaperFactory.properties
For details about this property resource file, please look into FormValueEscaperFactory.

Occasionally, you may want to URL-encode the String to be inserted. This JSP/Servlet API also includes: which is another implementation of FormValueEscaper interface. By this implementation, the String to be inserted is URL-encoded before it is inserted into the code fragments.
Note that the above implementation uses ISO-8859-1 (US-ascii) as the charset. In addition to ISO-8859-1 (US-ascii), the implementations for UTF-8 and Shift_JIS are also included in this API. They are:
Java DocSourcecharset
UrlEncodeUtf8[View source code]UTF-8
UrlEncodeShiftJis[View source code]Shift_JIS

Please look into the source codes of these 2 classes. As you notice, they are the subclass of which override the value of:

   protected String charset="ISO-8859-1";

in their constructors. In this way, you can easily add your own implementation for your requirement.

Go Site Map

Line breaks within HTML, HDML, WML or XHTML:

As described in the previous sections, you can insert the arbitrary String into the pre-defined code fragments. Then, the instance of Form can merge them all and return the concatenated String.

Please consider what will happen if the String to be inserted includes the line separators. As you know, most mark-up languages treat them as just single space character. As a result, the inserted String will be shown without any line breaks on the web browser.
To be shown with lines breaks, the line separators in the String must be replaced with the tags for lines break, such as <br>. And this is the responsibility of the implementation of FormValueBreaker.

The implementation of this interface will be used by the instance of Form to replace the line separators. The list of the available implementations should be listed in:

  • FormValueBreakerFactory.properties
where the value of each property is the fully qualified class name of the implementation of this interface. The key in this property resource file can be specified as the value of break.type attribute of d.value element in the XML. Then, the corresponding implementation will be used to replace the line separators.

The implementation of this interface must implement:
  • no-argument public constructor
  • getBreaked(String)

The tags for line break differ with the mark-up languages. In case of HTML and HDML, it is <br>. As for WML and XHTML, <br /> should be used instead.
To be ready for both of them, the 2 implementations are included in this package. They are: So, please feel free to use any of them. Or, if you like, you can define your own implementation which satisfies your requirement.

Go Site Map

Download:

-- 230.00 USD with 1 year FREE upgrade
-- Or FREE 30 days trial

You can try or purchase this product at Java API Shop by OOP-Research.

Go Site Map Go Shop



Caution!
All the APIs for Servlet/JSP introduced by this web site are now included in Bento framework:
  • Simpler than JSTL or Apache Struts
  • MVC framework by HTML
  • Input validation from CGI FORM
  • Easy user authentication
  • Easy localization (L10n)
To download the APIs and source code examples, please visit the web site of Bento framework.


JBuilder 2007


General Information

For Java Development

Java and all Java-based trademarks and logos are trademarks or registered of Sun Microsystems, Inc. in the United States and other countries.


ALL CONTENTS COPYRIGHT 1997-2007, OOP-Research Corporation. All rights reserved.