HISTORY
Web servers started out as file servers. Then came CGI, the Common Gateway Interface.
This is just a means to pass data from a form to an external form processing program on the server.
CGI uses environment variables to pass this information: the GET or POST methods.
Since CGI requires loading a program on each request, the Netscape Web server introduced the faster Netscape Server API, or NSAPI, which uses the equivalent of a DLL.
This eliminated the overhead in loading programs on each request.
However, any crash in NSAPI brings down the whole server. Also, only a few languages can be used to interface with DLLs.
Microsoft has an equivalent to NSAPI: ISAPI. ISAPI supports even fewer languages than NSAPI.
Then came the FastCGI protocol which allowed CGI programs to run continuously. However, FastCGI is not an accepted standard, and it is not truly multithreaded, as spawned servers are limited.
Active Server Pages, ASP, is a Web page with embedded server code.
The advantages: server code and browser code are in the same place, and can communicate with databases and other applications (and can therefore support 1, 2, and 3-tiered architectures).
The disadvantages are: limited languages are supported, and ASP runs on few servers.
Servlets were developed at Sun. Advantages over CGI: no program loading necessary, as Java runs on the JVM. Also, servlets are not constrained to the HTTP protocol.
Disadvantages: not yet as fast as some non-Java web servers.
Java Server Pages, JSP, is Sun's answer to ASP. Advantages: same as ASP, and available on non-Windows platforms, can be extended to support languages other than Java, has ability to create customized tags, a la XML. Also, JSPs are compiled into servlets, and enjoy all their advantages, as well.
JSP SYNTAX
- JSP comments are enclosed between <%-- and --%>. These are not output under JSP.
- Java expressions enclosed between <%= and %>, are evaluated, and the result is output.
- Java code outside the main JSP method, such as other methods or properties, must be enclosed by <%! and %>.
- JSP compile time directives are of the form <%@ directive-type options %> directive types:
- <%@ page options %> options can be:
- language="java" other languages might include javascript
- import="package-spec.*"
- session="true or false" (only false when used to detect compile time bugs)
- buffer="none or number[kb]" default: >=8kb
- autoflush="true or false" default: true
- isThreadSafe="true or false" default: true, but up to you to make it so!
- errorPage="error-page-URL"
- isErrorPage="true or false" default: false
- contentType="content-type" default: text/html
- info="description of this servlet"
- extends="name-of-super-class" (super class must implement the JspPage interface, and typically extends HttpServlet)
- <%@ include file="file-URL" %>
- <%@ taglib uri=".../glarf.tld" prefix="glarf" %>:
if .../glarf.tld is of form:
<?xml version="1.0"?>
<!DOTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib><tlibversion>1.0</tlibversion><jspversion>1.1</jspversion>
<shortname>glarf</shortname><info>comment describing this taglib</info> <tag>
<name>foo</name>
<tagclass>fooClass</tagclass>
<attribute>
<name>attrib1</name><required>yes or no</required>
</attribute>
...other attributes...
</tag>
</taglib>
the custom tag defined here is <glarf:foo>
the class, fooClass, must extend TagSupport, and override methods doStartTag and doEndTag. doStartTag can return one of SKIP_BODY(ignor content of tag), EVAL_BODY_INCLUDE(pass thru content, and evaluate all tags).
doEndTag can return EVAL_PAGE(continue evaluating page), SKIP_PAGE(dis-continue evaluating page). fooClass could also have properties (the attributes), and get / set methods, just like a bean.
- JSP actions of the form <jsp:action-name>. JSP actions:
- <jsp:forward page="url">: go to new page. corresponding method in servlet:
RequestDispatcher d = request.getRequestDispactcher("destURL");
d.forward(request, response);
- <jsp:useBean id="glarf" [scope="page,request,session,or application"] init-options/>: init options are needed when first used. Default scope is page. Init options could be one of:
- class="class-name" type="type-name"
- beanName="class-name" type="type-name"
- type="type-name"
This creates a jsp variable with name glarf, properties of which can be accessed via <%= glarf.getFoo() %> when foo is a property of glarf.
relaying bean attributes in servlets in various scopes is done via:
- scope = request:
glarfClass theBean = request.getAttribute("glarf");
- scope = session:
glarfClass theBean = (HttpSession)request.getSession().getAttribute("glarf");
- scope = page:
glarfClass theBean = pageContext.getAttribute("glarf");
- <jsp:getProperty name="bean-name" prop="prop-name"/>: output the value of this property
- <jsp:setProperty name="bean-name" prop="prop-name" value="new-prop-value"/>: set the bean's property to this value
- <jsp:include page="url-spec">: includes whatever corresponds to the url-specification. This can be another JSP, a servlet, or a static page. corresponding method in servlet:
RequestDispatcher d = request.getRequestDispactcher("destURL"); d.include(request, response);
- <jsp:param/>: additional parameters. These can be in the <jsp:forward>, <jsp:include>, or <jsp:plugin> tags
- <jsp:plugin options>: .. options can be (in bold means required):
- type = bean or applet
- code = classname of plugin object
- codebase = location of class object
- align, archive, height, hspace, iepluginurl, jrevision, name, nspluginurl, vspace, width
-
All other text in the document that is outside these JSP components is passed thru, unfiltered.
JSP Built-in Java Objects
OBJECT | CLASS | Description
| application | javax.servlet.ServletContext | all data in the application
| config | javax.servlet.ServletConfig | configuration info for this JSP
| exception | java.lang.Throwable | error/exception that caused this error page
| out | javax.servlet.jsp.JspWriter | Writer used to send response to browser
| page | java.lang.Object | current JSP (same as the Java this)
| pageContext | javax.servlet.jsp.PageContext | reference most objects JSP page used, and utilities such as forward and include
| request | javax.servlet.http.HttpServletRequest | info about upcoming request (form variables)
| response | javax.servlet.http.HttpServletResponse | info about response: header variables, cookies, content type
| session | javax.servlet.http.HttpSession | data associated with browser session
|
javax.servlet API
INTERFACE | METHODS
| RequestDispatcher |
public void forward (ServletRequest, ServletResponse) throws ServletException, java.io.IOException
forwards current request to another resource on the same server. Not to be used after response has started.
public void include (ServletRequest, ServletResponse) throws ServletException, java.io.IOException
includes another resource at runtime
| Servlet |
public void destroy ()
called just before closing servlet, allows resource cleanup
public ServletConfig getServletConfig ()
gets the initialization parameters of the servlet
public String getServletInfo ()
gets info like: author, version, copyright. cannot have XML or HTML markups
public void init (ServletConfig) throws ServletException
performs initialization for servlet, such as opening the database
public void service (ServletRequest, ServletResponse) throws ServletException, java.io.IOException
this is called by servlet to process a request. init will always have been completed before this will be called. Code should sometimes be added to make this thread-safe.
| ServletConfig |
public String getInitParameter (String parameterName)
returns the value of the parameter, or null if no such parameter
public Enumeration getInitParameterNames ()
returns enumeration of all init parameter names for this servlet
public ServletContext getServletContext ()
allows accessing application-level scope objects, logging, request dispatching
public String getServletName ()
returns the name of the servlet
| ServletContext |
public Object getAttribute (String name)
returns the application scope object corresponding to an attribute name
public Enumeration getAttributeNames ()
returns enumeration of all application-scope attribute names
public ServletContext getContext (String uri)
returns the servlet context for a specific servlet, providing a method to allow applications to exchange data. URI must begin with '/'.
public String getInitParameter (String name)
returns the value of an initialization parameter for the servlet engine itself (not the servlet)
public Enumeration getInitParameterNames ()
returns enumeration of all servlet engine initialization parameter names
public int getMajorVersion ()
returns minor version number of the servlet API that the servlet engine supports
public int getMinorVersion ()
returns major version number of the servlet API that the servlet engine supports
public String getMimeType (String file)
returns the mime type associated with the file, or null if none
public RequestDispatcher getNamedDispatcher (String servletName)
returns the request dispatcher for the named servlet, or null if there is none.
public StringgetRealPath (String virtualPath)
returns the local OS's full path for a virtual path, or null if there is no possibility.
public RequestDispatcher getRequestDispatcher (String resourcePath)
returns the request dispatcher the given resource, or null if none. NOTE: resource does not need to be a servlet.
public URL getResource (String path) throws MalformedURLException
returns a URL that points to a particular resource, or null if there is no such mapping.
public InputStream getResourceAsStream (String path)
returns the contents of the named resource (unprocessed) as an input stream, or null if there is no such mapping.
public String getServerInfo ()
returns the name and version of the servlet engine in form server-name/server-version.
public Servlet getServlet (String name) throws ServletException
returns reference to the named servlet. DEPRECATED in 2.1
public Enumeration getServletNames ()
returns the enumeration of all the servlet names in the server engine. DEPRECATED in 2.1
public Enumeration getServlets ()
returns the enumeration of all the servlet names in the server engine. DEPRECATED in 2.1
public void log (String message)
public void log (String message, Throwable throwable)
public void log (Exception exc, String message) deprecated in 2.1
logs a message and optional exception to the serlet engine's log file
public void removeAttribute (String name)
removes a named attribute stored at the application context level
public void setAttribute (String name, Object)
stores an attribute at the application context level
public Enumeration getServlets ()
returns the enumeration of all the servlet names in the server engine. DEPRECATED in 2.1
| ServletRequest |
public Object getAttribute (String name)
returns the object stored with a request context. This is the normal context where objects are stored via setAttribute. Some servlet engines, such as Sun's JWS, store incoming HTTPS certificates as the javax.servlet.request.X509Certificate attribute.
public Enumeration getAttributeNames ()
returns an enumeration of the names of objects stored in this (request context) level.
public String getCharacterEncoding ()
returns character encoding used in the request, if any, otherwise null.
public int getContentLength ()
returns number of bytes in the incoming request content, or -1 if unknown.
public String getContentType ()
returns the mime type of incoming request, or null if unknown.
public ServletInputStream getInputStream () throws java.io.IOException
returns an input stream for reading the request content as a stream of bytes (cannot be used after calling getReader).
public java.util.Locale getLocale ()
returns the preferred locale specified by browser (the language).
public Enumeration getLocales ()
returns all locales supported by the browser.
public String getParameter (String name)
returns the value of an incoming parameter, or null if no such parameter.
public Enumeration getParameterNames ()
returns all parameter names in the request.
public String[]getParameterValues (String name)
returns an array of parameters with a specified name, allowing access to mulitply specified parameters, or null if no such parameters.
public String getProtocol ()
returns the name and version of the protocol used to make the request. Example: HTTP/1.0
public BufferedReader getReader () throws java.io.IOException
returns a reader used to read content data sent from the browser. The advantage of this over getInputStream is that it aloso performs any necessary character translation.
public String getRealPath (String virtualPath)
returns the local OS path for the specified path. DEPRECATED in 2.1: use ServletContext.getRealPath instead
public String getRemoteAddr ()
returns the numeric IP address of the requesting client.
public String getRemoteHost ()
returns the name of the requesting host, or it's numeric IP address, if unknown.
public RequestDispatchergetRequestDispatcher (String path)
returns a request dispatcher for the given resource. This returns dispatcher for all kinds of resources, not just servlets, as for getNamedDispatcher. Or null if no such dispatcher.
public String getScheme ()
returns the name of the scheme used to make the request. Example schemes are: ftp, http, https.
public String getServerName ()
returns the host name of the server receiving this request, of which there can be many associated with this service.
public int getServerPort ()
returns the port number the request was sent to. For normal http, this is 80, and for normal https, this is 443.
public boolean isSecure ()
returns true when request was made using a secure protocol, like https.
public void removeAttribute (String name)
removes the specified attribute from the request content.
public void setSttribute (String name, Object value)
stores the named value in the request content.
| ServletResponse |
public void flushBuffer () throws java.io.IOException
flushes any output currently in the output buffer, committing the response. After this, fowarding to another page may cause an error, or cause mixed content between next and last pages.
public int getBufferSize ()
returns the size of the response buffer, or 0 if there is no buffering.
public String getCharacterEncoding ()
returns the character encoding used in the response. Default: ISO-8859-1 (Latin-1).
public java.util.Locale getLocale ()
returns the response locale, which should have been set based on the request locale.
|
HANDLING HTML FORMS
On browser side, forms are presented in HTML as:
<FORM action=form-processing-URL method=GET or POST>
<input name=field-name type=text, checkbox, ...., or radio [value=...] >
<select name=field-name><option value=... [selected]></select>
<input name=subname type=submit>
</form>
A simple JSP form handler would look like:
<html><body>
<% String first_field = request.getParameter("first-field-name"); ... >
First field is <%=first_field%>
</body></html>
The best way to save data between requests is using the session object: using hidden form variables has no security. session is a built-in variable in JSP, and is of type HttpSession.
The most common methods are:
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name, Object value);
NOTE: all throw IllegalStateException.
The session object must be gotten before sending any response, as session information is stored in a session cookie. One complication deals with users having multiple sessions open. In shopping cart, when user gives up and starts over, a new session needs to be started.
MVC - Model - View - Controller Paradigm
The following summarizes how this works:
- Controller servlet connects to the application server, gets some data, stores it in the request object
- The controller servlet grabs some information from the database(model), and stores it in the request object
- In case of database errors, the controller servlet forwards to an error JSP.
- The controller servlet gets the user profile info from the security server
- If user is a manager, controller servlet forwards to the manager (view) display JSP
- Otherwise, controller servlet forwards to the regular (view) display JSP
Component (tier)
| Description
| Implemented as
| CONTROLLER | the INPUT, changing system | JSP or servlet
| init() method loads the ODBC driver, and connects (preferably via a connection pool)
destroy() method closes the connection
| MODEL | the DATA of system | Java classes, interfacing with SQL
| .
| VIEW | the OUTPUT of data, usually display | JSP
| view example:
<html><body>
Results matching your request are...
<% String first_field = request.getParameter("first-field-name"); ... %>
First field is <%=first_field%>
</body></html>
|
SHOPPING CART WITH BEANS
STEP | Implementation
| Controller
| <@ page language="java" import="shopping_cart.*, java.net.*, java.text.*" %>
<html><body>
<a href="viewShoppingCart.jsp">View Shopping Cart</a>
<p>Available Products
<p><table><tr><th>Description<th>Quantity<th>Price</tr>
<jsp:useBean id="catalog" class="shoppingCart.productCatalog" scope="application">
<% ... String glarfStr = (String)request.getParameter("glarf");...
|
COMPLICATIONS
- Only one instance of the JSP object is usually loaded, so any operations on class variables should be initialized, performed, and used with the JSP object synchronized (synchronized(this){ ... })).
- When JSP makes use of a database,
WML
WML is based on XML. Start of file is of form:
<%@ page language="java" contentType="text/vnd.wap.wml" %>
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC ".//WAPFORUM//DTD.WML 1.1//EN "http://www.wapforum.org/DTD/wml_1.1.xml">
WML content is a sequence of cards (a deck) enclosed between <wml> and </wml>. Card content lies between <card id="glarf"> and </card>.
To detect a wireless client, in a servlet:
if (request.getHeader("Accept").indexOf("text/vnd.wap.wml")>=0)
//then a wireless client
WML Component
| Description
| <!-- glarf --> | WML comments are the same as in HTML
| <a href="glarf">HyperLink</a> | anchor links the same as in HTML
| <do type="accept" [label="glarf"]>
<go href="#foo">
</do> | This uses the phone's accept key to navigate between cards
| <do type="accept" [label="glarf"]>
<go href="foo" method="post">
<postfield name="xx" value="$(xx)"/>
...
≶/go>
</do> | This is how forms are used
| <p> ... </p> | Same as in HTML, except closing </p> is required.
| FORM input fields:
| <postfield name="glarf" value="$(glarf)"/> | Indide a <do type="accept"><go href="foo" method="post">... </go>...</do> Where each glarf field is the name of an input or select tag. This is the method of passing form info to the foo link.
| <select name="glarf">
<option value="foo">foo</option>
...
</select>
| <input name="glarf" format="format-string"/> | $glarf is the value of parameter glarf, and can occur anywhere in WML, including inside a string. Format characters are shown in following table:
|
Format char
| Description
| A | Any uppercase letter, NO number
| a | any lowercase letter, NO number
| M | any character. First character defaults to uppercase
| m | any character, first character defaults to lowercase
| N | any number or symbol
| X | any number, uppercase letter, or symbol
| x | any number, lowercase letter, or symbol
| * | match any 0 or more format character (to right)
a prefix number specifies how many format characters
| \ | prefixes a fixed character, for example "\-"
|
|
Servlets
Generally a servlet extends HttpServlet. The main method to be overridden is the method:
public void service(HttpServletRequest, HttpServletRestonse) throws IOException, ServletException.
service generally gets a database connection from the connection pool, puts the fields in a class object built around the form data via: glarf.foo = request.getParameter("foo");
The database may then be modified (usually this is done in the glarf class). Then determine if request is WML, and forwards to the appropriate page (for the response) via: getServletContext().getRequestDispatcher( dest-page).forward(request, response);
Actually, should also catch any exceptions, and forward problem to an error page. Finally, the database connection should be released.
Database Connection Pools
Generally, store the connection pool in an application attribute. The following code handles this:
IConnection Pool pool = (IConnectionPool) application.getAttribute("NameOfThisPool");
if (pool == null){
synchronized(application){
pool = (IConnectionPool) application.getAttribute("NameOfThisPool");
if (pool == null){
try{ Class.forName("org.gjt.mm.mysql.Driver").newInstance();
} catch (Exception e){
application.log("Error loading JDBC driver", e);
} pool = newConnectionPool("jdbc:mysql://localhost/thisdir", "", "", 3);
application.setAttribute("NameOfThisPool", pool);
}
}
}
|