Java Servlets
Java Servlets
Java Servlets
Today we all are aware of the need of creating dynamic web pages i.e the ones which have the capability to change the site
contents according to the time or are able to generate the contents according to the request received by the client. If you like
coding in Java, then you will be happy to know that using Java there also exists a way to generate dynamic web pages and
that way is Java Servlet. But before we move forward with our topic let’s first understand the need for server-side
extensions.
Servlets are the Java programs that runs on the Java-enabled web server or application server. They are used to handle the
request obtained from the web server, process the request, produce the response, then send response back to the web server.
Properties of Servlets :
Servlets work on the server-side.
Servlets capable of handling complex request obtained from web server.
Execution of Servlets :
Execution of Servlets involves the six basic steps:
1. The clients send the request to the web server.
2. The web server receives the request.
3. The web server passes the request to the corresponding servlet.
4. The servlet processes the request and generate the response in the form of output.
5. The servlet send the response back to the web server.
6. The web server sends the response back to the client and the client browser displays it on the screen.
A servlet life cycle can be defined as the entire process from its creation till the destruction. The following are the paths
followed by a servlet.
The service () method is called by the container and service method invokes doGet, doPost, doPut, doDelete, etc. methods
as appropriate. So you have nothing to do with service() method but you override either doGet() or doPost() depending on
what type of request you receive from the client.
The doGet() and doPost() are most frequently used methods with in each service request. Here is the signature of these two
methods.
Architecture Diagram
The following figure depicts a typical servlet life-cycle scenario.
First the HTTP requests coming to the server are delegated to the servlet container.
The servlet container loads the servlet before invoking the service() method.
Then the servlet container handles multiple requests by spawning multiple threads, each thread executing the
service() method of a single instance of the servlet.
Servlet API
1. Servlet API
2. Interfaces in javax.servlet package
3. Classes in javax.servlet package
4. Interfaces in javax.servlet.http package
5. Classes in javax.servlet.http package
The javax.servlet and javax.servlet.http packages represent interfaces and classes for servlet api.
The javax.servlet package contains many interfaces and classes that are used by the servlet or web container. These are not
specific to any protocol.
The javax.servlet.http package contains interfaces and classes that are responsible for http requests only
Initialization
On receiving the request from the client, the servlet engine (container) checks whether it is the first request to the servlet. If it
is the first request, then the servlet engine instantiates the servlet and initializes it by sending the initialization method call
that is, init(). The code related to database connections is placed in the init() method.
Service calls
After initialization, servlets are capable of handling many requests, by means of a single servlet instance. Each client request
generates one service call (that is, thread to provide service) and these calls can be concurrent. In a JDBC servlet, the service
calls process incoming name value pair information from a browser, and return raw data or HTML pages (dynamic or static)
as output. Note that in the name-value pair, the name indicates the parameter name and value indicates the value(s) of that
parameter.
Servlet termination
The destroy method provided by the HttpServlet class destroys the servlet and logs the destruction. This method is
overridden to destroy the resources used in the servlet. The destroy method should undo any initialization work that is done
in the init() method. In the TestDataBaseCon example of Program, the destroy method is the used for this purpose.
Program Using the destroy method for servlet termination.
public class TestDataBaseCon extends
{
Connection connection = null;
// init() method
// service() method
public void destroy()
{
// Close the connection and allow it to be garbage collected
connection.close();
connection = null;
}
}
A server calls the destroy method after all service calls have been completed, or a server specific number of seconds have
passed without there being any request from the client. If the servlet handles any long-running operations, the service
methods might still be running when the server calls the destroy method. Hence, it must be ensured that those threads
complete their function. The destroy method described in Program expects all client interactions to be completed when it is
called, because the servlet has no long-running operations.
The term network programming refers to writing programs that execute across multiple devices (computers), in which the
devices are all connected to each other using a network.
The java.net package of the J2SE APIs contains a collection of classes and interfaces that provide the low-level
communication details, allowing you to write programs that focus on solving the problem at hand.
The java.net package provides support for the two common network protocols −
TCP − TCP stands for Transmission Control Protocol, which allows for reliable communication between two
applications. TCP is typically used over the Internet Protocol, which is referred to as TCP/IP.
UDP − UDP stands for User Datagram Protocol, a connection-less protocol that allows for packets of data to be
transmitted between applications.
This chapter gives a good understanding on the following two subjects −
Socket Programming − This is the most widely used concept in Networking and it has been explained in very
detail.
URL Processing − This would be covered separately. Click here to learn about URL Processing in Java language.
Socket Programming
Sockets provide the communication mechanism between two computers using TCP. A client program creates a socket on
its end of the communication and attempts to connect that socket to a server.
When the connection is made, the server creates a socket object on its end of the communication. The client and the server
can now communicate by writing to and reading from the socket.
The java.net.Socket class represents a socket, and the java.net.ServerSocket class provides a mechanism for the server
program to listen for clients and establish connections with them.
The following steps occur when establishing a TCP connection between two computers using sockets −
The server instantiates a ServerSocket object, denoting which port number communication is to occur on.
The server invokes the accept() method of the ServerSocket class. This method waits until a client connects to the
server on the given port.
After the server is waiting, a client instantiates a Socket object, specifying the server name and the port number to
connect to.
The constructor of the Socket class attempts to connect the client to the specified server and the port number. If
communication is established, the client now has a Socket object capable of communicating with the server.
On the server side, the accept() method returns a reference to a new socket on the server that is connected to the
client's socket.
After the connections are established, communication can occur using I/O streams. Each socket has both an OutputStream
and an InputStream. The client's OutputStream is connected to the server's InputStream, and the client's InputStream is
connected to the server's OutputStream.
TCP is a two-way communication protocol, hence data can be sent across both streams at the same time. Following are the
useful classes providing complete set of methods to implement sockets.
If the ServerSocket constructor does not throw an exception, it means that your application has successfully bound to the
specified port and is ready for client requests.
Following are some of the common methods of the ServerSocket class −
1
public int getLocalPort()
Returns the port that the server socket is listening on. This method is useful if you passed in
0 as the port number in a constructor and let the server find a port for you.
When the ServerSocket invokes accept(), the method does not return until a client connects. After a client does connect, the
ServerSocket creates a new Socket on an unspecified port and returns a reference to this new Socket. A TCP connection
now exists between the client and the server, and communication can begin.
public Socket(String host, int port, InetAddress localAddress, int localPort) throws
3 IOException.
Connects to the specified host and port, creating a socket on the local host at the specified
address and port.
When the Socket constructor returns, it does not simply instantiate a Socket object but it actually attempts to connect to the
specified server and port.
Some methods of interest in the Socket class are listed here. Notice that both the client and the server have a Socket object,
so these methods can be invoked by both the client and the server.
4 String getHostAddress()
Returns the IP address string in textual presentation.
5 String getHostName()
Gets the host name for this IP address.
7 String toString()
Converts this IP address to a String.
Understanding ports
port
On computer and telecommunication devices, a port (noun) is generally a specific place for being physically connected to
some other device, usually with a socket and plug of some kind. Typically, a personal computer is provided with one or
more serial ports and usually one parallel port. The serial port supports sequential, one bit-at-a-time transmission to
peripheral devices such as scanners and the parallel port supports multiple-bit-at-a-time transmission to devices such as
printers.
2) In programming, a port (noun) is a "logical connection place" and specifically, using the Internet's protocol, TCP/IP, the
way a client program specifies a particular server program on a computer in a network. Higher-level applications that use
TCP/IP such as the Web protocol, Hypertext Transfer Protocol, have ports with preassigned numbers. These are known as
"well-known ports" that have been assigned by the Internet Assigned Numbers Authority (IANA). Other application
processes are given port numbers dynamically for each connection. When a service (server program) initially is started, it is
said to bind to its designated port number. As any client program wants to use that server, it also must request to bind to the
Port numbers are from 0 to 65535. Ports 0 to 1024 are reserved for use by certain privileged services. For the HTTP service,
port 80 is defined as a default and it does not have to be specified in the Uniform Resource Locator (URL).
3) In programming, to port (verb) is to move an application program from an operating system environment in which it was
developed to another operating system environment so it can be run there. Porting implies some work, but not nearly as
much as redeveloping the program in the new environment. Open standard programming interface (such as those specified in
The RMI (Remote Method Invocation) is an API that provides a mechanism to create distributed application in java. The
RMI allows an object to invoke methods on an object running in another JVM.
The RMI provides remote communication between the applications using two objects stub and skeleton.
RMI uses stub and skeleton object for communication with the remote object.
A remote object is an object whose method can be invoked from another JVM. Let's understand the stub and skeleton
objects:
stub
The stub is an object, acts as a gateway for the client side. All the outgoing requests are routed through it. It resides at the
client side and represents the remote object. When the caller invokes method on the stub object, it does the following tasks:
skeleton
The skeleton is an object, acts as a gateway for the server side object. All the incoming requests are routed through it. When
the skeleton receives the incoming request, it does the following tasks:
. Application Layer
This layer is nothing but the actual systems (client and server) involved in communication. A client Java program
communicates with the other Java program on the server side. RMI is nothing but a communication between two JVMs
placed on different systems.
Proxy Layer
The proxy layer consists of proxies (named as stub and skeleton by designers) for client and server. Stub is client side
proxy and Skeleton is server side proxy. Stub and skeleton, as many people confuse, are not separate systems but they are
after all programs placed on client and server. The stub and skeleton are not hard coded by the Programmer but they are
generated by RMI compiler (this is shown in execution part later). Stub is placed on client side and skeleton is placed on
server side. The client server communication goes through these proxies. Client sends its request of method invocation (to be
executed on remote server) to stub. Stub inturn sends the request to skeleton. Skeleton passes the request to the server
program. Server executes the method and sends the return value to the skeleton (to route to client). Skeleton sends to stub
and stub to client program.
Marshaling and Unmarshaling
One more job of proxies is marshaling and unmarshaling. Marshaling is nothing but converting data into a special format
suitable to pass through the distributed environment without loosing object persistence. For this reason, the RMI
mechanism implicitly serialize the objects involved in communication. The stub marshals the data of client and then sends to
the skeleton. As the format is not understood by the server program, it is unmarshaled by the skeleton into the original
format and passed to server. Similarly from server to client also.
A marshal stream includes a stream of objects that are used to transport parameters, exceptions, and errors needed for these
streams for communicating with each other. Marshaling and unmarshaling are done by the RMI runtime mechanism
implicitly without any programmers extra coding.
Transport layer does not exist separately but is a part of Remote reference layer. Transport layer is responsible for actually
setting up connections and handling the transport of data from one machine to another. It can be modified to handle
encrypted streams, compression algorithms and a number of other security/performance related enhancements.
The marshaled stream is passed to RRL(Remote Reference Layer). Task of RRL is to identify the host, that is, remote
machine. The marshaled stream is passed to Transport layer which performs routing.
This section discusses the task of implementing a class for the compute engine. In general, a class that implements a remote
interface should at least do the following:
An RMI server program needs to create the initial remote objects and export them to the RMI runtime, which makes them
available to receive incoming remote invocations. This setup procedure can be either encapsulated in a method of the remote
object implementation class itself or included in another class entirely. The setup procedure should do the following:
The complete implementation of the compute engine follows. The engine.ComputeEngine class implements the remote
interface Compute and also includes the main method for setting up the compute engine. Here is the source code for
the ComputeEngine class:
package engine;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import compute.Compute;
import compute.Task;
public ComputeEngine() {
super();
}
The following sections discuss each component of the compute engine implementation.
This declaration states that the class implements the Compute remote interface and therefore can be used for a remote object.
The ComputeEngine class defines a remote object implementation class that implements a single remote interface and no
other interfaces. The ComputeEngine class also contains two executable program elements that can only be invoked locally.
The first of these elements is a constructor for ComputeEngine instances. The second of these elements is a main method
that is used to create a ComputeEngine instance and make it available to clients.
The ComputeEngine class has a single constructor that takes no arguments. The code for the constructor is as follows:
public ComputeEngine() {
super();
}
This constructor just invokes the superclass constructor, which is the no-argument constructor of the Object class. Although
the superclass constructor gets invoked even if omitted from the ComputeEngine constructor, it is included for clarity.
The class for a remote object provides implementations for each remote method specified in the remote interfaces.
The Compute interface contains a single remote method, executeTask, which is implemented as follows:
This method implements the protocol between the ComputeEngine remote object and its clients. Each client provides
the ComputeEngine with a Task object that has a particular implementation of the Task interface's execute method.
The ComputeEngine executes each client's task and returns the result of the task's execute method directly to the client.
Arguments to or return values from remote methods can be of almost any type, including local objects, remote objects, and
primitive data types. More precisely, any entity of any type can be passed to or from a remote method as long as the entity is
an instance of a type that is a primitive data type, a remote object, or a serializable object, which means that it implements
the interface java.io.Serializable.
Some object types do not meet any of these criteria and thus cannot be passed to or returned from a remote method. Most of
these objects, such as threads or file descriptors, encapsulate information that makes sense only within a single address
space. Many of the core classes, including the classes in the packages java.lang and java.util, implement
the Serializable interface.
The rules governing how arguments and return values are passed are as follows:
Remote objects are essentially passed by reference. A remote object reference is a stub, which is a client-side
proxy that implements the complete set of remote interfaces that the remote object implements.
Local objects are passed by copy, using object serialization. By default, all fields are copied except fields that are
marked static or transient. Default serialization behavior can be overridden on a class-by-class basis.
Passing a remote object by reference means that any changes made to the state of the object by remote method invocations
are reflected in the original remote object. When a remote object is passed, only those interfaces that are remote interfaces
are available to the receiver. Any methods defined in the implementation class or defined in non-remote interfaces
implemented by the class are not available to that receiver.
For example, if you were to pass a reference to an instance of the ComputeEngine class, the receiver would have access only
to the compute engine's executeTask method. That receiver would not see the ComputeEngine constructor, its main method,
or its implementation of any methods of java.lang.Object.
In the parameters and return values of remote method invocations, objects that are not remote objects are passed by value.
Thus, a copy of the object is created in the receiving Java virtual machine. Any changes to the object's state by the receiver
are reflected only in the receiver's copy, not in the sender's original instance. Any changes to the object's state by the sender
are reflected only in the sender's original instance, not in the receiver's copy.
The main method's first task is to create and install a security manager, which protects access to system resources from
untrusted downloaded code running within the Java virtual machine. A security manager determines whether downloaded
code has access to the local file system or can perform any other privileged operations.
If an RMI program does not install a security manager, RMI will not download classes (other than from the local class path)
for objects received as arguments or return values of remote method invocations. This restriction ensures that the operations
performed by downloaded code are subject to a security policy.
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
Next, the main method creates an instance of ComputeEngine and exports it to the RMI runtime with the following
statements:
The static UnicastRemoteObject.exportObject method exports the supplied remote object so that it can receive invocations
of its remote methods from remote clients. The second argument, an int, specifies which TCP port to use to listen for
incoming remote invocation requests for the object. It is common to use the value zero, which specifies the use of an
anonymous port. The actual port will then be chosen at runtime by RMI or the underlying operating system. However, a non-
zero value can also be used to specify a specific port to use for listening. Once the exportObject invocation has returned
successfully, the ComputeEngine remote object is ready to process incoming remote invocations.
The exportObject method returns a stub for the exported remote object. Note that the type of the variable stub must
be Compute, not ComputeEngine, because the stub for a remote object only implements the remote interfaces that the
exported remote object implements.
The exportObject method declares that it can throw a RemoteException, which is a checked exception type.
The main method handles this exception with its try/catch block. If the exception were not handled in this
way, RemoteException would have to be declared in the throws clause of the main method. An attempt to export a remote
object can throw a RemoteException if the necessary communication resources are not available, such as if the requested
port is bound for some other purpose.
Before a client can invoke a method on a remote object, it must first obtain a reference to the remote object. Obtaining a
reference can be done in the same way that any other object reference is obtained in a program, such as by getting the
reference as part of the return value of a method or as part of a data structure that contains such a reference.
The system provides a particular type of remote object, the RMI registry, for finding references to other remote objects. The
RMI registry is a simple remote object naming service that enables clients to obtain a reference to a remote object by name.
The registry is typically only used to locate the first remote object that an RMI client needs to use. That first remote object
might then provide support for finding other objects.
The java.rmi.registry.Registry remote interface is the API for binding (or registering) and looking up remote objects in the
registry. The java.rmi.registry.LocateRegistry class provides static methods for synthesizing a remote reference to a registry
at a particular network address (host and port). These methods create the remote reference object containing the specified
network address without performing any remote communication. LocateRegistry also provides static methods for creating a
new registry in the current Java virtual machine, although this example does not use those methods. Once a remote object is
registered with an RMI registry on the local host, clients on any host can look up the remote object by name, obtain its
reference, and then invoke remote methods on the object. The registry can be shared by all servers running on a host, or an
individual server process can create and use its own registry.
The ComputeEngine class creates a name for the object with the following statement:
The code then adds the name to the RMI registry running on the server. This step is done later with the following statements:
This rebind invocation makes a remote call to the RMI registry on the local host. Like any remote call, this call can result in
a RemoteException being thrown, which is handled by the catch block at the end of the main method.
The no-argument overload of LocateRegistry.getRegistry synthesizes a reference to a registry on the local host and
on the default registry port, 1099. You must use an overload that has an int parameter if the registry is created on a
port other than 1099.
When a remote invocation on the registry is made, a stub for the remote object is passed instead of a copy of the
remote object itself. Remote implementation objects, such as instances of ComputeEngine, never leave the Java
virtual machine in which they were created. Thus, when a client performs a lookup in a server's remote object
registry, a copy of the stub is returned. Remote objects in such cases are thus effectively passed by (remote)
reference rather than by value.
For security reasons, an application can only bind, unbind, or rebind remote object references with a registry
running on the same host. This restriction prevents a remote client from removing or overwriting any of the entries
in a server's registry. A lookup, however, can be requested from any host, local or remote.