Course topics

By WebNest Studio Engineering Team

Advanced Java Tutorial

MVC Architecture with Servlets and JSP

Early JSP applications often mixed HTML, business logic, and database access all in one file — a style sometimes called "Model 1" — which worked for small pages but became unmanageable as applications grew. The Model-View-Controller (MVC) pattern, applied to servlets and JSP as "Model 2," separates these concerns into three distinct roles, and it remains the conceptual foundation underneath virtually every modern Java web framework, including Spring MVC.

Mapping MVC onto Servlets and JSP

Each part of MVC has a natural home in a servlet-and-JSP application, and keeping them separate is the entire point of the pattern.

  • Model — plain Java objects (often JavaBeans) and business/data-access logic representing the application's data, independent of any web-specific code. A Model class knows nothing about HttpServletRequest or JSP.
  • View — JSP pages responsible only for presentation: rendering data that has already been prepared, using EL and JSTL rather than business logic.
  • Controller — a servlet that receives the HTTP request, invokes the appropriate Model logic, stores the results as request attributes, and forwards to the correct JSP view.

A Typical Request Flow

A request first hits the Controller servlet, which reads input via request.getParameter(), delegates to Model classes to perform the actual work (validating input, querying a database, applying business rules), places the resulting data into request scope with setAttribute(), and finally forwards to a JSP view with RequestDispatcher.forward(). The JSP then reads that data purely through EL expressions like ${product.name} and JSTL tags, without embedding Java business logic of its own.

Why the Separation Matters

Keeping these roles separate produces several concrete benefits: JSP pages stay simple enough for designers to edit without touching Java code; business logic in the Model can be unit-tested without a servlet container, since it has no dependency on HttpServletRequest; and the same Model and Controller logic can serve multiple different views (an HTML JSP, a JSON API response, a mobile-friendly page) without duplicating business rules. Violating the separation — for example, putting a database query directly inside a JSP scriptlet — reintroduces exactly the maintenance problems MVC was designed to prevent.

Example

A minimal MVC flow: Model, Controller servlet, and JSP view

Java
// --- Model: a plain JavaBean, no servlet dependencies ---
public class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
    public String getName() { return name; }
    public double getPrice() { return price; }
}

// --- Controller: a servlet coordinating Model and View ---
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.List;
import java.util.Arrays;

@WebServlet("/products")
public class ProductController extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // In a real app this would call a service/DAO layer instead of hardcoding data
        List<Product> products = Arrays.asList(
            new Product("Wireless Mouse", 799.00),
            new Product("Mechanical Keyboard", 2499.00)
        );
        request.setAttribute("products", products);

        RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/views/productList.jsp");
        dispatcher.forward(request, response);
    }
}
Output
productList.jsp (View, using JSTL/EL only):
<c:forEach var="p" items="${products}">
  <li>${p.name} - Rs. ${p.price}</li>
</c:forEach>

Rendered in browser:
- Wireless Mouse - Rs. 799.0
- Mechanical Keyboard - Rs. 2499.0

Common Mistakes

  • Writing database queries or business rules directly inside a JSP scriptlet instead of delegating to a Model/service class through the Controller.
  • Letting a JSP view read request parameters directly and make decisions, blurring the line between Controller and View responsibilities.
  • Skipping the Controller and mapping URLs directly to JSP files, which pushes all logic back into the View and recreates the old Model 1 problems.
  • Forgetting to use request scope (not session or application) for data that is only relevant to a single forwarded request, causing stale data to leak into later, unrelated requests.

Exercise

Using the lesson's A minimal MVC flow: Model, Controller servlet, and JSP view example, create a small implementation or design sketch that demonstrates MVC splits responsibilities: Model (data/business logic), View (JSP presentation), Controller (servlet coordinating the two).. Add a test case or scenario that would catch Writing database queries or business rules directly inside a JSP scriptlet instead of delegating to a Model/service class through the Controller., and describe the expected result.

Show hints
  • Start with Mapping MVC onto Servlets and JSP and compare your approach with A minimal MVC flow: Model, Controller servlet, and JSP view. Identify the decision or behavior the lesson recommends.
  • Walk through your scenario step by step. Confirm that it follows MVC splits responsibilities: Model (data/business logic), View (JSP presentation), Controller (servlet coordinating the two). and that it would catch the failure described by Writing database queries or business rules directly inside a JSP scriptlet instead of delegating to a Model/service class through the Controller..

Quick quiz

1. Which choice is a mistake to avoid in MVC Architecture with Servlets and JSP?

  • A. Letting a JSP view read request parameters directly and make decisions, blurring the line between Controller and View responsibilities.
  • B. MVC splits responsibilities: Model (data/business logic), View (JSP presentation), Controller (servlet coordinating the two).
  • C. Writing database queries or business rules directly inside a JSP scriptlet instead of delegating to a Model/service class through the Controller.
Show answer

C. Avoid this approach: Writing database queries or business rules directly inside a JSP scriptlet instead of delegating to a Model/service class through the Controller. The lesson recommends: MVC splits responsibilities: Model (data/business logic), View (JSP presentation), Controller (servlet coordinating the two).

Interview questions

A teammate is about to make this mistake: Writing database queries or business rules directly inside a JSP scriptlet instead of delegating to a Model/service class through the Controller. How would you diagnose and correct it using the lesson's guidance?

Show answer

MVC splits responsibilities: Model (data/business logic), View (JSP presentation), Controller (servlet coordinating the two). Apply this in Mapping MVC onto Servlets and JSP; the example A minimal MVC flow: Model, Controller servlet, and JSP view shows one way to do it. Avoid Writing database queries or business rules directly inside a JSP scriptlet instead of delegating to a Model/service class through the Controller. and explain how your implementation or design prevents that failure.

Key Points to Remember

  • MVC splits responsibilities: Model (data/business logic), View (JSP presentation), Controller (servlet coordinating the two).
  • A typical flow: Controller servlet reads the request, calls the Model, sets request attributes, and forwards to a JSP view.
  • Views should use EL/JSTL for presentation only, never embed business logic or direct data access.
  • This separation enables independent testing of business logic, easier maintenance, and reuse of the same Model/Controller for multiple views.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

These examples need a JDK project with their libraries on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering