Understanding JSP Servlets

Understanding JSP ServletsServlets is the main technology for developing servlets.

Understanding the Servlet API is your gateway to becoming a formidable Java Web Developer.

It is imperative that you be familiar with the core interfaces and classes in the Servlet API.

DammnnBlockedUnblockFollowFollowingApr 19At the centre of Servlet technology is Servlet, an interface that all servlet classes must implement either directly or indirectly.

You implement it directly when you write a servlet class that implements Servlet.

You implement it indirectly when you extend a class that implements this interface.

The Servlet interface defines a contract between a servlet and the servlet container.

The contract boils down to the promise by the servlet container to load the servlet class into memory and call specific methods on the servlet instance.

There can only be one instance for each servlet type in an application.

A user request causes the servlet container to call a servlet’s service method, passing an instance of ServletRequest and an instance of ServletResponse.

The ServletRequest encapsulates the current HTTP request so that servlet developers do not have to parse and manipulate raw HTTP data.

The ServletResponse represents the HTTP response for the current user and makes it easy to send a response back to the user.

For each application, the servlet container also creates an instance of ServletContext.

The object encapsulates the environment details of the context.

There is only one ServletContext for each context.

For each servlet instance, there is also a ServletConfig that encapsulates the servlet configuration.

ServletThe Servlet interface defines these five methods:void init(ServletConfig config) throws ServletExceptionvoid service(ServletRequest request, ServletResponse response) throws ServletException, java.

io.

IOExceptionvoid destroy()java.

lang.

String getServletInfo()ServletConfig getServletConfig()Note that the convention for writing a Java method signature is to use the fully qualified name for types that are not in the same package as the type containing the method.

As such, in the signature of the service method javax.

servlet.

ServletException, which is in the same package as Servlet, is written without the package information whereas java.

io.

Exception is written fully.

init, service, and destroy are lifecycle methods.

The servlet container invokes these three methods according to these rules:init.

The servlet container invokes this method the first time the servlet is requested.

This method is not called at subsequent requests.

You use this method to write initialization code.

When invoking this method, the servlet container passes a ServletConfig.

Normally, you will assign the ServletConfig to a class level variable so that this object can be used from other points in the servlet class.

service.

The servlet container invokes this method each time the servlet is requested.

You write the code that the servlet is supposed to do here.

The first time the servlet is requested, the servlet container calls the init method and the service method.

For subsequent requests, the only service is invoked.

destroy: The servlet container invokes this method when the servlet is about to be destroyed.

This occurs when the application is unloaded or when the servlet container is being shut down.

Normally, you write clean-up code in this method.

The other two methods in Servlet are non-life cycle methods: getServletInfo and getServletConfig.

getServletInfo: This method returns the description of the servlet.

You can return any string that might be useful or even null.

getServletConfig: This method returns the ServletConfig passed by the servlet container to the init method.

However, in order for getServletConfig to return a non-null value, you must have assigned the ServletConfig passed to the init method to a class level variable.

An important point to note is thread safety.

A servlet instance is shared by all users in an application, so class-level variables are not recommended unless they are read-only or members of the java.

util.

concurrent.

atomic package.

The next section, “Writing A Basic Servlet Application,” shows how you can write a Servlet Implementation.

Writing A Basic Servlet ApplicationWriting a servlet application is surprisingly easy.

All you have to do is create a directory structure and place your servlet classes in a certain directory.

In this section, you’ll learn how to write a simple servlet application named app01a.

Initially, it will contain one servlet, MyServlet, which sends a greeting to the user.

You need a servlet container to run your servlets.

Tomcat, an open source servlet container, is available free of charge and runs on any platform where Java is available.

Writing and Compiling the Servlet ClassAfter making sure you have a servlet container on your local machine, the next step is to write and compile a servlet class.

The servlet class for this example, MyServlet, is given down here.

By convention, the name of a servlet class is suffixed withpackage app01a;import java.

io.

IOException;import java.

io.

PrintWriter;import javax.

servlet.

Servlet;import javax.

servlet.

ServletConfig;import javax.

servlet.

ServletException;import javax.

servlet.

