Chapter 04 Introduction – Different Ways of Creating a Servlet


Servlet Series: Full Stack Java Development
In our journey through the Servlet Series—part of the larger Full Stack Java Development roadmap—this chapter focuses on an important milestone: understanding the different ways of creating a servlet and why one approach might be preferred over another.
If you’ve been following along, you already know that Servlets act as the backbone of Java-based web applications, bridging the gap between client requests and server-side processing. But in the real world, there isn’t just a single way to build them. Depending on the type of protocol we are dealing with, the complexity of request handling, and the need for maintainability, developers may choose different base classes or interfaces to create a servlet.
This chapter takes you step-by-step from the Servlet interface, through GenericServlet, and finally to the specialized HttpServlet, exploring not just the "how" but the "why" behind each choice. Along the way, we’ll break down real request scenarios—like GET and POST—examine their request object handling, and see exactly how lifecycle methods work under the hood.
By the end of this chapter, you will not only know how to implement a servlet in multiple ways but also have the practical insight to choose the right approach in a production environment. We will be using clear examples, dissecting method calls, and even exploring request parameter handling with both single and multiple values, so that no conceptual gap remains.
Overview of Chapter 04 – Different Ways of Creating a Servlet
This chapter is structured to give you a progressive and detailed understanding, following the exact sequence you’ve written in the raw theory. The sections will flow as follows:
Foundation: Servlet Interface and GenericServlet
Introduction to the Servlet interface and its abstract methods.
Transition to GenericServlet and the reduction of required methods.
Why GenericServlet simplifies development but is not enough for HTTP-specific tasks.
Why HttpServlet Exists
Limitations of a single
service()
method in GenericServlet.The need for request-method-specific handling.
Introduction to the HttpServlet class and its method structure.
Understanding GET and POST Requests
Common ways GET requests are triggered.
How POST requests are sent in web applications.
Step-by-step breakdown of form submissions, URL patterns, and query strings.
Implementing GET and POST in HttpServlet
Code examples for handling GET requests.
Code examples for handling POST requests.
Using
getParameter()
to extract request data.
Life Cycle of an HttpServlet
From request submission to container handling.
Internal method invocation hierarchy.
How the container decides which method to execute.
Case Studies on Method Execution
Scenarios with different method combinations in the servlet class.
How GET/POST requests behave when certain methods are missing.
Combining Logic for Multiple Request Types
The
doProcess()
approach for shared logic.Dynamically identifying the request method.
Advanced Request Object Handling
Retrieving single and multiple parameters.
Practical example with a full student registration form.
Generating dynamic HTML output from servlet responses.
Alright, Rohit — here’s the Section 1 expansion using your raw theory and the diagram you provided.
I’ve kept it in a professional, paragraph-based, storytelling format, exactly in your flow, and included the diagram with a technical caption.
Section 1 – From Servlet Interface to HttpServlet
When we first approach servlet development in Java, the journey starts with the most fundamental building block: the Servlet interface. This interface defines the contract that any servlet must fulfill, containing five abstract methods. At this level, we are working with the most generic form of a servlet, one that is not tied to any particular communication protocol. Implementing this interface directly gives us full control, but also comes with the burden of providing definitions for all the methods, whether we need them or not. This can make servlet creation unnecessarily verbose for most use cases.
To make the process easier and reduce boilerplate code, Java introduced the GenericServlet abstract class. This class implements the Servlet
interface and its methods, except for a single abstract method:
public abstract void service(ServletRequest request, ServletResponse response);
By implementing all other methods and leaving only service()
as abstract, GenericServlet drastically simplifies servlet development. Now, instead of implementing all five methods from the Servlet
interface, a developer only needs to focus on the one central service()
method. This is particularly useful when building protocol-independent web applications because it allows handling of requests in a uniform way.
However, there is a catch. While GenericServlet
is great for generic request processing, modern web applications rarely deal with just any protocol. In real-world development, HTTP is the dominant communication protocol. This means requests often need to be processed differently depending on whether they are GET or POST requests. With only one generic service()
method, distinguishing between request types and debugging becomes more difficult. This is where HttpServlet comes into play.
The HttpServlet
abstract class extends GenericServlet
and introduces a structure tailored specifically for handling HTTP requests. It provides dedicated methods such as:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
By separating doGet()
and doPost()
, HttpServlet
allows developers to implement logic that is specific to each HTTP request type. This makes the codebase cleaner, improves readability, and makes debugging much easier. Even though HttpServlet
contains no abstract methods, it is still marked as abstract
because it serves as a base class intended for extension, not direct instantiation.
The Hierarchy in Action
The relationship between these classes and interfaces can be visualized in the diagram below:
Figure 1 – Class and Interface Hierarchy of HttpServlet
At the top level, we have the Servlet
interface, which defines the basic lifecycle methods every servlet must support. GenericServlet
implements Servlet
, as well as ServletConfig
(which provides configuration information to a servlet) and Serializable
(which allows servlet objects to be serialized if needed). This makes GenericServlet
both protocol-agnostic and easily configurable.
HttpServlet
then extends GenericServlet
, inheriting all of its capabilities while adding HTTP-specific methods. This layered design allows Java to support multiple protocols through GenericServlet while providing specialized handling for HTTP through HttpServlet.
Section 2 – Why HttpServlet Exists
When we start working with GenericServlet
, it feels like we already have a solid foundation for processing web requests. After all, it simplifies the Servlet
interface by leaving us with only one method to implement:
public abstract void service(ServletRequest request, ServletResponse response);
This single entry point for request processing might seem convenient at first, especially for applications that are protocol-independent. But here’s the problem: in the real world, almost every Java web application is designed to work over HTTP protocol, and HTTP is not a one-size-fits-all kind of protocol. It supports multiple request methods like GET, POST, PUT, DELETE, and more—each serving a distinct purpose.
When we handle all requests inside one service()
method, we are essentially lumping together logic for all request types. This quickly becomes messy. Imagine a situation where both GET and POST requests are hitting the same servlet. Without a clear separation, you’d need conditional checks inside the service()
method to figure out which request type arrived:
String methodType = request.getMethod();
if (methodType.equals("GET")) {
// handle GET
} else if (methodType.equals("POST")) {
// handle POST
}
While technically possible, this approach is far from elegant. It spreads HTTP-specific logic inside a generic method and makes debugging harder. For example, if a POST request isn’t behaving as expected, you would need to dig through a service()
method that also handles GET, PUT, and DELETE requests, making it harder to isolate and fix the issue. The generic nature of GenericServlet
becomes a disadvantage when you need precision.
The Need for Request-Method-Specific Handling
HTTP request methods are designed with different semantics.
GET requests are generally used to retrieve data and are idempotent, meaning repeated calls should produce the same result.
POST requests are meant to submit data to the server, often resulting in a change in state or database updates.
Because of these differences, mixing their handling logic in one method is not only bad for maintainability but can also lead to subtle bugs. For example, if a GET request accidentally triggers logic meant for POST, you could end up unintentionally modifying data when the user only meant to retrieve it.
This is why we need request-method-specific handling—a clean, structured approach where GET-related logic lives in one place, POST-related logic in another, and so on. This not only improves code clarity but also aligns perfectly with HTTP’s intended design.
Enter HttpServlet
To address these challenges, Java provides the HttpServlet
abstract class. This class specializes in handling HTTP protocol requests and introduces separate methods for each HTTP request type. The most commonly overridden are:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
With these methods, we no longer need to clutter a single service()
method with multiple conditions. Instead, the Servlet container automatically determines the request method type and calls the corresponding method in our servlet class. This means if a GET request comes in, doGet()
is called; if a POST request comes in, doPost()
is called—without us having to explicitly check the method type.
HttpServlet
also provides an HTTP-specific version of the service()
method:
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
This version takes HttpServletRequest
and HttpServletResponse
objects instead of the generic ServletRequest
and ServletResponse
. It acts as a dispatcher, determining the HTTP request method and forwarding the call to the appropriate doXXX()
method.
Even though HttpServlet
doesn’t declare any abstract methods, it is still marked abstract
because it is intended to be extended rather than instantiated directly. Developers implement the specific request-handling methods they need, leaving the rest to the default implementation provided by HttpServlet
.
Section 3 – Understanding GET and POST Requests
Now that we know why HttpServlet
exists and how it separates request-handling logic, it’s time to focus on the two most common HTTP request types you’ll deal with in servlet development: GET and POST. Even though both are used to send information from a client (like a browser) to a server, their behavior and intended purposes are fundamentally different.
How a GET Request is Sent in a Web Application
In a web environment, GET requests can be triggered in multiple ways. Some of the most common scenarios include:
Typing a URL directly into the browser’s address bar and hitting Enter.
Clicking a hyperlink (
<a href="...">
) within a webpage.Submitting a form with
method="GET"
.Submitting a form without specifying the
method
attribute, since GET is the default.
When a GET request is made, the browser appends the form data to the URL in the form of a query string. This query string is key-value data, like:
http://localhost:8080/test?username=Rohit
Here, username
is the key, and Rohit
is the value. Because this information becomes part of the URL, it is visible in the browser’s address bar and also gets stored in the browser history.
How a POST Request is Sent in a Web Application
POST requests are usually generated by submitting a form where method="POST"
is explicitly specified. Unlike GET, POST sends data in the request body instead of appending it to the URL. This means the information is not visible in the address bar, making it more suitable for sensitive data like login credentials.
Example form for POST:
<form method="POST" action="./test">
Enter Name: <input type="text" name="username">
<br>
<input type="submit" value="login">
</form>
When the user enters a value (say "Sachin"
) and clicks the login button, the browser prepares an HTTP request with the data in the body. The request is then sent to the server, which hands it over to the Catalina servlet container in Tomcat. The container uses the action
attribute of the form to determine which servlet should handle the request. Here, ./test
points to the servlet mapped with the /test
URL pattern.
How the Container Routes the Request
When the Catalina container receives a request:
It identifies the servlet to handle the request using the URL pattern (either from
web.xml
or annotations like@WebServlet
).If the servlet is not yet loaded, it goes through the loading → instantiation → initialization sequence.
The container then determines the HTTP request method type.
If the request is a GET, it calls
doGet()
; if it is a POST, it callsdoPost()
.
For example, here’s a simple servlet handling both GET and POST:
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.*;
@WebServlet(urlPatterns="/test")
public class TestServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Request method is of type: GET");
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Request method is of type: POST");
}
}
Behavioral Differences in Practice
If you type a URL directly in the browser or click a link, you’re generating a GET request.
If you submit a form with POST, the request type is POST.
GET parameters are visible in the URL as a query string, while POST parameters are hidden inside the request body.
When data needs to be fetched without modifying server state, GET is preferred. When data needs to be sent or stored (like a registration form), POST is the safer and more semantically correct option.
Section 4: Implementing GET and POST in HttpServlet
When working with Java Servlets, one of the most important tasks is handling client requests based on the HTTP method used. In the HTTP protocol, the two most common request methods are GET and POST. Both serve distinct purposes and are handled differently inside an HttpServlet
.
The GenericServlet
class, as seen in the servlet hierarchy diagram, provides only a single service()
method for handling requests, without distinguishing between request types. This design works for generic protocols but is not sufficient for HTTP-specific requirements. For instance, in web applications, GET and POST requests have entirely different use cases — GET is often used for retrieving data, while POST is used for submitting data to the server.
To address this, the HttpServlet
class, which extends GenericServlet
, introduces a method-specific handling mechanism by defining dedicated methods such as doGet()
for GET requests and doPost()
for POST requests. The CATALINA container determines the request type and automatically calls the corresponding method in the servlet.
4.1 Handling GET Requests in HttpServlet
A GET request is typically used to retrieve resources from the server. When a form is submitted with method="GET"
or when a user directly enters a URL in the browser, the form data is appended to the request URL as a query string.
For example, if a form field has the name username
and the value Rohit
, the browser sends the following request:
http://localhost:9999/MyApp/test?username=Rohit
Here, username=Rohit
is the query string.
Example: Handling GET requests in HttpServlet
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Request method is of type: GET");
// Extracting request parameter from query string
String username = request.getParameter("username");
System.out.println("Username is: " + username);
}
}
Explanation:
The container detects the request method as GET.
It calls the
doGet()
method inHttpServlet
.The form data is passed to the servlet via the
HttpServletRequest
object.The
getParameter("username")
method retrieves the value of the input field named"username"
.
4.2 Handling POST Requests in HttpServlet
A POST request is used to send data to the server in the request body, not as part of the URL. This is often preferred for sensitive information (such as passwords) or when sending large amounts of data.
When a form is submitted with method="POST"
, the browser sends the request without appending parameters to the URL. For example, if the username entered is Virat
, the URL might still look like:
http://localhost:9999/MyApp/test
but the username=Virat
data will be present in the HTTP body.
Example: Handling POST requests in HttpServlet
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Request method is of type: POST");
// Extracting request parameter from request body
String username = request.getParameter("username");
System.out.println("Username is: " + username);
}
Explanation:
The container detects the request method as POST.
It calls the
doPost()
method inHttpServlet
.The form data is included in the request body instead of the URL.
The same
getParameter()
method works here — the container takes care of parsing both GET query strings and POST request bodies.
4.3 Using getParameter()
to Extract Request Data
The getParameter()
method is defined in the ServletRequest
interface and is available in HttpServletRequest
. It is used to retrieve the value of a form field sent by the client.
Syntax:
String value = request.getParameter("fieldName");
fieldName
→ This must match thename
attribute of the HTML form input element.If multiple parameters have the same name (e.g., checkboxes), use
getParameterValues()
to retrieve them as a String array.
Example with HTML form:
<form method="GET" action="./test">
Enter Name: <input type="text" name="username" />
<input type="submit" value="Submit" />
</form>
If the user types "Rohit"
in the text field, then:
request.getParameter("username"); // returns "Rohit"
4.4 Flow from Browser to Servlet
When a user interacts with a web page that sends data to a servlet, there is a clear sequence of steps from browser → server → container → servlet. The uploaded diagram illustrates this process. Let’s break it down step-by-step.
1. User Action (Browser Side)
- Suppose we have an HTML form for login:
<form method="POST" action="./test">
Enter Name: <input type="text" name="username">
<br>
<input type="submit" value="login">
</form>
Key attributes in the
<form>
tag:method: Specifies the HTTP method (
GET
orPOST
).action: Defines the relative URL (
./test
) that maps to a servlet in the project.
The
name
attribute of<input>
(username
here) becomes the key for sending data.If the user types Rohit and clicks Login, the browser will prepare the request:
For GET: Data is sent as a query string in the URL, e.g.,
?username=Rohit
.For POST: Data is sent inside the request body (no query string in the URL).
2. HTTP Request Sent to Tomcat Server
The browser sends the HTTP request (method, URL, headers, and body if POST) to the Tomcat server.
Tomcat receives the request and passes it to the Catalina container for processing.
3. Catalina Container Processing
Inside Catalina:
Read the Request Line
- Extracts method (
GET
orPOST
) and the target path (/test
).
- Extracts method (
Match URL Pattern
Catalina checks
web.xml
or the@WebServlet
annotation to find which servlet corresponds to/test
.Example mapping in
web.xml
:<servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>com.example.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>/test</url-pattern> </servlet-mapping>
Determine Which Method to Call
If the request method is GET, Catalina calls the servlet’s
doGet()
method.If the request method is POST, Catalina calls the servlet’s
doPost()
method.
4. Servlet Execution
When Catalina calls your servlet, it creates:
An
HttpServletRequest
object (contains request data like form parameters, headers, and method).An
HttpServletResponse
object (used to send data back to the client).
Inside
doPost()
ordoGet()
:You use
request.getParameter("username")
to retrieve the submitted value.For example:
@WebServlet("/test") public class TestServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { String name = request.getParameter("username"); response.getWriter().println("Hello " + name); } }
If the user entered Rohit,
request.getParameter("username")
returns"Rohit"
.
5. Response Sent Back to Browser
The servlet processes the request (e.g., validates the username, fetches from a database, etc.).
Using
HttpServletResponse
, it sends the response HTML or JSON back to the client.The browser then renders the response for the user.
Key Points
The
action
attribute in<form>
is critical—it tells the browser which URL pattern to target.URL patterns map to specific servlet classes, either through
web.xml
or annotations.HttpServletRequest
is the bridge between the HTML form and servlet code—it holds form data as key-value pairs.Method-specific handling (
doGet()
vs.doPost()
) improves code organization and separation of logic.
6. Demonstration Output
If you send:
GET Request:
Visitinghttp://localhost:8080/MyApp/test?username=Rohit
Output:Request method is of type: GET Username is: Rohit
POST Request:
Submitting the HTML form withusername=Virat
Output:Request method is of type :: POST Username is: Virat
7. Key Points for Interviews
GET requests are idempotent and used for data retrieval. Parameters are sent in the URL.
POST requests are used for data submission, parameters sent in the request body.
The
action
attribute in the HTML form specifies the URL where the request should be sent.The
name
attribute in form fields defines the key for the parameter map inHttpServletRequest
.getParameter()
retrieves parameter values regardless of whether the request is GET or POST.
Section 5 – Life Cycle of an HttpServlet
Understanding the life cycle of an HttpServlet
is one of the most important concepts for mastering Java web application development. Whether you are preparing for interviews or working on real-world projects, this knowledge forms the backbone of troubleshooting and optimization. In this section, we will walk through the complete journey of a request—from the moment it leaves the browser to the point where the servlet sends a response back—while also exploring the internal method invocation hierarchy and the decision-making process used by the servlet container.
1. From Request Submission to Container Handling
When a client (usually a web browser) sends a request to a server, the life cycle of an HttpServlet
begins. Let’s imagine a simple scenario: a user fills in a form on a web page and clicks the “Submit” button. The browser now constructs an HTTP request and sends it to the web server.
The web server’s first task is to determine what type of resource the request is asking for. If it’s a static resource (such as an HTML file, CSS, or image), the server will simply locate it and send it back to the client. This is a straightforward copy-and-paste action: the server fetches the file from disk and streams it back.
However, if the request is for dynamic content—such as invoking business logic, querying a database, or generating HTML on the fly—the server cannot handle this directly. Instead, it hands over control to a web container (in the case of Apache Tomcat, this container is known as Catalina).
The container plays a crucial role: it matches the request’s URL pattern with a servlet class. This mapping can be configured either in web.xml
or via @WebServlet
annotations in the servlet code. Once it identifies the correct servlet—for example, /test
mapping to TestServlet
—it checks whether an instance of that servlet already exists.
If the servlet instance does not exist, the container performs the initialization phase:
Loading – The servlet’s
.class
file is loaded into memory. This step triggers any static blocks inside the class.Instantiation – The servlet object is created by calling its constructor.
Initialization – The
init()
method is called once in the servlet’s life cycle, allowing it to set up resources, configurations, or connections.
2. Request Processing Phase
Once the servlet is loaded and initialized, the container moves into the request processing phase. This is where the service()
methods come into play. The container starts by creating request and response objects—these are instances of HttpServletRequest
and HttpServletResponse
(although the base interface types ServletRequest
and ServletResponse
are used initially).
The container then calls:
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException
At this point, the container checks if the servlet class itself has overridden this public service()
method.
If it has: the container executes your servlet’s
service()
method directly, and whatever logic you’ve written inside will handle all request types (GET, POST, etc.).If it hasn’t: the container falls back to
HttpServlet
’s default implementation ofservice(ServletRequest, ServletResponse)
.
3. Internal Method Invocation Hierarchy
When the container calls HttpServlet
’s service(ServletRequest, ServletResponse)
method, something important happens—it downcasts the generic request and response objects into HTTP-specific ones:
HttpServletRequest hreq = (HttpServletRequest) request;
HttpServletResponse hresp = (HttpServletResponse) response;
service(hreq, hresp); // Calls the protected version
Now, the protected service(HttpServletRequest, HttpServletResponse)
method is in control. This is where the HTTP method dispatching logic exists. The method does the following:
Extracts the request method type:
String requestType = request.getMethod();
Determines which method to call:
If
requestType
equals"GET"
, it callsdoGet(request, response)
.If
requestType
equals"POST"
, it callsdoPost(request, response)
.If it’s any other HTTP method and there’s no handler, it returns a 501 Not Implemented status.
This hierarchy ensures that:
public service(ServletRequest, ServletResponse)
is at the top of the chain.protected service(HttpServletRequest, HttpServletResponse)
acts as the dispatcher.doGet()
anddoPost()
methods handle the actual business logic.
4. How the Container Decides Which Method to Execute
The container’s decision-making process is systematic and rule-based:
Check for
public service(ServletRequest, ServletResponse)
in your servlet class
If found, it handles all request types—GET, POST, PUT, DELETE—without method-specific differentiation.If not found, check for
protected service(HttpServletRequest, HttpServletResponse)
in your servlet class
If found, it will be executed for all request types, but now you have access to HTTP-specific methods and headers.If neither service method is overridden, the container uses
HttpServlet
’s defaultprotected service()
method to calldoGet()
,doPost()
, or anotherdoXXX()
method based on the request type.If the relevant
doXXX()
method is not present in your servlet class, the container executes the parentHttpServlet
version of that method, which returns a 405 Method Not Allowed status.
5. Summary of Method Call Flow
The call flow can be visualized like this:
public service(ServletRequest, ServletResponse)
↓
protected service(HttpServletRequest, HttpServletResponse)
↓
doGet() / doPost() / doPut() / doDelete()
This design allows maximum flexibility—you can choose to handle all requests in a single method, intercept them in the HTTP-specific service()
method, or break them down into individual doXXX()
methods for cleaner separation.
In the next section, we will study real-world method execution cases, including what happens when certain methods are missing, and how this affects GET and POST requests. This will bring clarity to why method hierarchy matters in servlet programming.
Section 6 – Case Studies on Method Execution in HttpServlet
Now that we understand the life cycle of an HttpServlet
and the internal method invocation hierarchy, it’s time to explore how these concepts play out in real execution scenarios. In this section, we’ll walk through different cases where the presence or absence of certain methods in your servlet affects how GET and POST requests are handled.
These cases are not just theoretical—they occur frequently in real-world development and are often tested in interviews. By the end of this section, you’ll know exactly how the container behaves in each situation.
Case 1 – Overriding Only public service(ServletRequest, ServletResponse)
In this scenario, your servlet class only overrides the public service()
method from the Servlet
interface:
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("Public service() called for all requests");
}
Here’s what happens:
For every incoming request—whether GET, POST, PUT, or DELETE—the container will execute your
public service()
method.The container will not proceed to
protected service(HttpServletRequest, HttpServletResponse)
or anydoXXX()
methods because you’ve intercepted the flow at the very top.This approach is useful if you want a single entry point for all request types without method-specific handling.
Case 2 – Overriding Both public service()
and protected service()
If your servlet overrides both:
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("Public service() called");
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Protected service() called");
}
The container’s choice is clear:
The
public service()
method takes precedence.The
protected service()
method is never called, even though it exists.Again, no
doGet()
ordoPost()
methods will be reached.
This case demonstrates that the public service method has the highest priority in the execution chain.
Case 3 – Overriding protected service()
and doGet()
Suppose your servlet looks like this:
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Protected service() called");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doGet() called");
}
Here’s the flow:
Regardless of whether the request type is GET or POST, the container will call your protected service() method directly.
The
doGet()
method will never be invoked, even for GET requests.This is because once you override the HTTP-specific
service()
method, you are taking full control of request dispatching.
Case 4 – Sending a GET Request When Only doPost()
Exists
If you send a GET request but your servlet only has:
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doPost() called");
}
The container’s behavior:
It checks for
doGet()
in your servlet.Since it is missing, the container falls back to
HttpServlet
’s defaultdoGet()
implementation.The default
doGet()
sends a 405 Method Not Allowed response, informing the client that GET is unsupported for this URL.
Case 5 – Sending a POST Request When Only doGet()
Exists
Similarly, if you send a POST request but your servlet only has:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doGet() called");
}
The container looks for
doPost()
in your servlet.If it is missing, it calls
HttpServlet
’s defaultdoPost()
method.The result is the same as Case 4—a 405 Method Not Allowed status.
Case 6 – Common Logic for Both GET and POST Requests
Often, you might need the same processing logic for both GET and POST requests. Writing the same code in doGet()
and doPost()
would be repetitive. Instead, you can extract the shared logic into a separate method, often called doProcess()
:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
private void doProcess(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Request method is: " + request.getMethod());
String userName = request.getParameter("username");
System.out.println("Username is: " + userName);
}
With this design:
GET requests call
doGet()
which in turn callsdoProcess()
.POST requests call
doPost()
which also callsdoProcess()
.The request method can still be identified using
request.getMethod()
if needed.
This approach is cleaner and avoids duplication while keeping method separation intact.
Why These Cases Matter
Understanding these cases is crucial because:
They reveal how the servlet container prioritizes methods.
They help you avoid confusion when a method you expect to run is never called.
They are a favorite topic in interviews because they test both theory and practical debugging ability.
Section 7 – Combining Logic for Multiple Request Types & Advanced Request Handling
In modern web applications, a servlet often needs to handle both GET and POST requests for the same resource. While the methods doGet()
and doPost()
allow you to separate handling logic, there are many cases where you need shared business logic regardless of the request type. At the same time, you must know how to extract request data correctly to make the servlet truly dynamic.
This section covers:
Combining request handling logic for GET and POST.
Retrieving request parameters (single and multiple values).
Detecting the request method at runtime.
A complete real-world student registration form example.
1. Combining GET and POST Logic in Servlets
While you could write identical code in both doGet()
and doPost()
, this leads to redundancy. A better approach is to create a common method—often named doProcess()
—that both doGet()
and doPost()
call.
Example:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
private void doProcess(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h3>Request Method: " + request.getMethod() + "</h3>");
String userName = request.getParameter("username");
out.println("<p>Username: " + userName + "</p>");
}
How it works:
Both GET and POST requests reach the same processing method.
You can still differentiate them using
request.getMethod()
if you need method-specific branching insidedoProcess()
.
2. Retrieving Request Parameters
Parameters sent from an HTML form are passed as name–value pairs in the request.
You can retrieve them using:
Single-value parameter:
String value = request.getParameter("fieldName");
Multiple values (e.g., checkboxes):
String[] values = request.getParameterValues("fieldName");
3. Detecting the Request Method at Runtime
You can check the request method in any servlet method:
String method = request.getMethod();
if ("GET".equalsIgnoreCase(method)) {
// GET-specific logic
} else if ("POST".equalsIgnoreCase(method)) {
// POST-specific logic
}
This is especially useful if you choose not to separate methods but still want method-aware processing.
4. Real-World Example – Student Registration Form
Let’s put it all together with a working example.
HTML Form (studentForm.html)
<!DOCTYPE html>
<html>
<head>
<title>Student Registration</title>
</head>
<body>
<h2>Student Registration</h2>
<form action="register" method="post">
Name: <input type="text" name="name"><br><br>
Age: <input type="number" name="age"><br><br>
Gender:
<input type="radio" name="gender" value="Male"> Male
<input type="radio" name="gender" value="Female"> Female<br><br>
Subjects:
<input type="checkbox" name="subjects" value="Math"> Math
<input type="checkbox" name="subjects" value="Science"> Science
<input type="checkbox" name="subjects" value="English"> English<br><br>
<input type="submit" value="Register">
</form>
</body>
</html>
Servlet (StudentRegisterServlet.java)
import java.io.*;
import jakarta.servlet.*;
import jakarta.servlet.http.*;
public class StudentRegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doProcess(request, response);
}
private void doProcess(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String name = request.getParameter("name");
String age = request.getParameter("age");
String gender = request.getParameter("gender");
String[] subjects = request.getParameterValues("subjects");
out.println("<html><body>");
out.println("<h2>Student Registration Details</h2>");
out.println("<p>Name: " + name + "</p>");
out.println("<p>Age: " + age + "</p>");
out.println("<p>Gender: " + gender + "</p>");
out.println("<p>Subjects: ");
if (subjects != null) {
for (String subject : subjects) {
out.print(subject + " ");
}
} else {
out.print("No subjects selected");
}
out.println("</p>");
out.println("<p>Request Method Used: " + request.getMethod() + "</p>");
out.println("</body></html>");
}
}
5. How the Flow Works
User fills in the HTML form and clicks Submit.
The browser sends a POST request to
/register
(as defined inaction
).The container maps
/register
toStudentRegisterServlet
.The servlet calls
doPost()
→ which callsdoProcess()
.Parameters are extracted, and an HTML response is generated dynamically.
6. Key Takeaways
One method for both GET and POST (
doProcess()
) is a clean, maintainable approach.request.getParameter()
retrieves single values;getParameterValues()
retrieves arrays.Always check for
null
in multi-value parameters to avoidNullPointerException
.The request method can be detected programmatically with
getMethod()
, even inside a shared method.
Subscribe to my newsletter
Read articles from Rohit Gawande directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Rohit Gawande
Rohit Gawande
🚀 Tech Enthusiast | Full Stack Developer | System Design Explorer 💻 Passionate About Building Scalable Solutions and Sharing Knowledge Hi, I’m Rohit Gawande! 👋I am a Full Stack Java Developer with a deep interest in System Design, Data Structures & Algorithms, and building modern web applications. My goal is to empower developers with practical knowledge, best practices, and insights from real-world experiences. What I’m Currently Doing 🔹 Writing an in-depth System Design Series to help developers master complex design concepts.🔹 Sharing insights and projects from my journey in Full Stack Java Development, DSA in Java (Alpha Plus Course), and Full Stack Web Development.🔹 Exploring advanced Java concepts and modern web technologies. What You Can Expect Here ✨ Detailed technical blogs with examples, diagrams, and real-world use cases.✨ Practical guides on Java, System Design, and Full Stack Development.✨ Community-driven discussions to learn and grow together. Let’s Connect! 🌐 GitHub – Explore my projects and contributions.💼 LinkedIn – Connect for opportunities and collaborations.🏆 LeetCode – Check out my problem-solving journey. 💡 "Learning is a journey, not a destination. Let’s grow together!" Feel free to customize or add more based on your preferences! 😊