This completes our discussion of client side programming. What is on the server side?
Dynamic Content - started with cgi
Then came servlets - why are servlets better than cgi?
But you still have to generate the entire HTML from within your program
Other similar technologies include Microsoft ASP, BEA weblogic, Cold Fusion, IBM WebSphere, Sun's Java Web Server, Allaire's JRun,
More recently, server scripting languages like PHP and Ruby have become popular, and Perl has been used as a cgi server scripting language for years.
Tomcat
Apache Jakarta Tomcat is a servlet container. You should download it from http://tomcat.apache.org and install it on your laptop.
You need jdk1.4 or higher (latest is 1.5) installed.
To test your installation, point your browser to http://localhost:8080 and you should see the tomcat home page.
CATALINA_HOME refers to the jakarta directory
The tomcat directory has a number of subdirectories.
Servlets
Servlets are java programs running inside a web server. They are accessed thru a URL and typically return HTML.
Here is a the structure of a basic servlet to handle get requests
/* servlet skeleton compile with
-classpath CATALINA_HOME\common\lib\servlet-api.jar */
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class SomeServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
String s = request.getParamater(pName);
PrintWriter out = response.getWriter();
// Use ``out'' to send content to browser
}
}
Here is the on-line help page for the HttpServlet class
An httpServeletRequest has a method getParameter which can be used to get the value of a parameter sent by the client. Here is the on-line help for an HttpServletRequest
Here is a full java program to convert dollars to Euros CurrencyConverter.java
/* CurrencyConverter.java: A servlet to convert dollars to Euros */
/* compile with -classpath <CATALINA_HOME>\common\lib\servlet-api.jar */
import java.io.*;
import java.util.*;
import java.text.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CurrencyConverter extends HttpServlet {
private static final double EXCHANGE_RATE = 0.79;
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html>");
out.println("<head><title>Currency Conversion</title></head>");
out.println("<body>");
String amount = req.getParameter("amount");
try {
NumberFormat nf = NumberFormat.getInstance();
double Value = nf.parse(amount).doubleValue();
Value *= EXCHANGE_RATE;
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
out.println("<big>" + "$" +
amount + " = €" +
nf.format(Value) + "</BIG>");
}
catch (ParseException e) {
out.println("Bad number format");
}
out.println("</body></html>");
}
}
Here is the html front end for it, CurrencyConverter.html.
<html>
<head>
<title>Currency Converter</title>
</head>
<body>
<form method=GET action="servlet/CurrencyConverter">
<h3>Simple Currency Converter</h3>
<p>Use this form to convert US dollars to Euros (€)
</p>
Type the amount to be converted in the box
<input type=text name="amount">
<input type=submit>
</form>
</body>
</html>
To deploy this
<web-app>
....
<servlet>
<servlet-name>CurrencyConverter</servlet-name>
<servlet-class>CurrencyConverter</servlet-class>
</servlet>
...
<servlet-mapping>
<servlet-name>CurrencyConverter</servlet-name>
<url-pattern>/servlet/CurrencyConverter</url-pattern>
</servlet-mapping>
...
The life of a servlet
An instance is created, often at startup time, by the container, This
calls the init() function. While it is running each request
calls the service() method, which in turn implements
doGet() or doPost(). Each request runs in a
separate thread. Eventually it is destroyed with the
destroy() method.
The get request is supposed to be idempotent (calling it more than once is like calling it once). The post request is not necessarily idempotent (hitting the submit button twice). But there is nothing in the code to ensure this.
Besides parameters, what else can you get from the request object
string client = request.getHeader("User-Agent");
Cookie[] cookies = request.getCookies();
HttpSession session = request.getSession();
String theMethod = request.getMethod();
InputStream in = request.getInputStream();
What other response methods would you use besides getWriter()
The servlet can redirect response.sendRedirect("http.//..."); This sends a 301 error code to the browser along with the url, and the browser should know enough to contact the new url
Features of a web app
One web app can have multiple servlets
ServletConfig is one per servlet
ServletContext is one per web app
The general form to access a servlet is
http://<host>:port/<Context Root>/<Servlet Path>?query-string
The Deployment Descriptor
CATALINA_HOME/webapps/contextroot/WEB-INF/web.xml
You can initialize parameters in the Deployment Descriptor file
<servlet> ... <init-param> <param-name>RATE<param-name> <param-value>.82</param-value> </init-param> </servlet>in the servlet code String s = getServletContext().getInitParameter("RATE");
Distinguish between servlet init parameters and context init parameters
You can also change the url
<servlet>
<servlet-name>CurrencyConverter</servlet-name>
<servlet-class>CurrencyConverter</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CurrencyConverter</servlet-name>
<url-pattern>/dollar2euro</url-pattern>
</servlet-mapping>
But you have to change the action in the html code
action=dollar2euros
You do this for two reasons, it makes it easier to move stuff around. you just have to change the dd, not the html file, and it is a security measure, it hides the file structure from the user.
Sessions
By default, a servlet is stateless, but often multiple connections apply to the same session. One way to maintain session information is with an HttpSession object
On the client's first request, the container generates a unique session id and sends it back to the client. All subsequent requests from the client will contain this.
This is done with cookies, but the Httpsession hides the cookie details from the application.
HttpSession session = request.getSession();
if (session.isNew()) // this is a new session
session.setAttribute("foo","bar");
session.getAttribute("foo");
This only works if the client accepts cookies
Here is a very simple jsp file
<html>
<head>
<title>Date JSP</title>
</head>
<body>
<h1>Date JSP</h1>
<p>The Current Time is:
<%= new java.util.Date() %>
</p>
</body>
</html>
This file has a .jsp suffix. The first time it is invoked, Jasper
reads this file, generates a java servlet file, compiles it, and
puts the class file in the appropriate directory.
JSP syntax
There are three types of elements, Directives, Scripting elements, and Action elements
A directive has this syntax
<%@ directive (attribute=''value'')* %>
There are three types of directives: page directives, include directives , tag library directives
The page directive has
eleven possible attributes, of which we care about only
one, import
<%@ page import="java.io.*" %>
The include directive allows you to include the contents of
other files in your jsp page
<%@ include file=''includes/headers.html'' %>
We will not discuss tag libraries in this course, but it is possible to define your own jsp tags and put them in a tag library.
Scripting elements There are three types of scripting elements: scriptlets, declarations, and expressions
scriptlets are code blocks of java, they start with <% and end with %> The code is copied directly into the java file created by jasper. Here is a short program which uses the page directive and scriptlets.
<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.text.*" %>
<%! private static final double EXCHANGE_RATE = 0.79; %>
<%
String amount = request.getParameter("amount");
try {
NumberFormat nf = NumberFormat.getInstance();
double Value = nf.parse(amount).doubleValue();
Value *= EXCHANGE_RATE;
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
%>
<html>
<head><title>Currency Conversion JSP</title></head>
<body>
<big>
$ <%= amount %> =
€ <%= nf.format(Value) %>
</big>
</body>
</html>
<%
}
catch (ParseException e) {
out.println("Bad number format");
}
%>
You can look at the java file which is created by jasper. This is
often useful for debugging. Here is the file created from the
above jsp. It's path name is
CATALINA_HOME\work\Catalina\localhost\myJSPApp\org\apache\jsp\CurrencyConverter_jsp.java
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.io.*;
import java.util.*;
import java.text.*;
public final class CurrencyConverter_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final double EXCHANGE_RATE = 0.79;
private static java.util.Vector _jspx_dependants;
public java.util.List getDependants() {
return _jspx_dependants;
}
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write('\n');
out.write('\n');
out.write('\n');
out.write('\n');
out.write('\n');
String amount = request.getParameter("amount");
try {
NumberFormat nf = NumberFormat.getInstance();
double Value = nf.parse(amount).doubleValue();
Value *= EXCHANGE_RATE;
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
out.write("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head><title>Currency Conversion JSP</title></head>\n");
out.write(" <body>\n");
out.write(" <h1>Conversion from dollars to euros</h1>\n");
out.write(" <p>\n");
out.write(" <big>\n");
out.write(" $ ");
out.print( amount );
out.write(" =\n");
out.write(" € ");
out.print( nf.format(Value) );
out.write("\n");
out.write(" </big>\n");
out.write(" </body>\n");
out.write("</html>\n");
}
catch (ParseException e) {
out.println("Bad number format");
}
out.write('\n');
out.write('\n');
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
}
} finally {
if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
JSP Implicit Objects There are a number of implicit objects
which will be in the java file created by your jsp, and you can access
these from a scriptlet. Here they are. The types should be obvious
Expressions get evaluated when the jsp page is requested and the result is converted to a string and fed to the print method of the out implicit object. The first jsp (date) used an expression.
Action elements
Here is a list of action elements
jsp.useBean jsp.setProperty jsp.getProperty jsp.param jsp.include jsp.forward jsp.plugin jsp.params jsp.fallbackWe are only concerned with the first three, which pertain to javabeans. A javabean is a regular java class with some special characteristics
The jsp:useBean action is a directive to the jsp compiler to use a particular bean. Here is an example.
<jsp:useBean id="converter" class="converter.CurrencyConverterBean">
There is an optional scope variable which can have these values: page (default), request, session, application
The jsp.setProperty and jsp.getProperty are used to set and get variables in the bean.
<jsp:setProperty name="converter" property="amount" value="3"/>
<jsp:getProperty name="converter" property="Value"/>
Here is our currency converter program using a javabean. The first program is the bean itself, which is just a simple java class which has the bean characteristics.
package converters;
import java.util.*;
import java.text.*;
public class CurrencyConverterBean {
private static final double EXCHANGE_RATE = 0.79;
private NumberFormat nf = NumberFormat.getInstance();
private String amount;
public void setAmount(String amount) {
this.amount = amount;
}
public String getEuroval() {
try {
double Value = nf.parse(amount).doubleValue();
Value *= EXCHANGE_RATE;
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
return "€" + nf.format(Value);
}
catch (ParseException e) {
return ("Bad number format");
}
}
}
Here is the jsp file that uses this bean.
<jsp:useBean id="converter" class="converters.CurrencyConverterBean" scope="page" >
<jsp:setProperty name="converter" property="amount" />
</jsp:useBean>
<html>
<head><title>Currency Converter JSP</title></head>
<body>
<big>
<jsp:getProperty name="converter" property="amount" /> = <jsp:getProperty name="converter" property="euroval" />
</big>
</body>
</html>
If you don't like my example of JSP and Beans, here is an article called What are JavaBeans? Read both this and the next article Calling JavaBeans from a JSP page.
There are lots of jsp resources on the web. Here is a link to the sun page on jsp syntax.
Here's a very comprehensive tutorial on servlets and JSPs. The link to the JSP material is at the bottom of the righthand column.