ServletRequest;import javax.

servlet.

ServletResponse;import javax.

servlet.

annotation.

WebServlet;@WebServlet(name = "MyServlet", urlPatterns = { "/my" })public class MyServlet implements Servlet { private transient ServletConfig servletConfig; @Override public void init(ServletConfig servletConfig) throws ServletException { this.

servletConfig = servletConfig; } @Override public ServletConfig getServletConfig() { return servletConfig; } @Override public String getServletInfo() { return "My Servlet"; } @Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { String servletName = servletConfig.

getServletName(); response.

setContentType("text/html"); PrintWriter writer = response.

getWriter(); writer.

print("<html><head></head>" + "<body>Hello from " + servletName + "</body></html>"); } @Override public void destroy() { } }The first thing you may notice when reading the code is this annotation:-@WebServlet(name = "MyServlet", urlPatterns = { "/my" })The WebServlet annotation type is used to declare a servlet.

You can name the servlet as well as tell the container what URL invokes the servlet.

The name attribute is optional and, if present, ordinarily given the name of the servlet class.

What’s important is the urlPatterns attribute, which is also optional but almost always present.

In MyServlet, urlPattern tells the container that the /my pattern should invoke the servlet.

Note that a URL pattern must begin with a forward slash.

The servlet’s init method is called once and sets the private transient servletConfig variable to the ServletConfig object passed to the method.

The app01a directory at the top of the structure is the application directory.

Under the application directory is a WEB-INF directory.

It, in turn, has two subdirectories:classes.

Your servlet classes and other Java classes must reside here.

The directories under classes reflect the class package.

In Figure 1.

2 there is one class deployed, app01a.

MyServlet.

lib.

Deploy jar files required by your servlet application here.

The Servlet API jar file does not need to be deployed here because the servlet container already has a copy of it.

In this application, the lib directory is empty.

An empty lib directory may be deleted.

A servlet/JSP application normally has JSP pages, HTML files, image files, and other resources.

These should go under the application directory and are often organized in subdirectories.

For instance, all image files can go to an image directory, all JSP pages to JSP, and so on.

Any resource you put under the application directory is directly accessible to the user by typing the URL to the resource.

If you want to include a resource that can be accessed by a servlet but not accessible to the user, put it under WEB-INF.

Now, deploy the application to Tomcat.

With Tomcat, one way to deploy an application is by copying the application directory to the webapps directory under Tomcat installation.

You can also deploy an application by editing the server.

xml file in Tomcat’s conf directory or deploying an XML file separately in order to avoid editing server.

xml.

Other servlet containers may have different deployment rules.

The recommended method for deploying a servlet/JSP application is to deploy it as a war file.

A war file is a jar file with war extension.

You can create a war file using the jar program that comes with the JDK or tools like WinZip.

You can then copy the war file to Tomcat’s webapps directory.

When you start or restart Tomcat, Tomcat will extract the war file automatically.

Deployment as a war file will work in all servlet containers.

Invoking the ServletTo test your first servlet, start or restart Tomcat and direct your browser to the following URL (assuming Tomcat is configured to listen on port 8080, its default port):http://localhost:8080/app01a/myThe output would be:Hello from MyServlet Congratulation you have written your first servlet application.

ServletRequestFor every HTTP request, the servlet container creates an instance of ServletRequest and passes it to the servlet’s service method.

The ServletRequest encapsulates information about the request.

These are some of the methods in the ServletRequest interface.

public int getContentLength()Returns the number of bytes in the request body.

If the length is not known, this method returns -1.

public java.

lang.

String getContentType()Returns the MIME type of the request body or null if the type is not known.

public java.

lang.

String getParameter(java.

lang.

String name)Returns the value of the specified request parameter.

public java.

lang.

String getProtocol()Returns the name and version of the protocol of this HTTP request.

getParameter is the most frequently used method in ServletRequest.

A common use of this method is to return the value of an HTML form field.

You’ll learn how you can retrieve form values in the section “Working with Forms” later in this article.

getParameter can also be used to get the value of a query string.

For example, if a servlet is invoked using this URI.

