BIT 4303 DL Chapter Nine Ten
BIT 4303 DL Chapter Nine Ten
Java Servlets
In the early days, web servers deliver static contents that are indifferent to users' requests. Java
servlets are server-side programs (running inside a web server) that handle clients' requests and
return a customized or dynamic response for each request. The dynamic response could be based
on user's input (e.g., search, online shopping, online transaction) with data retrieved from
databases or other applications, or time-sensitive data (such as news and stock prices).
Java servlets typically run on the HTTP protocol. HTTP is an asymmetrical request-response
protocol. The client sends a request message to the server, and the server returns a response
message as illustrated.
Server-Side Technologies
There are many (competing) server-side technologies available: Java-based (servlet, JSP, JSF,
Struts, Spring, Hibernate), ASP, PHP, CGI Script, and many others.
Java servlet is the foundation of the Java server-side technology, JSP (JavaServer Pages), JSF
(JavaServer Faces), Struts, Spring, Hibernate, and others, are extensions of the servlet
technology.
Pre-requisites
HTML, Java Programming Language, HTTP and Apache Tomcat Server, SQL and MySQL
Database System, and many others.
Servlets are server-side programs run inside a Java-capable HTTP server. Apache Tomcat
Server (@ http://tomcat.apache.org) is the official Reference Implementation (RI) for Java
servlet and JSP, provided free by open-source foundation Apache (@ http://www.apache.org).
You need to install Tomcat to try out Java servlets. Read "How to Install Tomcat and Get Started
Java Servlet Programming".
I shall denote Tomcat's installed directory as <CATALINA_HOME>, and assume that Tomcat server
is running in port 8080.
Java Servlet has these versions: [TODO features and what is new]
J2EE 1.2 (December 12, 1999) (Java Servlet 2.2, JSP 1.1, EJB 1.1, JDBC 2.0)
J2EE 1.3 (September 24, 2001) (Java Servlet 2.3, JSP 1.2, EJB 2.0, JDBC 2.1)
J2EE 1.4 (November 11, 2003) (Java Servlet 2.4, JSP 2.0, EJB 2.1, JDBC 3.0)
Java EE 5 (May 11, 2006) (Java Servlet 2.5, JSP 2.1, JSTL 1.2, JSF 1.2, EJB 3.0, JDBC
3.0)
Java EE 6 (December 10, 2009) (Java Servlet 3.0, JSP 2.2/EL 2.2, JSTL 1.2, JSF 2.0,
EJB 3.1, JDBC 4.0)
Java EE 7: expected in end of 2012.
Java Servlet is the foundation technology for Java server-side programming. You need to
understand Servlet thoroughly before you could proceed to other Java server-side technologies
such as JavaServer Pages (JSP) and JavaServer Faces (JSF).
2. Review of HTTP
A HTTP Servlet runs under the HTTP protocol. It is important to understanding the HTTP
protocol in order to understand server-side programs (servlet, JSP, ASP, PHP, etc) running over
the HTTP. Read "HTTP Basics", if needed.
In brief, HTTP is a request-response protocol. The client sends a request message to the server.
The server, in turn, returns a response message. The messages consists of two parts: header
(information about the message) and body (contents). Header provides information about the
messages. The data in header is organized in name-value pairs.
Read "HTTP Request and Response Messages" for the format, syntax of request and response
messages, and examples.
Let us begin by writing a servlet that says hello in response to a client's request. We shall use
JDK and Tomcat to understand the basics, instead of IDE such as Eclipse/NetBeans. Once you
understand the basics, you should use Eclipse/NetBeans to develop your webapp for better
productivity.
We shall begin by defining a new webapp (web application) called "helloservlet" in Tomcat.
A webapp, known as a web context in Tomcat, comprises a set of resources, such as HTML files,
CSS, JavaScripts, images, programs and libraries.
A Java webapp has a standardized directory structure for storing various types of resources.
Servlets are Java programs that runs inside a Java-capable HTTP server. A user can invoke a
servlet by issuing a specific URL from the browser (HTTP client). In this example, we shall
write a servlet called "HelloServlet.java" and compiled into "HelloServlet.class". A
client can invoke "HelloServlet.class" by issuing URL
http://hostname:port/helloServlet/sayhello (i.e., "sayhello" relative to the webapp).
A servlet shall be kept inside a Java package (instead of the default no-name package) for proper
deployment. Let's call our package "mypkg". Create a sub-directory called "mypkg" under "WEB-
INF\src". Use a programming text editor to enter the following source codes, and save as
"HelloServlet.java" in "<CATALINA_HOME>\webapps\helloservlet\WEB-INF\src\mypkg".
1 // To save as "<CATALINA_HOME>\webapps\helloservlet\WEB-
2 INF\src\mypkg\HelloServlet.java"
3 package mypkg;
4
5 import java.io.*;
6 import javax.servlet.*;
7 import javax.servlet.http.*;
8
9 public class HelloServlet extends HttpServlet {
10 @Override
11 public void doGet(HttpServletRequest request, HttpServletResponse
12 response)
13 throws IOException, ServletException {
14 // Set the response message's MIME type
15 response.setContentType("text/html;charset=UTF-8");
16 // Allocate a output writer to write the response message into the
17 network socket
18 PrintWriter out = response.getWriter();
19
20 // Write the response message, in an HTML page
21 try {
22 out.println("<!DOCTYPE html>");
23 out.println("<html><head>");
24 out.println("<meta http-equiv='Content-Type' content='text/html;
25 charset=UTF-8'>");
26 out.println("<title>Hello, World</title></head>");
27 out.println("<body>");
28 out.println("<h1>Hello, world!</h1>"); // says Hello
29 // Echo client's request information
30 out.println("<p>Request URI: " + request.getRequestURI() +
31 "</p>");
32 out.println("<p>Protocol: " + request.getProtocol() + "</p>");
33 out.println("<p>PathInfo: " + request.getPathInfo() + "</p>");
34 out.println("<p>Remote Address: " + request.getRemoteAddr() +
35 "</p>");
36 // Generate a random number upon each request
37 out.println("<p>A Random Number: <strong>" + Math.random() +
38 "</strong></p>");
out.println("</body>");
out.println("</html>");
} finally {
out.close(); // Always close the output writer
}
}
}
We define a Java class called HelloServlet (in Line 8). Line 2 places this class in a
package called mypkg. Hence, we save the source file under "mypkg" of the
"helloservlet\WEB-INF\src" directory, following the Java's standard package
directory structure.
We need the Servlet API library to compile this program. Servlet API is not part of JDK
or Java SE (but belongs to Java EE). Tomcat provides a copy of servlet API called
"servlet-api.jar" in "<CATALINA_HOME>\lib". You could copy "servlet-api.jar"
from "<CATALINA_HOME>\lib" to "<JAVA_HOME>\jre\lib\ext" (the JDK Extension
Directory), or include the Servlet JAR file in your CLASSPATH.
To compile the program under JDK, we need to use the -d option to specify the output
destination directory to place the compiled class in "helloservlet\WEB-
INF\class\mypkg" directory.
// Change directory to <CATALINA_HOME>\webapps\helloservlet\WEB-INF
d:\...> cd <CATALINA_HOME>\webapps\helloservlet\WEB-INF
// Compile the source file and place the class in the specified
destination directory
d:\<CATALINA_HOME>\webapps\helloservlet\WEB-INF> javac -d classes
src\mypkg\HelloServlet.java
The option "-d classes" specifies the output destination directory, relative to the
current directory. The output is <CATALINA_HOME>\webapps\helloservlet\WEB-
A web user invokes a servlet, which is kept in the web server, by issuing a specific URL from
the browser. In this example, we shall configure the following request URL to trigger the
"HelloServlet":
http://hostname:port/helloservlet/sayhello
To run the servlet, first start the Tomcat server. Verify that the web context "helloservlet" has
been deployed by observing the following messages in the Tomcat's console:
http://localhost:8080/helloservlet/sayhello
Try selecting "View Source" in your browser, which produces these output:
<!DOCTYPE html>
<html><head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>Hello, World</title></head>
<body>
<h1>Hello, world!</h1>
<p>Request URI: /helloservlet/sayhello</p>
<p>Protocol: HTTP/1.1</p>
<p>PathInfo: null</p>
<p>Remote Address: 127.0.0.1</p>
<p>A Random Number: <strong>0.4320795689818858</strong></p>
</body>
</html>
It is important to take note that users receive the output of the servlet. User does not receive the
servlet's program codes, which are kept under a hidden directory "WEB-INF" and not directly
accessible by web users.
Everything that can possibly go wrong will go wrong... Read "Common Error Messages". The
likely errors are "404 File Not Found" and "500 Internal Server Error".
Create the following HTML script, and save as "form_input.html" under the context root
"helloservlet".
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
5 <title>User Input Form</title>
6 </head>
7
8 <body>
9 <h2>User Input Form</h2>
10 <form method="get" action="echo">
11 <fieldset>
12 <legend>Personal Particular</legend>
13 Name: <input type="text" name="username" /><br /><br />
14 Password: <input type="password" name="password" /><br /><br />
15 Gender: <input type="radio" name="gender" value="m" checked />Male
16 <input type="radio" name="gender" value="f" />Female<br /><br />
17 Age: <select name = "age">
18 <option value="1">< 1 year old</option>
19 <option value="99">1 to 99 years old</option>
20 <option value="100">> 99 years old</option>
21 </select>
22 </fieldset>
23
24 <fieldset>
25 <legend>Languages</legend>
26 <input type="checkbox" name="language" value="java" checked />Java
27 <input type="checkbox" name="language" value="c" />C/C++
28 <input type="checkbox" name="language" value="cs" />C#
29 </fieldset>
30
31 <fieldset>
32 <legend>Instruction</legend>
33 <textarea rows="5" cols="30" name="instruction">Enter your instruction
34 here...</textarea>
35 </fieldset>
36
37 <input type="hidden" name="secret" value="888" />
38 <input type="submit" value="SEND" />
39 <input type="reset" value="CLEAR" />
40 </form>
41 </body>
</html>
Start the tomcat server. Issue the following URL to request for the HTML page:
http://localhost:8080/helloservlet/form_input.html
Explanation
The <fieldset>...</fieldset> tag groups related elements and displays them in a box.
The <legend>...</legend> tag provides the legend for the box.
This HTML form (enclosed within <form>...</form>) contains the following types of
input elements:
1. Text field (<input type="text">): for web users to enter text.
2. Radio buttons (<input type="radio">): choose any one (and possibly none).
3. Pull-down menu (<select> and <option>): pull-down menu of options.
4. Checkboxes (<input type="checkbox">): chose none or more.
5. Text area (<textarea>...<textarea>): for web users to enter multi-line text.
(Text field for single line only.)
6. Hidden field (<input type="hidden">): for submitting hidden name=value pair.
7. Submit button (<input type=submit>): user clicks this button to submit the
form data to the server.
8. Reset button (<input type="reset">): resets all the input field to their default
value.
Each of the input elements has an attribute "name", and an optional attribute "value". If
an element is selected, its "name=value" pair will be submitted to the server for
processing.
The <form> start-tag also specifies the URL for submission in the action="url"
attribute, and the request method in the method="get|post" attribute.
For example, suppose that we enter "Alan Smith" in the text field, select "male", and click the
"SEND" button, we will get a "404 page not found" error (because we have yet to write the
processing script). BUT observe the destination URL:
http://localhost:8080/helloservlet/echo?username=Alan+Smith&gender=m&....
Observe that:
Similar to the "HelloServlet", we define the "EchoServlet" under package "mypkg", and save
the source file as "<CATALINA_HOME>\webapps\helloservlet\WEB-
INF\src\mypkg\EchoServlet.java".
1 // To save as "<CATALINA_HOME>\webapps\helloservlet\WEB-
2 INF\src\mypkg\EchoServlet.java"
3 package mypkg;
4
5 import java.io.*;
6 import javax.servlet.*;
7 import javax.servlet.http.*;
8 import java.util.*;
9
10 public class EchoServlet extends HttpServlet {
11
12 @Override
13 public void doGet(HttpServletRequest request, HttpServletResponse
14 response)
15 throws IOException, ServletException {
16 // Set the response message's MIME type
17 response.setContentType("text/html; charset=UTF-8");
18 // Allocate a output writer to write the response message into the
19 network socket
20 PrintWriter out = response.getWriter();
21
22 // Write the response message, in an HTML page
23 try {
24 out.println("<!DOCTYPE html>");
25 out.println("<html><head>");
26 out.println("<meta http-equiv='Content-Type' content='text/html;
27 charset=UTF-8'>");
28 out.println("<title>Echo Servlet</title></head>");
29 out.println("<body><h2>You have enter</h2>");
30
31 // Retrieve the value of the query parameter "username" (from
32 text field)
33 String username = request.getParameter("username");
34 // Get null if the parameter is missing from query string.
35 // Get empty string or string of white spaces if user did not
36 fill in
37 if (username == null
38 || (username = htmlFilter(username.trim())).length() == 0)
39 {
40 out.println("<p>Name: MISSING</p>");
41 } else {
42 out.println("<p>Name: " + username + "</p>");
43 }
44
45 // Retrieve the value of the query parameter "password" (from
46 password field)
47 String password = request.getParameter("password");
48 if (password == null
49 || (password = htmlFilter(password.trim())).length() == 0)
50 {
51 out.println("<p>Password: MISSING</p>");
52 } else {
53 out.println("<p>Password: " + password + "</p>");
54 }
55
56 // Retrieve the value of the query parameter "gender" (from radio
57 button)
58 String gender = request.getParameter("gender");
59 // Get null if the parameter is missing from query string.
60 if (gender == null) {
61 out.println("<p>Gender: MISSING</p>");
62 } else if (gender.equals("m")) {
63 out.println("<p>Gender: male</p>");
64 } else {
65 out.println("<p>Gender: female</p>");
66 }
67
68 // Retrieve the value of the query parameter "age" (from pull-
69 down menu)
70 String age = request.getParameter("age");
71 if (age == null) {
72 out.println("<p>Age: MISSING</p>");
73 } else if (age.equals("1")) {
74 out.println("<p>Age: < 1 year old</p>");
75 } else if (age.equals("99")) {
76 out.println("<p>Age: 1 to 99 years old</p>");
77 } else {
78 out.println("<p>Age: > 99 years old</p>");
79 }
80
81 // Retrieve the value of the query parameter "language" (from
82 checkboxes).
83 // Multiple entries possible.
84 // Use getParameterValues() which returns an array of String.
85 String[] languages = request.getParameterValues("language");
86 // Get null if the parameter is missing from query string.
87 if (languages == null || languages.length == 0) {
88 out.println("<p>Languages: NONE</p>");
89 } else {
90 out.println("<p>Languages: ");
91 for (String language : languages) {
92 if (language.equals("c")) {
93 out.println("C/C++ ");
94 } else if (language.equals("cs")) {
95 out.println("C# ");
96 } else if (language.equals("java")) {
97 out.println("Java ");
98 }
99 }
100 out.println("</p>");
101 }
102
103 // Retrieve the value of the query parameter "instruction" (from
104 text area)
105 String instruction = request.getParameter("instruction");
106 // Get null if the parameter is missing from query string.
107 if (instruction == null
108 || (instruction = htmlFilter(instruction.trim())).length()
109 == 0
110 || instruction.equals("Enter your instruction here...")) {
111 out.println("<p>Instruction: NONE</p>");
112 } else {
113 out.println("<p>Instruction: " + instruction + "</p>");
114 }
115
116 // Retrieve the value of the query parameter "secret" (from
117 hidden field)
118 String secret = request.getParameter("secret");
119 out.println("<p>Secret: " + secret + "</p>");
120
121 // Get all the names of request parameters
122 Enumeration names = request.getParameterNames();
123 out.println("<p>Request Parameter Names are: ");
124 if (names.hasMoreElements()) {
125 out.print(htmlFilter(names.nextElement().toString()));
126 }
127 do {
128 out.print(", " + htmlFilter(names.nextElement().toString()));
129 } while (names.hasMoreElements());
130 out.println(".</p>");
131
132 // Hyperlink "BACK" to input page
133 out.println("<a href='form_input.html'>BACK</a>");
134
135 out.println("</body></html>");
136 } finally {
137 out.close(); // Always close the output writer
138 }
139 }
140
141 // Redirect POST request to GET request.
142 @Override
143 public void doPost(HttpServletRequest request, HttpServletResponse
144 response)
145 throws IOException, ServletException {
146 doGet(request, response);
147 }
148
149 // Filter the string for special HTML characters to prevent
150 // command injection attack
151 private static String htmlFilter(String message) {
152 if (message == null) return null;
153 int len = message.length();
StringBuffer result = new StringBuffer(len + 20);
char aChar;
The query string comprises name=value pairs. We can retrieve the query parameters
from the request message (captured in doGet()'s argument HttpServletRequest
request) via one of the following methods:
request.getParameter("paramName")
// Returns the parameter value in a String.
// Returns null if parameter name does not exist.
// Returns the first parameter value for a multi-value parameter.
request.getParameterValues("paramName")
// Return all the parameter values in a String[].
// Return null if the parameter name does not exist.
request.getParameterNames()
// Return all the parameter names in a java.util.Enumeration,
possibly empty.
Our <form>'s action attribute refers to relative URL "echo", which has to be mapped to the
EchoServlet.class in the web application deployment descriptor file "WEB-INF\web.xml":
<servlet>
<servlet-name>HelloWorldServlet</servlet-name>
<servlet-class>mypkg.HelloServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>EchoServletExample</servlet-name>
<servlet-class>mypkg.EchoServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/sayhello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>EchoServletExample</servlet-name>
<url-pattern>/echo</url-pattern>
</servlet-mapping>
</web-app>
Two request methods, GET and POST, are available for submitting form data, to be specified in
the <form>'s attribute "method=GET|POST". GET and POST performs the same basic function.
That is, gather the name-value pairs of the selected input elements, URL-encode, and pack them
into a query string. However, in a GET request, the query string is appended behind the URL,
separated by a '?'. Whereas in a POST request, the query string is kept in the request body (and
not shown in the URL). The length of query string in a GET request is limited by the maximum
length of URL permitted, whereas it is unlimited in a POST request. I recommend POST request
for production, as it does not show the strange looking query string in the URL, even if the
amount of data is limited. In this tutorial, I use GET method, so that you can inspect the query
string on the URL.
Inside the servlet, GET request is processed by the method doGet(), while POST request is
processed by the method doPost(). Since they often perform identical operations, we re-direct
doPost() to doGet() (or vice versa), as follows:
HTTP is a request-response protocol. The client sends a request message to the server. The
server, in turn, returns a response message. The request and response messages consists of two
parts: header (information about the message) and body (contents). Header provides information
about the messages. The data in header is organized in name-value pairs. Read "HTTP Request
and Response Messages" for the format, syntax of request and response messages.
5.1 HttpServletRequest
The request message is encapsulated in an HttpServletRequest object, which is passed into the
doGet() methods. HttpServletRequest provides many methods for you to retrieve the headers:
5.2 HttpServletResponse
Example: [TODO]
6. Session Tracking
HTTP is a stateless protocol. In other words, the current request does not know what has been
done in the previous requests. This creates a problem for applications that runs over many
requests, such as online shopping (or shopping cart). You need to maintain a so-called session to
pass data among the multiple requests.
1. Cookie: A cookie is a small text file that is stored in the client's machine, which will be
send to the server on each request. You can put your session data inside the cookie. The
biggest problem in using cookie is clients may disable the cookie.
2. URL Rewriting: Passes data by appending a short text string at the end of every URL,
e.g., http://host/path/file.html;jsessionid=123456. You need to rewrite all the
URLs (e.g., the "action" attribute of <form>) to include the session data.
3. Hidden field in an HTML form: pass data by using hidden field tag (<input
type="hidden" name="session" value="...." />). Again, you need to include the
hidden field in all the pages.
6.1 HttpSession
Programming your own session tracking (using the above approaches) is tedious and
cumbersome. Fortunately, Java Servlet API provides a session tracking facility, via an interface
called javax.servlet.http.HttpSession. It allows servlets to:
View and manipulate information about a session, such as the session identifier, creation
time, and last accessed time.
Bind objects to sessions, allowing user information to persist across multiple user
requests.
1. Check if a session already exists. If so, use the existing session object; otherwise, create a
new session object. Servlet API automates this step via the getSession() method of
HttpServletRequest:
2. // Retrieve the current session. Create one if not exists
3. HttpSession session = request.getSession(true);
4. HttpSession session = request.getSession(); // same as above
5.
6. // Retrieve the current session.
7. // Do not create new session if not exists but return null
HttpSession session = request.getSession(false);
The first statement returns the existing session if exists, and create a new HttpSession
object otherwise. Each session is identified via a session ID. You can use
session.getID() to retrieve the session ID string.
HttpSession, by default, uses cookie to pass the session ID in all the client's requests
within a session. If cookie is disabled, HttpSession switches to URL-rewriting to
append the session ID behind the URL. To ensure robust session tracking, all the URLs
emitted from the server-side programs should pass thru the method
response.encodeURL(url). If cookie is used for session tracking, encodeURL(url)
returns the url unchanged. If URL-rewriting is used, encodeURL(url) encodes the
specified url by including the session ID.
8. The session object maintains data in the form of key-value pairs. You can use
session.getAttribute(key) to retrieve the value of an existing key,
session.setAttribute(key, value) to store new key-value pair, and
session.removeAttribute(key) to remove an existing key-value pair. For example,
9. // Allocate a shopping cart (assume to be a list of String)
10. List<String> shoppingCart = new ArrayList<>();
11. // Populate the shopping cart
12. shoppingCart.add("Item 1");
13. .....
14. // Retrieve the current session, create one if not exists
15. HttpSession session = request.getSession(true);
16. // Place the shopping cart inside the session
17. synchronized (session) { // synchronized to prevent concurrent
updates
18. session.setAttribute("cart", shoppingCart);
19. }
.....
Any page within the session can retrieve the shopping cart:
20. You can use session.invalidate() to terminate and remove a session. You can use set
setMaxInactiveInterval() and getMaxInactiveInterval() to set and get the
inactive interval from the last client request, before the server invalidate the session.
6.2 Example
The following servlet demonstrates the use of session, by counting the number of accesses within
this session from a particular client. We also use getID() to retrieve the session ID,
getCreationTime() and getLastAccessedTime() to get the session creation and last accessed
times.
SessionServlet.java
// To save as "<CATALINA_HOME>\webapps\helloservlet\WEB-
INF\src\mypkg\SessionServlet.java"
package mypkg;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Date;
web.xml
......
<servlet>
<servlet-name>SessionTestServlet</servlet-name>
<servlet-class>mypkg.SessionServlet</servlet-class>
</servlet>
......
......
<servlet-mapping>
<servlet-name>SessionTestServlet</servlet-name>
<url-pattern>/sessiontest</url-pattern>
</servlet-mapping>
What is PHP?
It is powerful enough to be at the core of the biggest blogging system on the web
(WordPress)!
It is deep enough to run the largest social network (Facebook)!
It is also easy enough to be a beginner's first server side language!
With PHP you are not limited to output HTML. You can output images, PDF files, and even
Flash movies. You can also output any text, such as XHTML and XML.
Why PHP?
PHP runs on various platforms (Windows, Linux, Unix, Mac OS X, etc.)
PHP is compatible with almost all servers used today (Apache, IIS, etc.)
PHP supports a wide range of databases
PHP is free. Download it from the official PHP resource:
PHP is easy to learn and runs efficiently on the server side
A PHP script is executed on the server, and the plain HTML result is sent back to the
browser.
Example
<!DOCTYPE html>
<html>
<body>
<?php
echo "Hello World!";
?>
</body>
</html>
Example
<?php
$txt = "Hello world!";
$x = 5;
$y = 10.5;
?>
After the execution of the statements above, the variable $txt will hold the value Hello world!,
the variable $x will hold the value 5, and the variable $y will hold the value 10.5.
Note: When you assign a text value to a variable, put quotes around the value.
Note: Unlike other programming languages, PHP has no command for declaring a variable. It is
created the moment you first assign a value to it.
PHP Variables
A variable can have a short name (like x and y) or a more descriptive name (age, carname,
total_volume).
A variable starts with the $ sign, followed by the name of the variable
A variable name must start with a letter or the underscore character
A variable name cannot start with a number
A variable name can only contain alpha-numeric characters and underscores (A-z, 0-9,
and _ )
Variable names are case-sensitive ($age and $AGE are two different variables)
Output Variables
The PHP echo statement is often used to output data to the screen.
The following example will show how to output text and a variable:
Example
<?php
$txt = "W3Schools.com";
echo "I love $txt!";
?>
The scope of a variable is the part of the script where the variable can be referenced/used.
local
global
static
Example
<?php
$x = 5; // global scope
function myTest() {
// using x inside this function will generate an error
echo "<p>Variable x inside function is: $x</p>";
}
myTest();
A variable declared within a function has a LOCAL SCOPE and can only be accessed within
that function:
Example
<?php
function myTest() {
$x = 5; // local scope
echo "<p>Variable x inside function is: $x</p>";
}
myTest();
To do this, use the global keyword before the variables (inside the function):
Example
<?php
$x = 5;
$y = 10;
function myTest() {
global $x, $y;
$y = $x + $y;
}
myTest();
echo $y; // outputs 15
?>
PHP also stores all global variables in an array called $GLOBALS[index]. The index holds the
name of the variable. This array is also accessible from within functions and can be used to
update global variables directly.
Example
<?php
$x = 5;
$y = 10;
function myTest() {
$GLOBALS['y'] = $GLOBALS['x'] + $GLOBALS['y'];
}
myTest();
echo $y; // outputs 15
?>
To do this, use the static keyword when you first declare the variable:
Example
<?php
function myTest() {
static $x = 0;
echo $x;
$x++;
}
myTest();
myTest();
myTest();
?>
Then, each time the function is called, that variable will still have the information it contained
from the last time the function was called.
The PHP superglobals $_GET and $_POST are used to collect form-data.
Example
<html>
<body>
</body>
</html>
When the user fills out the form above and clicks the submit button, the form data is sent for
processing to a PHP file named "welcome.php". The form data is sent with the HTTP POST
method.
To display the submitted data you could simply echo all the variables. The "welcome.php" looks
like this:
<html>
<body>
</body>
</html>
Welcome John
Your email address is john.doe@example.com
The same result could also be achieved using the HTTP GET method:
Example
<html>
<body>
</body>
</html>
<html>
<body>
</body>
</html>
The code above is quite simple. However, the most important thing is missing. You need to
validate form data to protect your script from malicious code.
This page does not contain any form validation, it just shows how you can send and
retrieve form data.
However, the next pages will show how to process PHP forms with security in mind!
Proper validation of form data is important to protect your form from hackers and
spammers!
Both GET and POST are treated as $_GET and $_POST. These are superglobals, which means
that they are always accessible, regardless of scope - and you can access them from any function,
class or file without having to do anything special.
$_GET is an array of variables passed to the current script via the URL parameters.
$_POST is an array of variables passed to the current script via the HTTP POST method.
Note: GET should NEVER be used for sending passwords or other sensitive information!
Moreover POST supports advanced functionality such as support for multi-part binary input
while uploading files to server.
However, because the variables are not displayed in the URL, it is not possible to bookmark the
page.
Next; lets see how we can process PHP forms the secure way!
What is MySQL?
MySQL is a database system used on the web
MySQL is a database system that runs on a server
MySQL is ideal for both small and large applications
MySQL is very fast, reliable, and easy to use
MySQL uses standard SQL
MySQL compiles on a number of platforms
MySQL is free to download and use
MySQL is developed, distributed, and supported by Oracle Corporation
MySQL is named after co-founder Monty Widenius's daughter: My
The data in a MySQL database are stored in tables. A table is a collection of related data, and it
consists of columns and rows.
Databases are useful for storing information categorically. A company may have a database with
the following tables:
Employees
Products
Customers
Orders
Database Queries
A query is a question or a request.
We can query a database for specific information and have a recordset returned.
The query above selects all the data in the "LastName" column from the "Employees" table.
PDO will work on 12 different database systems, where as MySQLi will only work with MySQL
databases.
So, if you have to switch your project to use another database, PDO makes the process easy. You
only have to change the connection string and a few queries. With MySQLi, you will need to
rewrite the entire code - queries included.
Both support Prepared Statements. Prepared Statements protect from SQL injection, and are very
important for web application security.
MySQLi (object-oriented)
MySQLi (procedural)
PDO
<?php
$servername = "localhost";
$username = "username";
$password = "password";
// Create connection
$conn = new mysqli($servername, $username, $password);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "Connected successfully";
?>
Note on the object-oriented example above: $connect_error was broken until PHP 5.2.9
and 5.3.0. If you need to ensure compatibility with PHP versions prior to 5.2.9 and 5.3.0,
use the following code instead:
// Check connection
if (mysqli_connect_error()) {
die("Database connection failed: " . mysqli_connect_error());
}
<?php
$servername = "localhost";
$username = "username";
$password = "password";
// Create connection
$conn = mysqli_connect($servername, $username, $password);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
echo "Connected successfully";
?>
Example (PDO)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
try {
$conn = new PDO("mysql:host=$servername;dbname=myDB", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
?>
Notice that in the PDO example above we have also specified a database (myDB). PDO
require a valid database to connect to. If no database is specified, an exception is thrown.
Tip: A great benefit of PDO is that it has an exception class to handle any problems that
may occur in our database queries. If an exception is thrown within the try{ } block, the
script stops executing and flows directly to the first catch(){ } block.
$conn->close();
mysqli_close($conn);
Example (PDO)
$conn = null;
You will need special CREATE privileges to create or to delete a MySQL database.
<?php
$servername = "localhost";
$username = "username";
$password = "password";
// Create connection
$conn = new mysqli($servername, $username, $password);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Create database
$sql = "CREATE DATABASE myDB";
if ($conn->query($sql) === TRUE) {
echo "Database created successfully";
} else {
echo "Error creating database: " . $conn->error;
}
$conn->close();
?>
Note: When you create a new database, you must only specify the first three arguments to
the mysqli object (servername, username and password).
Tip: If you have to use a specific port, add an empty string for the database-name
argument, like this: new mysqli("localhost", "username", "password", "", port)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
// Create connection
$conn = mysqli_connect($servername, $username, $password);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
// Create database
$sql = "CREATE DATABASE myDB";
if (mysqli_query($conn, $sql)) {
echo "Database created successfully";
} else {
echo "Error creating database: " . mysqli_error($conn);
}
mysqli_close($conn);
?>
Example (PDO)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
try {
$conn = new PDO("mysql:host=$servername;dbname=myDB", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "CREATE DATABASE myDBPDO";
// use exec() because no results are returned
$conn->exec($sql);
echo "Database created successfully<br>";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
Tip: A great benefit of PDO is that it has exception class to handle any problems that may occur
in our database queries. If an exception is thrown within the try{ } block, the script stops
executing and flows directly to the first catch(){ } block. In the catch block above we echo the
SQL statement and the generated error message.
A database table has its own unique name and consists of columns and rows.
The data type specifies what type of data the column can hold. For a complete reference of all
the available data types, go to our Data Types reference.
After the data type, you can specify other optional attributes for each column:
NOT NULL - Each row must contain a value for that column, null values are not allowed
DEFAULT value - Set a default value that is added when no other value is passed
UNSIGNED - Used for number types, limits the stored data to positive numbers and zero
AUTO INCREMENT - MySQL automatically increases the value of the field by 1 each
time a new record is added
PRIMARY KEY - Used to uniquely identify the rows in a table. The column with
PRIMARY KEY setting is often an ID number, and is often used with
AUTO_INCREMENT
Each table should have a primary key column (in this case: the "id" column). Its value must be
unique for each record in the table.
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$conn->close();
?>
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
if (mysqli_query($conn, $sql)) {
echo "Table MyGuests created successfully";
} else {
echo "Error creating table: " . mysqli_error($conn);
}
mysqli_close($conn);
?>
Example (PDO)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn = null;
?>
The INSERT INTO statement is used to add new records to a MySQL table:
In the previous chapter we created an empty table named "MyGuests" with five columns: "id",
"firstname", "lastname", "email" and "reg_date". Now, let us fill the table with data.
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$conn->close();
?>
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
if (mysqli_query($conn, $sql)) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($conn);
}
mysqli_close($conn);
?>
Example (PDO)
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john@example.com')";
// use exec() because no results are returned
$conn->exec($sql);
echo "New record created successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
Chapter eleven
It is a lot more productive and efficient to use an IDE (such as Eclipse or NetBeans) to develop
your web application. You could start/stop your servers from IDE directly. You could debug
your web application in IDE, like debugging standalone application.
I strongly encourage you to study the examples, Read "Tomcat's Java Servlet Examples
Explained".
Database Servlet
Read "Java Servlet Case Study" and "Java Servlet Case Study Continue".
A servlet is a Java web component, managed by a servlet container (such as Apache Tomcat or
Glassfish), which generates dynamic content in response to client's request. A servlet container
(or servlet engine) is a web server extension which provides servlet functionality. A servlet
container contains and manages servlets throughout their life cycle.
Interface Servlet
The Servlet interface is the central abstraction of the Java servlet API. HttpServlet - the most
commonly servlet which handles HTTP requests, is a subclass of GenericServlet which
implements Servlet interface.
// Servlet's lifecycle
void init(ServletConfig config)
void destroy()
void service(ServletRequest request, ServletResponse response)
// Servlet configuration and information
ServletConfig getServletConfig()
String getServletInfo()
A servlet's life cycle is managed via the init(), service() and destroy() methods.
Servlet container (e.g., Tomcat or Glassfish) is responsible for loading and instantiating
servlets. It may load and instantiate servlets when it is started, or delay until it determines that
the servlet is needed to service a request (usually at the first request to the servlet).
The servlet container invokes the init(ServletConfig) method of the servlet, providing a
ServletConfig object as an argument. init() runs only once. It is usually used to read
persistent configuration data and initialize costly resource.
This ServletConfig object allows the servlet to access initialization parameters for this
particular servlet. These parameters are defined in the web application deployment descriptor
file (i.e., “web.xml”), under the servlet's name, as follows:
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>ServletClassFile</servlet-class>
<init-param>
<param-name>initParam1</param-name>
<param-value>initParam1Value</param-value>
</init-param>
<init-param>
<param-name>initParam2</param-name>
<param-value>initParam2Value</param-value>
</init-param>
</servlet>
The ServletConfig interface defines these methods to retrieve the initialization parameters for
this servlet.
For example,
The ServletConfig also gives servlet access to a ServletContext object that provides
information about this web context (aka web application). ServletContext will be discussed
later.
In Service
Once a servlet is initialized, the servlet container invokes its service() method to handle client
requests. This method is called once for each request. Generally, the servlet container handle
concurrent request to the same servlet by running service() on different threads (unless
SingleThreadModel interface is declared).
End of Service
When the servlet container decides that a servlet should be removed from the container (e.g.,
shutting down the container or time-out, which is implementation-dependent), it calls the
destroy() method to release any resource it is using and save any persistent state. Before the
servlet container calls the destroy(), it must allow all service() threads to complete or time-
out.
Interface ServletContext
The ServletContext interface defines a servlet's view of the webapp (or web context) in which
it is running (a better name is actually ApplicationContext). Via the ServletContext object,
a servlet can communicate with the container, e.g., write to event log, get the URL reference to
resources, and get and set attributes that other servlets in the same context can access.
There is one ServletContext object for each web application deployed into a container. You
can specify initialization parameters for a web context (that are available to all the servlet under
the web context) in the web application deployment descriptor, e.g.,
<web-app ......>
<context-param>
<param-name>jdbcDriver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</context-param>
<context-param>
<param-name>databaseUrl</param-name>
<param-value>jdbc:mysql://localhost/eshop</param-value>
</context-param>
......
</web-app>
Servlets under this web context can access the context's initialization parameters via the
ServletConfig's methods:
// ServletConfig
String getInitParameter(String name)
java.util.Enumeration getInitParameterNames()
A servlet can bind an attribute of name-value pair into the ServletContext, which will then be
available to other servlet in the same web application. The methods available are:
// ServletContext
Object getAttribute(String name)
void setAttribute(String name, Object value)
void removeAttribute(String name)
java.util.Enumeration getAttributeNames()
When building a web application, it is often useful to forward a request to another servlet, or to
include the output of another servlet in the response. The RequestDispatcher interface supports
these. The RequestDispatcher can be obtained via ServletContext:
// ServletContext
RequestDispatcher getRequestDispatcher(String servletPath)
RequestDispatcher getNamedDispatcher(String servletName)
Once the servlet obtained a RequestDispatcher of another servlet within the same web
application, it could include or forward the request to that servlet, e.g.,
RequestDispatcher rd = context.getRequestDispatcher("/test.jsp?isbn=123");
rd.include(request, response);
// or
rd.forward(request, response);
Filtering
A filter is a reusable piece of code that can transform the content of HTTP requests, responses,
and header information. Examples of filtering components are:
Authentication filters
Logging and auditing filters
Image conversion filters
Data compression filters
Encryption filters
Tokenizing filters
Filters that trigger resource access events
XSL/T filters that transform XML content
MIME-type chain filters
Caching filters
[TODO] more
The "web.xml" contains the web application deployment descriptors. Tomcat's has a system-
wide (global) "web.xml" in "<CATALINA_HOME>\conf". Each web application has its own
"web.xml" in "ContextRoot\WEB-INF", which overrides the global settings. Tomcat monitors
web.xml for all web applications and reloads the web application when web.xml changes, if
reloadable is set to true.
A Sample "web.xml"
Tomcat 6 and Glassfish 3 supports Servlets 2.5, JSP 2.1 and JSF 2.0.
<web-app ...>
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>mypkg.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/MyURL</url-pattern>
</servlet-mapping>
</web-app>
You can use wildcard '*' in the <url-pattern> for pattern matching. For example, /MyURL.*
(which is matched by /MyURL.html and etc.), /MyURL/* (which is matched by /MyURL/test,
and etc.)
Always use a custom URL for servlet, as you could choose a short and meaningful URL and
include initialisation. parameters, filter, security setting in the deployment descriptor (see the
next section).
You can pass initialization parameters in the form of name-value pairs into a particular servlet
from "web.xml". For example,
<web-app ...>
<servlet>
<servlet-name>ServletName</servlet-name>
<servlet-class>mypkg.MyServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>listing</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ServletName</servlet-name>
<url-pattern>/MyURL</url-pattern>
</servlet-mapping>
</web-app>
Inside the servlet, you can retrieve the init parameters via the ServletConfig object:
package mypkg;
public class MyServlet extends HttpServlet {
@Override
public void init() {
ServletConfig config = getServletConfig();
String strDebug = config.getInitParameter("debug");
if (strDebug.equals("true")) debug = true;
String strListing = config.getInitParameter("listing");
if (strListing.equals("true")) listing = true;
}
......
}
Specified in webapp's "WEB-INF\web.xml", and available to all the servlets under this webapp.
You can use the getInitParameter() method of ServletContext object to retrieve the init
parameters.
<web-app ......>
<context-param>
<param-name>email</param-name>
<param-value>query@abcde.com</param-value>
</context-param>
......
</web-app>
<context-param>
<param-name>email</param-name>
<param-value>query@abcde.com</param-value>
</context-param>
Use the getInitParameter() method of ServletContext object to retrieve the init parameters.
Welcome Page
Specifies the page to be displayed for request to web context root. For example,
<web-app ...>
......
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>test/index.html</welcome-file>
</welcome-file-list>
</web-app>
Servlet 3.0
For example,
@WebServlet(
name = "HelloServletExample",
urlPatterns = {"/sayhello"},
initParams = {
@WebInitParam(name = "param1", value = "value1"),
@WebInitParam(name = "param2", value = "value2")}
)
public class HelloServlet extends HttpServlet { ...... }
The above is equivalent to the following configuration in "web.xml" prior to Servlet 3.0. The
web application deployment descriptor "web.xml" has become optional in Servlet 3.0. Instead,
the container at run time will process the annotations of the classes in WEB-INF/classes and
JAR files in lib directory.
// web.xml
<servlet>
<servlet-name>HelloServletExample</servlet-name>
<servlet-class>hello.HelloServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>value2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServletExample</servlet-name>
<url-pattern>/sayhello</url-pattern>
</servlet-mapping>
@WebServlet
@WebServlet defines a servlet component and its metadata, with the following attributes:
Example:
@WebServlet("/sayHello")
public class Hello1Servlet extends HttpServlet { ...... }
// One URL pattern
@WebInitParam
@WebInitParam is Used to declare init params in servlet, with the following attributes:
String name and String value (required): Declare the name and value of the init
parameter.
String description (optional) description, default empty string "".
@WebFilter
For example, the following filter log the request time for all the requests (urlPattern="/*").
1 package mypkg;
2
3 import java.io.*;
4 import java.util.logging.Logger;
5 import javax.servlet.*;
6 import javax.servlet.annotation.*;
7 import javax.servlet.http.*;
8
9 @WebFilter(urlPatterns={"/*"})
10 public class RequestTimerFilter implements Filter {
11 private static final Logger logger
12 = Logger.getLogger(RequestTimerFilter.class.getName());
13
14 @Override
15 public void init(FilterConfig config) throws ServletException {
16 logger.info("RequestTimerFilter initialized");
17 }
18
19 @Override
20 public void doFilter(ServletRequest request, ServletResponse response,
21 FilterChain chain)
22 throws IOException, ServletException {
23 long before = System.currentTimeMillis();
24 chain.doFilter(request, response);
25 long after = System.currentTimeMillis();
26 String path = ((HttpServletRequest)request).getRequestURI();
27 logger.info(path + ": " + (after - before) + " msec");
28 }
29
30 @Override
31 public void destroy() {
32 logger.info("RequestTimerFilter destroyed");
33 }
34 }
@WebListener
@WebListener()
public class MyContextListner extends ServletContextListner { ...... }
@MultipartConfig
For uploading file using multipart/form-data POST Request. Read "Uploading Files in
Servlet 3.0".
Chapter twelve
The goal of ADO.NET is to provide a bridge between your objects in ASP.NET and your back
end database. ADO.NET provides an object-oriented view into the database, encapsulating many
of the database properties and relationships within ADO.NET objects. Further, and in many ways
most important, the ADO.NET objects encapsulate and hide the details of database access; your
objects can interact with ADO.NET objects without knowing or worrying about the details of
how the data is moved to and from the database.
The ADO object model is rich, but at its heart is a fairly straightforward set of classes. The key
class is the DataSet, which is located in the System.Data namespace.
The dataset represents a rich subset of the entire database, cached on your machine without a
continuous connection to the database. Periodically, you’ll reconnect the dataset to its parent
database, and update the database with changes to the dataset that you’ve made, and update the
dataset with changes in the database made by other processes.
The dataset captures not just a few rows from a single table, but represents a set of tables with all
the metadata necessary to represent the relationships and constraints among the tables recorded
in the original database.
The dataset is comprised of DataTable objects as well as DataRelation objects. These are
accessed as properties of the DataSet object.
ASP's primary interface to relational databases is through Microsoft's ActiveX Data Objects
(ADO). This ability to access multiple types of data stores, along with a relatively simple and flat
object model, make ADO the simplest method yet devised for retrieving data.
The three main objects in the ADO object model and their most useful and common methods are
reviewed here. In ADO, there are often several ways to accomplish a task. However, there are
reasons why you should prefer one object or method instead of another.
Before you can retrieve any data from a database, you have to create and initialize a connection
to that database. In ADO, you use a Connection object to make and break database connections.
A Connection object is a high-level object that works through a provider (think driver) mat
actually makes the data requests.
Dim Conn
Set Conn = Server.CreateObject("ADODB.Connection")
By default, connections are read-only, but you can create a read-write or write-only connection
by setting the Connection object's Mode property. There are several Mode constants - in fact,
ADO is rife with constants. You have to include the adovbs.inc file. To use the ADO constants,
include the following line in each file where you use ADO, substituting the appropriate drive and
path for your server:
If you open the adovbs.inc file with Notepad or another text editor, you'll see groups of
constants.
Typically, you only need to select one of the first three values. If you only need to read
information from the database (the most common action), use the adModeRead constant. If you
only need to write data, use the adModeWrite constant. If you need to read and write data within
a single page, use the adModeReadWrite constant. Some people always use the
adModeReadWrite constant, but that slows down data access when you only need to read or
write, but not both.
The last five constants are of less use in a Web application where you may not know how many
people are simultaneously connected. The adModeShareDenyRead constant prevents other
connections from reading the database. Similarly, the adModeShareDenyWrite constant lets
other connections read from, but not write to the database. The misnamed
adModeShareExclusive constant prevents all other connections from opening the database. To
thoroughly confuse the issue, the adModeShareDenyNone constant allows all other connections to
attach to the database with any type of permission. The adModeRecursive constant works in
concert with all of the Share-type constants except adModeShareDenyNone to propagate the
setting to sub-records of the current record. For example, you can use adShareDenyRead +
adModeRecursive to deny read permissions to sub-records.
The ConnectionString
After setting the mode, you must set the Connection object's ConnectionString property.
Although you must set this property each time you open a new Connection object, you should
define the connection string (or strings) in your application's global.asa file as an application-
level or session-level variable. There are at least three reasons to define the connection string in
the global.asa file; it means you only have one place to check for connection string problems,
you can change the connection from one database to another with minimal code changes during
development, and you can copy or move your application from one server to another very
quickly.
The ConnectionString property is both simple and complicated. It has several parts, all of which
are optional, depending on which type of connection string you're using, but typically, you
specify the following:
Provider name
Name of the database server
Name of the database you want to use
User ID (UID) with which to connect
Password (PWD) for that user ID.
You separate the parts of the connection string with semicolons. For example, at the simplest
level, you can use an Open Database Connectivity (ODBC) Data Source Name (DSN), a user ID,
and password to connect to your database. A DSN already contains the provider, the database
server, and the database name, so you don't have to specify those again.
For example:
Dim Conn
Set Conn = Server.Create0bject("ADODB.Connection")
Conn.Mode = adModeReadWrite
Conn.ConnectionString = "DSN=myDSN;UID=manas;PWD=manas;"
Unfortunately, that's not the best method. By default, ODBC DSNs use the MSDASQL provider,
but the JET OLEDB provider is faster and provides more functionality. Use this type of
connection string instead.
The ConnectionString contains the provider name, the name of the server (in this case, and the
path to the MDB file. We use the Server.MapPath function to translate the virtual path to the
actual path on the server’s disk. For example, a database at the location:
http://www.manastungare.com/users.mdb
can actually be the file:
E:\Web\Databases\users.mdb
Server.MapPath translates the first address to the second (which is what is needed by the
ADODB.Connection object.)
You must set most of the Connection object's properties before opening the connection. If you
later want to change a property, close the connection, change the property value, and then reopen
the connection.
Conn.Open
If the Open method executes without errors, you have a working connection to the database.
All the procedures so far can be simplified with an alternate syntax. The Open method accepts up
to four optional arguments: a ConnectionString, a user ID, a password, and the Options argument
consisting of a ConnectOptionEnum constant.
You can specify more than one value for the options by adding the constants together.
There are three ways to obtain data from a database using ADO. All of them require a connection.
The simplest way is to use the Execute method of the Connection object.
An SQL statement or query, table, view, or stored procedure name called the
CommandText argument
A variable called RecordsAffected that will contain the number of records affected by the
statement or query after the Execute method completes
And a CommandTypeEnum constant called Options that tells the database what type of
statement or query you want to run, and whether to return a Recordset object.
Connection objects can open tables directly, and can execute SQL in either pre-compiled form
(called Stored Procedures) or dynamically by interpreting and executing the SQL statement at
runtime. All these types of requests return records. The returned records are called result sets,
and ADO wraps the resulting rows in a Recordset object.
The return value of the Execute method, by default, is a Recordset object that contains the
result of the statement or query. You can control whether the Execute method returns a
Recordset object by adding the adExecuteNoRecords constant to the Options constant. If you're
running a SELECT statement, you generally need the resulting Recordset object; but when you're
running an INSERT or UPDATE query, you usually don't need any records returned.
When you submit a command that changes data to SQL Server, such as an UPDATE, INSERT,
or DELETE query, it always treats the statement as a transaction. If the statement fails, all
operations in the statement fail - However, you often need to execute one or more statements as a
transaction. To do that, you must wrap the statements in a high-level transaction yourself. You
manage transactions with the Connection object's BeginTrans, CommitTrans, and
RollbackTrans methods.
Recordset objects provide more functionality than simply a method for holding and scrolling
through data. A Recordset object is a table of values. It has rows and columns like a database
table; but a Recordset object is not a table. It's more like a virtual table or view.
First, the values of the Recordset object's columns may come from several different tables via a
JOIN operation. Second, the column values may be calculated values — they may not match any
value in the database. Finally, you can search and sort Recordset objects, rum them into strings
or arrays, and even persist them to and retrieve them from disk storage as objects or as XML data.
If you need a Recordset object with any type of cursor other than a forward-only, read-only
cursor, you need to open it directly rather than calling the Execute method of a Connection
object. Recordset objects also have an Open method, which takes several arguments.
The CommandText argument contains the SQL query. The Connection | ConnectionString
argument contains either a reference to an open Connection object or a valid
ConnectionString argument. If you use a ConnectionString argument, the Open method
creates a Connection object for you.
If you're going to make only one call to the database in a page, letting ADO create a Connection
object is a viable option. However, if you're going to make more than one call, you should create
and open your own Connection object. The reason is that you have more control over the type
and duration of the Connection object if you open and close it yourself.
The CursorType argument is a value derived from one or more adCursorTypeEnum values. The
following list shows the valid values and a description of each:
adOpenForwardOnly
Returns a forward-only cursor. This is the default cursor type. If you don't specify a
cursor type, ADO always returns a forward-only cursor. As the name implies, you can
only move forward, not backward, through the Recordset object. You should use this
whenever you need to make only one pass through a Recordset object because it's the
fastest type of cursor.
adOpenKeyset
Returns a keyset cursor. You can move in any direction with this cursor type first, last,
forward, backward, skip, or move to bookmark (if the provider supports bookmarks).
You can see changes that others make to the records in the Recordset object, but you can't
see records added since you opened the Recordset object. You cannot access or change
records that other users delete. Use a keyset cursor for large record sets where you need
to be able to scroll backward or you need to change. The server creates a unique
bookmark for each row when you first run the query. Those bookmarks don't change
during the life of the Recordset object, which is why you can't see new records.
adOpenDynamic
Returns a dynamic cursor. This type is exactly like a keyset cursor except that you can
see new records that others add. A dynamic cursor checks constantly for updates and
additions to the result set. It does not build a set of bookmarks for the result set, so a
dynamic cursor often opens more quickly than a keyset cursor. Dynamic cursors require
the most resources of all cursor types, so you should not use them unless you need to see
additions to the result set while the Recordset object is open.
adOpenStatic
Returns a static cursor, which is a fixed copy of a set of records. You cannot see any
changes or inserts by others without querying the database again. Recordset objects with
static cursors can be updated.
Depending on the provider, you may be able to see changes your application makes to data with
a static cursor.
The LockType argument tells ADO how to treat database locks In general, you want to avoid
locking data for updates or inserts because locks created by one user can cause problems for
other users in your application. Read-only locks do not cause such problems. The valid
LockType arguments are:
adLockReadOnly
adLockPessimistic
Pessimistic locking is the strongest type of lock. Records with pessimistic locking are
unavailable to other users of your application. Pessimistic locks occur when the server
delivers the record. The record remains locked until you close the Recordset object You
should avoid pessimistic locking in Web applications whenever possible.
adLockOptimistic
Optimistic locking locks records just before an update occurs, and unlocks them
immediately afterward. Other users can access data during the time you're updating the
record, which means they may potentially be viewing outdated data. Similarly, with
optimistic locking, multiple users may simultaneously try to update the same data,
leading to problems. You should avoid optimistic locking in Web applications whenever
possible.
AdLockBatchOptimistic
Optimistic batch locks act like optimistic locks, except they work for batch updates —
deferring immediate updates in favor of updating many records at one time rather than
updating each record immediately as with adLockOptimistic locking. It's your call
whether batch updates or immediate updates are better for your application, in part, it
depends on the level of interactivity your application demands and how people expect to
use the application.
The final Recordset.Open argument is the Options flag. The Options flag takes exactly the
same values as the Connection.Execute options argument. Again, the options argument is not
required, but you should always include it. It tells ADO whether the query is a table, view, stored
procedure, or dynamic SQL statement.
The Update method fails because even though the Recordset object may have an updateable
cursor type, the underlying connection is read-only. To open an updateable Recordset object you
must set the ConnectionMode property to adModeReadWrite.
Think of a Recordset object as a table with an empty row at the top and bottom, and a current-
record pointer. The record pointer points to only one record at a time. When you use one of the
Move methods, you don't scroll the record set - you move the record pointer. Recordset objects
have EOF (end-of-file) and BOF (beginning-of-file) methods to let you know when the record
pointer has moved past the last record or prior to the first record. EOF and BOF are Boolean
properties.
It's important to check whether a Recordset object is at the BOF or EOF position before requesting
data, because Recordset objects raise an error if you request data when the Recordset object is at
either of these two positions.
You can search and sort data with Recordset methods, although it’s much more efficient to
obtain only the data you need from the server and retrieve it already sorted. To sort a record set,
assign its Sort property the names of the field(s) you want to sort by. For example, to sort the
Recordset:
R.Sort = "LastName"
To sort by more than one field, separate the field names with commas, as follows:
You can also search for specific records in a record set. To perform the search, use the
Recordset.Find method. You specify the search conditions with the equivalent of a SQL
WHERE clause, without the word WHERE. After performing a find, the Recordset object is
positioned at the first record found, or if no records are found, at the end of the Recordset (EOF).
You may include multiple conditions, just as in a WHERE clause. In addition to the search
criteria, the Find method accepts three other optional arguments:
SkipRecords
The number of records to skip before beginning the search. This argument is particularly
useful when you're searching in a loop. By setting SkipRecords to 1, you can begin
searching in the record following the current record. When searching backward, set this
value to a negative number.
SearchDirection
Start:
The number or bookmark of the record where the search should begin. You should
specify either SkipRecords or Start, but not both.
Although we’ve been talking of Recordset objects as tables, that's just a convenient mental
model. Recordset objects actually consist of a two-dimensional array of Field objects. In the
ADO object model, Field objects contain the data. Therefore, each Field object has a type, a size,
and a value. A Field object also has properties for the numeric scale of its value, the original
value, the underlying value (in the database), the defined size, the actual size, and the precision,
as well as a list of other attributes. Most of the time you will not need to deal with the Field
object properties and methods, but its useful to study them in case you do need them.