http://domain/context/servletName?id=123you can retrieve the value of id from inside your servlet using this statement:String id = request.

getParameter("id");Note that getParameter returns null if the parameter does not exist.

In addition to getParameter, you can also use getParameterNames, getParameterMap, and getParameterValues to retrieve form field names and values as well as query strings.

See the section “HttpServlet” for examples of how to use these methods.

ServletResponseThe javax.

servlet.

ServletResponse interface represents a servlet response.

Prior to invoking a servlet’s service method, the servlet container creates a ServletResponse and pass it as the second argument to the service method.

The ServletResponse hides the complexity of sending a response to the browser.

One of the methods defined in ServletResponse is the getWriter method, which returns a java.

io.

PrintWriter that can send a text to the client.

By default, the PrintWriter object uses ISO-8859–1 encoding.

When sending a response to the client, most of the time you send it as HTML.

You are therefore assumed to be familiar with HTML.

NoteThere is also another method that you can use to send output to the browser: getOutputStream.

However, this method is for sending binary data, so in most cases, you will use getWriter and not getOutputStream.

Before sending any HTML tag, you should set the content type of the response by calling the setContentType method, passing “text/html” as an argument.

This is how you tell the browser that the content type is HTML.

Most browsers by default render a response as HTML in the absence of a content type.

However, some browsers will display HTML tags as plain text if you don’t set the response content type.

ServletConfigThe servlet container passes a ServletConfig to the servlet’s init method when the servlet container initializes the servlet.

The ServletConfig encapsulates configuration information that you can pass to a servlet through @WebServlet or the deployment descriptor.

Every piece of information so passed is called an initial parameter.

An initial parameter has two components: key and value.

To retrieve the value of an initial parameter from inside a servlet, call the getInitParameter method on the ServletConfig passed by the servlet container to the servlet’s init method.

The signature of getInitParameter is as follows.

java.

lang.

String getInitParameter(java.

lang.

String name)In addition, the getInitParameterNames method returns an Enumeration of all initial parameter names:java.

util.

Enumeration<java.

lang.

String> getInitParameterNames()For example, to retrieve the value of a contactName parameter, use this.

String contactName = servletConfig.

getInitParameter("contactName");On top of getInitParameter and getInitParameterNames, ServletConfig offers another useful method, getServletContext.

Use this method to retrieve the ServletContext from inside a servlet.

See the section “ServletContext” later in this article for a discussion on this object.

As an example of ServletConfig, let’s add a servlet named ServletConfigDemoServlet to app01a.

package app01a;import java.

io.

IOException;import java.

io.

PrintWriter;import javax.

servlet.

Servlet;import javax.

servlet.

ServletConfig;import javax.

servlet.

ServletException;import javax.

servlet.

ServletRequest;import javax.

servlet.

ServletResponse;import javax.

servlet.

annotation.

WebInitParam;import javax.

servlet.

annotation.

WebServlet;@WebServlet(name = "ServletConfigDemoServlet", urlPatterns = { "/servletConfigDemo" }, initParams = { @WebInitParam(name="admin", value="Saurav tripathi"), @WebInitParam(name="email", value="dondon@example.

com") })public class ServletConfigDemoServlet implements Servlet { private transient ServletConfig servletConfig; @Override public ServletConfig getServletConfig() { return servletConfig; } @Override public void init(ServletConfig servletConfig) throws ServletException { this.

servletConfig = servletConfig; } @Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { ServletConfig servletConfig = getServletConfig(); String admin = servletConfig.

getInitParameter("admin"); String email = servletConfig.

getInitParameter("email"); response.

setContentType("text/html"); PrintWriter writer = response.

getWriter(); writer.

print("<html><head></head><body>" + "Admin:" + admin + "<br/>Email:" + email + "</body></html>"); } @Override public String getServletInfo() { return "ServletConfig demo"; } @Override public void destroy() { } }As you can see, you pass two initial parameters (admin and email) to the servlet in the initParams attribute in @WebServlet:@WebServlet(name = "ServletConfigDemoServlet", urlPatterns = { "/servletConfigDemo" }, initParams = { @WebInitParam(name="admin", value="Saurav Tripathi"), @WebInitParam(name="email", value="dondon@example.

com") })You can invoke ServletConfigDemoServlet using this URL:http://localhost:8080/app01a/servletConfigDemoThe output from this program will be:Admin: Saurav Tripathi Email: dondon@example.

comAlternatively, you can pass initial parameters in the deployment descriptor.

Utilizing the deployment descriptor for this purpose is easier than using @WebServlet since the deployment descriptor is a text file and you can edit it without recompiling the servlet class.

ServletContextThe ServletContext represents the servlet application.

There is only one context per web application.

In a distributed environment where an application is deployed simultaneously to multiple containers, there is one ServletContext object per Java Virtual Machine.

You can obtain the ServletContext by calling the getServletContext method on the ServletConfig.

The ServletContext is there so that you can share information that can be accessed from all resources in the application and to enable dynamic registration of web objects.

The former is done by storing objects in an internal Map within the ServletContext.

Objects stored in ServletContext are called attributes.

The following methods in ServletContext deal with attributes:java.

lang.

Object getAttribute(java.

lang.

String name)java.

util.

Enumeration<java.

lang.

String> getAttributeNames()void setAttribute(java.

lang.

String name, java.

lang.

Object object)void removeAttribute(java.

lang.

String name)GenericServletThe preceding examples showed how to write servlets by implementing the Servlet interface.

However, did you notice that you had to provide implementations for all the methods in Servlet, even though some of them did not contain code?.In addition, you needed to preserve the ServletConfig object into a class level variable.

Fortunately, the GenericServlet abstract class comes to the rescue.

In keeping with the spirit of easier code writing in object-oriented programming, GenericServletimplements both Servlet and ServletConfig and perform the following tasks:Assign the ServletConfig in the init method to a class level variable so that it can be retrieved by calling getServletConfig.

Provide default implementations of all methods in the Servlet interface.

Provide methods that wrap the methods in the ServletConfig.

GenericServlet preserves the ServletConfig object by assigning it to a class level variable servletConfig in the init method.

Here is the implementation of init in GenericServlet.

public void init(ServletConfig servletConfig) throws ServletException { this.

servletConfig = servletConfig; this.

init();}However, if you override this method in your class, the init method in your servlet will be called instead and you have to call super.

init(servletConfig) to preserve the ServletConfig.

To save you from having to do so, GenericServlet provides a second init method, which does not take arguments.

This method is called by the first init method after ServletConfig is assigned to servletConfig:public void init(ServletConfig servletConfig) throws ServletException { this.

servletConfig = servletConfig; this.

init();}This means you can write initialization code by overriding the no-argument init method and the ServletConfig will still be preserved by the GenericServlet instance.

The GenericServletDemoServlet class in the next code is a rewrite of ServletConfigDemoServlet in the next code snippet.

Note that the new servlet extends GenericServletinstead of implementing Servlet.

package app01a;import java.

io.

IOException;import java.

io.

PrintWriter;import javax.

servlet.

GenericServlet;import javax.

servlet.

ServletConfig;import javax.

servlet.

ServletException;import javax.

servlet.

ServletRequest;import javax.

servlet.

ServletResponse;import javax.

servlet.

annotation.

WebInitParam;import javax.

servlet.

annotation.

WebServlet;@WebServlet(name = "GenericServletDemoServlet", urlPatterns = { "/generic" }, initParams = { @WebInitParam(name="admin", value="Saurav Tripathi"), @WebInitParam(name="email", value="dondon@example.

com") })public class GenericServletDemoServlet extends GenericServlet { private static final long serialVersionUID = 62500890L; @Override public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { ServletConfig servletConfig = getServletConfig(); String admin = servletConfig.

getInitParameter("admin"); String email = servletConfig.

getInitParameter("email"); response.

setContentType("text/html"); PrintWriter writer = response.

getWriter(); writer.

print("<html><head></head><body>" + "Admin:" + admin + "<br/>Email:" + email + "</body></html>"); }}As you can see, by extending GenericServlet you do not need to override methods that you don’t plan to change.

As a result, you have a cleaner code.

In this code the only method overridden is the service method.

Also, there is no need to preserve the ServletConfig yourself.

Invoke the servlet using this URL and the result should be similar to that of ServletConfigDemoServlet.

http://localhost:8080/app01a/genericEven though GenericServlet is a nice enhancement to Servlet, it is not something you use frequently, however, as it is not as advanced as HttpServlet.

HttpServletis the real deal and used in real-world applications.

Http ServletMost, if not all, servlet applications you write will work with HTTP.

This means you can make use of the features offered by HTTP.

The javax.

servlet.

http package is the second package in the Servlet API that contains classes and interfaces for writing servlet applications.

Many of the types in javax.

servlet.

http override those in javax.

servlet.

HttpServletThe HttpServlet class overrides the javax.

servlet.

GenericServlet class.

When using HttpServlet, you will also work with the HttpServletRequest and HttpServletResponse objects that represent the servlet request and the servlet response, respectively.

The HttpServletRequest interface extends javax.

servlet.

ServletRequest and HttpServletResponse extends javax.

servlet.

ServletResponse.

HttpServlet overrides the service method in GenericServlet and adds another service method with the following signature:protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.

io.

IOExceptionThe difference between the new service method and the one in javax.

servlet.

Servlet is that the former accepts an HttpServletRequest and an HttpServletResponse, instead of a ServletRequest and a ServletResponse.

The servlet container, as usual, calls the original service method in javax.

servlet.

Servlet, which in HttpServlet is written as follows:public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { HttpServletRequest request; HttpServletResponse response; try { request = (HttpServletRequest) req; response = (HttpServletResponse) res; } catch (ClassCastException e) { throw new ServletException("non-HTTP request or response"); } service(request, response);}The original service method downcasts the request and response objects from the servlet container to HttpServletRequest and HttpServletResponse, respectively, and call the new service method.

The downcasting is always successful because the servlet container always passes an HttpServletRequest and an HttpServletResponse when calling a servlet’s service method, to anticipate the use of HTTP.

Even if you are implementing javax.

servlet.

Servlet or extending javax.

servlet.

GenericServlet, you can downcast the servlet request and servlet response passed to the service method to HttpServletRequest and HttpServletResponse, respectively.

The new service method in HttpServlet then examines the HTTP method used to send the request (by calling request.

getMethod) and call one of the following methods: doGet, doPost, doHead, doPut, doTrace, doOptions, and doDelete.

Each of the seven methods represents an HTTP method.

doGet and doPost are the most often used.

As such, you rarely need to override the service methods anymore.

Instead, you override doGet or doPost or both doGet and doPost.

To summarize, there are two features in HttpServlet that you do not find in GenericServlet:Instead of the service method, you will override doGet, doPost, or both of them.

In rare cases, you will also override any of these methods: doHead, doPut, doTrace, doOptions, doDelete.

You will work with HttpServletRequest and HttpServletResponse, instead of ServletRequest and ServletResponse.

HttpServletRequestHttpServletRequest represents the servlet request in the HTTP environment.

It extends the javax.

servlet.

ServletRequest interface and adds several methods.

Some of the methods added are as follows.

java.

lang.

String getContextPath()Returns the portion of the request URI that indicates the context of the request.

Cookie[] getCookies()Returns an array of Cookie objects.

java.

lang.

String getHeader(java.

lang.

String name)Returns the value of the specified HTTP header.

java.

lang.

String getMethod()Returns the name of the HTTP method with which this request was made.

java.

lang.

String getQueryString()Returns the query string in the request URL.

HttpSession getSession()Returns the session object associated with this request.

If none is found, creates a new session object.

HttpSession getSession(boolean create)Returns the current session object associated with this request.

If none is found and the create argument is true, create a new session object.

HttpServletResponseHttpServletResponse represents the servlet response in the HTTP environment.

Here are some of the methods defined in it.

void addCookie(Cookie cookie)Adds a cookie to this response object.

void addHeader(java.

lang.

String name, java.

lang.

String value)Adds a header to this response object.

void sendRedirect(java.

lang.

String location)Sends a response code that redirects the browser to the specified location.

.

. More details

Leave a Reply