Runtime
Distinguish Java source, the JVM and a servlet container.
CodeBhavyaConnect requests, application layers and server-rendered or JSON responses.
Java web applications connect Java code to HTTP requests through a supported server runtime. This lesson maps the ecosystem before the next lesson develops servlet processing in more detail. You will explain the jobs of a servlet, service, repository, JSP view and JDBC connection without treating them as interchangeable components.
Our example is a public course catalog. A controller validates filters, a service asks a repository for records, and a view returns HTML or JSON. The browser lab simulates those boundaries locally; it does not run Java, compile JSP or connect to a database.
Distinguish Java source, the JVM and a servlet container.
Assign request, business, data and view responsibilities.
Explain JSP output and the role of an escaped model.
Recognize JDBC, drivers and parameterized queries.
Java source is compiled into bytecode that a Java runtime executes. In a servlet-based web application, a container accepts a request and invokes the mapped component. The browser receives the produced response rather than executing the servlet’s Java source.
Java and JavaScript are distinct languages. A Java backend can return HTML that loads ordinary browser JavaScript. It can also return JSON to a static frontend; using Java on the server does not force every page to be server-rendered.
A working Java command is not the same as a complete web environment. Compiling source requires a compiler and relevant dependencies. Running a servlet requires a compatible container or an application framework that supplies that runtime.
HTML, CSS and browser JavaScript.
Request and response contract.
Executes compiled application code.
Maps requests and manages web components.
Uploading a .java file to a static frontend does not compile or execute it. This lesson publishes teaching HTML and JavaScript; it does not change the frontend hosting into a Java server.
A Servlet handles requests through a container-managed Java component. JSP, now specified as Jakarta Pages, provides a server-side page technology for constructing a view. JDBC is the Java database-access API used with an appropriate driver and data source.
A service and repository are application design roles rather than mandatory classes supplied by one specification. Keeping them separate helps a controller stay focused on request handling while business and data-access logic can be tested independently.
A framework can organize these responsibilities differently, but the boundaries remain useful: incoming data is not already a business model, and a template is not the right place to decide whether a caller may change a protected record.
| Component | Main responsibility | Catalog example |
|---|---|---|
| Servlet/controller | Request and response decisions | Validate category, availability, limit and view |
| Service | Application rules and coordination | Filter accepted records before applying the limit |
| Repository/DAO | Data-access boundary | Load course records |
| JSP/view | Presentation | Render the accepted catalog as HTML |
| JDBC | Database operations through Java APIs | Bind values and read a result set |
The lab’s repository is a fixed local fixture. It has no SQL connection. The data panel and trace show the conceptual boundary so you can explain where a real JDBC implementation would fit.
Older Java EE servlet examples commonly import javax.servlet classes. Modern Jakarta Servlet examples use jakarta.servlet. The namespace choice must match the application’s dependencies and the target container; changing a package name in one source file does not automatically migrate an entire application.
For example, Tomcat 9 uses the older servlet namespace, while Tomcat 10 and later use Jakarta APIs. Tomcat 10.1 implements Servlet 6.0 and Pages 3.1; these are specific compatibility targets, not instructions to always select one server version.
Do not mechanically rename every javax package. JDBC types such as javax.sql.DataSource remain Java platform APIs. The servlet namespace migration does not turn that type into jakarta.sql.DataSource.
// Modern Jakarta Servlet imports:
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
// JDBC data-source API remains:
import javax.sql.DataSource;Check the container’s supported specification level, required Java version and your project’s API dependencies together. The lesson’s servlet and JSP fragments use Jakarta-style names; legacy javax.servlet projects need their own matched setup.
A servlet container maps request paths, provides request/response objects and manages servlet lifecycle calls. A servlet’s init phase prepares it, service handles requests, and destroy is part of lifecycle cleanup. The next lesson explores those callbacks and HTTP handlers in detail.
The container can serve static resources alongside mapped components. It can also translate and compile JSP pages for server-side execution. JSP source is not a special browser language that becomes dynamic merely by being downloaded.
A servlet instance may serve concurrent requests. Do not put the current learner, selected filter or per-request output into a mutable instance field and assume each request has its own servlet object. Keep request-specific work in appropriate local variables or request attributes.
Prepare component-level dependencies deliberately.
Process each request with its own input and outcome.
Protect shared state and avoid mixing callers’ data.
Release owned resources according to their lifecycle.
A connection pool or shared service object needs a suitable lifecycle too. A component being managed by a container does not make every object you store inside it automatically thread-safe.
A servlet mapping associates an application-relative URL pattern with a component. A deployed application can also have a context path. A browser request to /learning/catalog may reach a /catalog mapping inside the /learning application.
The servlet mapping is not simply a Java filename. The lab models GET /catalog as its only public route, with 404 for an unknown path and 405 plus Allow: GET for an unsupported method. Its routing is intentionally narrower than a complete container.
Real HttpServlet behavior includes method handling beyond this toy route, including framework/container treatment of HEAD and OPTIONS. Do not copy the simulator’s limited router as if it were a full servlet implementation.
import java.io.IOException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
res.setContentType("text/plain; charset=UTF-8");
res.getWriter().println("Java handles this request on the server.");
}
}This small class requires a matching Servlet API dependency and container. It is an illustrative component, not a standalone main program or a deployed endpoint in this website.
Request parameters are incoming values associated with a query or supported form submission. Request attributes are objects that application components can attach while handling the request. The two serve different purposes.
The catalog controller accepts four scalar strings: category, available, limit and view. Category is all, web or backend. Available is exactly true or false. Limit is exactly 1, 2 or 3. View is jsp or json. Only after acceptance does the controller convert the boolean and limit.
A repeated query parameter can produce multiple values. The lab includes an array-valued category variant to represent that shape; it rejects the request rather than silently choosing one. A real servlet should deliberately inspect getParameterValues when uniqueness matters.
// Illustrative controller fragment:
String[] values = request.getParameterValues("category");
if (values == null || values.length != 1) {
response.sendError(400, "One category value is required");
return;
}
// Validate the value, call the service, then attach an accepted model.
request.setAttribute("catalog", acceptedCourses);The fragment assumes request, response and an acceptedCourses model supplied by the surrounding handler. Request attributes survive an internal forward of that request; they are not durable browser storage or an automatic login identity.
A controller decides whether input is acceptable and selects the representation. A service coordinates application behavior. A repository or DAO isolates the data-access implementation. This separation lets a service use a fake repository in tests and a database-backed implementation in a deployment.
The lab validates before calling its repository. The repository returns at most ten bounded records. The service validates that record model, filters by category and availability, then applies the accepted limit in fixture order. Filtering after the limit could accidentally hide a matching course.
No request changes course records. The visible repository call count is just a local teaching counter. Empty results are accepted data, while an unavailable repository and an unacceptable returned record are different failures.
Validate input and choose a representation.
Coordinate filtering and accepted model rules.
Return data or a deliberate failure.
Render only the accepted model.
A larger application may enforce filtering efficiently in its repository or database. The exercise keeps three fixtures in memory so the order of decisions remains visible; it is not a performance design for an unbounded catalog.
A JSP page is processed on the server. In a controller/view flow, the controller attaches a model and forwards to a view that focuses on presentation. Keep authorization, SQL operations and business mutations out of the page template.
Expression Language such as ${course.title} reads model properties. For conventional JavaBean-style objects, a title property is exposed through a getter such as getTitle. Do not assume that displaying an expression automatically provides the output encoding your context needs.
The following modern Jakarta Tags fragment uses c:out for HTML text and c:forEach for a catalog. The appropriate tag-library implementation must be available in the application; a servlet container alone is not a guarantee that every JSP tag library is installed.
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<h2>Course catalog</h2>
<ul>
<c:forEach var="course" items="${catalog}">
<li>
<c:out value="${course.title}" />
— <c:out value="${course.available}" /> places
</li>
</c:forEach>
</ul>This template is a teaching fragment for an accepted catalog model. The browser lab generates a simplified JSP-style HTML result using JavaScript, and it never compiles or evaluates this JSP source.
An internal forward passes the same request to another server resource before the response is committed. A controller can attach request attributes and forward to a JSP under WEB-INF. That view can use the model without asking the browser to issue a second request.
A redirect returns a response instructing the client to request another URL. That later request does not automatically carry the first request’s attributes. Decide how needed state is preserved instead of assuming a forward and redirect are interchangeable.
Keeping a JSP under WEB-INF helps make the controller the intended entry point because those resources are not directly served as ordinary client requests. That arrangement does not replace authorization checks at protected handlers.
// Illustrative accepted-model branch:
request.setAttribute("catalog", acceptedCourses);
request.getRequestDispatcher("/WEB-INF/views/catalog.jsp")
.forward(request, response);
// Do this before committing response body output.The lab’s JSP branch records a simulated internal forward; it does not navigate the browser or call RequestDispatcher. Its JSON branch instead serializes the accepted model directly. Both are deliberate response choices.
JDBC supplies Java APIs for connecting to a database, executing statements and reading results. A suitable driver and configured connection or DataSource are required. A JDBC API import alone does not create a database or make a connection succeed.
Use bound values in prepared statements instead of concatenating untrusted input into SQL. Parameter binding keeps a value separate from the statement’s structure; dynamic table names or arbitrary SQL fragments need different deliberate controls.
Connections, statements and result sets have lifecycles. Try-with-resources helps close owned JDBC resources. Closing a pooled connection normally returns it to its pool; pool setup and credentials belong in protected backend configuration.
// Illustrative repository fragment; dataSource is already configured.
String sql = "SELECT id, title, available FROM courses "
+ "WHERE category = ? ORDER BY id";
try (java.sql.Connection con = dataSource.getConnection();
java.sql.PreparedStatement ps = con.prepareStatement(sql)) {
ps.setString(1, acceptedCategory);
try (java.sql.ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
// Map checked columns into CourseView objects.
}
}
}The lab does not execute this query or load a JDBC driver. Its repository fixtures let you test the service boundary without pretending that database availability, transactions or resource cleanup have been verified.
Choose the lifetime of an object deliberately. Request scope suits one accepted catalog model. Session scope can hold application state associated with a user’s session. Application scope can hold shared configuration or resources, with suitable safety and lifecycle rules.
A session object does not prove permission merely because it exists. Establish a trustworthy identity and apply authorization before returning protected data or changing records. The public catalog demonstration has no login or session system.
Do not copy one request’s selected filter into a global field and let a later request accidentally reuse it. Shared collections and session attributes can be accessed concurrently and need an appropriate strategy.
One request’s validated filters and view model.
State deliberately associated with a recognized session.
Shared dependencies with appropriate lifecycle and safety.
A scope name does not make mutable objects safe automatically.
The browser simulation is synchronous and local. Its tests can check that one run does not reuse an earlier model; they do not prove real servlet concurrency or distributed session behavior.
An empty catalog can be a successful 200 response with no matching records. Invalid query data returns 400 in this exercise. An unknown path and unsupported method have their own route outcomes. These decisions should not be collapsed into a generic database error.
The unavailable-repository fixture returns a simulated 503 without disclosing connection details. The malformed-record fixture returns 500 because the repository output fails the service’s accepted model contract. Neither outcome produces an accepted catalog view.
A JSP-style response uses text/html; a JSON response uses application/json. The caller should know which representation to parse. The Level 18 loader already illustrated why a received response, successful status and acceptable data are separate stages.
Render HTML or serialize JSON.
Return a completed zero-result outcome.
Reject before repository access.
Return a stable error without partial rendering.
A deployed server can log private diagnostics while sending a stable public message. The lab trace is visible teaching output and is not a recommendation to expose SQL details, credentials or production stack traces.
A project needs a matched Java toolchain, web API dependencies and runtime. A WAR is one packaging option for deploying a web application to a container; some frameworks package an embedded server differently. Packaging conventions are not interchangeable with static file uploads.
A conventional layout can keep Java source under a source tree, static web assets under a web-resource tree and JSP views under WEB-INF. The exact build configuration depends on the chosen tools. Mark container-provided APIs appropriately so incompatible copies are not bundled accidentally.
Test the mapping, context path, response encoding, JSP/tag-library availability and data-source configuration in the deployed environment. A successful compile does not establish that the runtime, driver or database has been configured correctly.
Illustrative project roles:
src/main/java/.../CatalogServlet.java controller
src/main/java/.../CatalogService.java service
src/main/java/.../CourseRepository.java data boundary
src/main/webapp/WEB-INF/views/catalog.jsp view
Build configuration matched APIs/runtimeThis lesson supplies explanatory fragments rather than a complete WAR project. No Java web server or database is deployed by the lesson patch. The next lesson builds understanding of Java Servlets before later JSP and database work.
A service can be tested with a fake repository to check valid records, empty data and failure behavior. A controller test can verify bad parameters are rejected before service access. A view test can check literal text and representation output. Real integration tests still need the container and data source.
For the catalog, test that category and availability filtering happen before limiting. Check invalid numeric spellings, duplicate-shaped parameters, missing fields and unknown view values. A repeated request should not inherit an earlier accepted model or stale HTML after a failure.
Keep the Java build and deployment checks separate from the browser lab’s automated checks. The simulation explains responsibilities and verifies its own JavaScript logic, but it does not establish Servlet, JSP, JDBC or JVM behavior.
Use controlled inputs and repository fixtures.
Verify actual servlet mappings and JSP behavior.
Exercise driver, connection and real query outcomes.
Inspect status, representation, keyboard use and layout.
The visualizer follows one accepted catalog request. The lab lets you change the query, repository outcome and response representation to locate the first failed boundary. Level 23 will continue with Java Servlets.
Follow a fixed catalog request through mapping, controller validation, service coordination, repository access and view selection. The player uses the same approved five-stage presentation. It explains the architecture without executing Java, JSP or JDBC.
A compatible container selects the application and servlet mapping.
GET /catalog?category=backend&available=true&limit=3&view=jspThe browser lab models one public route; a real container manages the actual request and component lifecycle.
This is a JavaScript model of application layers, not a servlet container or JVM. It sends no requests, executes no SQL and stores no course changes. The repository call count is a local teaching counter that Reset clears.
The three normal records are HTML & CSS (web, 12 places), Java Servlets (backend, 8) and JSP <Views> (backend, 0). The service filters by category and availability before applying a limit. Its model validates record shape, unique IDs, bounded titles and non-negative integer availability.
Choose a JSP-style HTML response or JSON. Inspect the decoded query, trace, accepted model and response source. Empty repository data is a successful empty result; offline data returns simulated 503, and malformed data returns 500. Bad query parameters fail before repository access.
Idle. JavaScript model; Java, JSP and JDBC are not running here.
Mock repository calls: 0
No request processed.No trace yet.No accepted model.No response yet.No response body yet.No preview yet.
Match namespaces, API dependencies and runtime specification levels.
Check mapping, scalar query values and normalization before data access.
Distinguish unavailable data access from a malformed returned model.
Check model names, getters, tag libraries and output encoding.
If a modern servlet import is unresolved, check the API dependency and target container rather than replacing every javax import blindly. If a view receives no catalog, check which request attribute the controller sets and whether the request was forwarded or redirected.
If a filter produces no matching course unexpectedly, check that limiting happens after filtering. If the view still shows an older catalog after a failure, clear the earlier model and response rather than presenting stale data as a new success.
A mock repository test does not verify a driver, connection pool or real query. A JavaScript view preview does not verify JSP compilation. Keep those integration checks explicit when building the real application.
No. Java web components need compilation, dependencies and a compatible runtime or container.
The servlet/controller handles request decisions and can attach a model; the JSP focuses on server-side presentation.
It remains a Java platform JDBC API. The Servlet namespace migration does not rename every javax package.
Parameters are incoming values. Attributes carry application objects within the request processing flow.
A forward dispatches the same request internally before commitment. A redirect asks the client to make another request, which does not automatically carry the original attributes.
Limiting first can discard records that would match the requested filters, producing the wrong result.
No. Use the appropriate output encoding for the destination; the example uses c:out for HTML text.
No. Real driver, data-source, query, resource and deployment behavior need separate integration tests.
GET /catalog, all/false/3, JSP, normal repository. Expected: 200 and all three records.
Backend/true/1. Expected: only Java Servlets with 8 places, despite the first fixture being a web course.
Switch the accepted request to JSON. Expected: application/json and the same selected records; earlier HTML preview cleared.
Choose empty repository. Expected: 200, zero accepted courses and a clear empty outcome.
Try limit "03", "3.0", "0", missing limit, array category or extra field. Expected: 400 and no repository call.
Try /missing and POST /catalog. Expected: 404 and 405 with Allow: GET; no repository access.
Try offline and invalid-record fixtures. Expected: 503 and 500 respectively; no accepted model or stale cards.
Use backend/false/3 with JSP. Expected: JSP <Views> shown literally, encoded body source and no injected view element.
A runtime that manages servlet components and request dispatch.
A container-managed Java web component that handles requests.
A server-side page technology used to construct views.
Java APIs for database access with appropriate drivers and resources.
The request-facing layer that validates input and chooses an outcome.
The layer that coordinates application rules and operations.
A boundary that isolates data-access implementation.
An application object attached to a request processing flow.
Dispatch of the same request to another server resource before response commitment.
A web-application archive format for deployment to a compatible runtime.
Design a catalog controller with unique scalar category, availability, limit and representation parameters. Validate before service access. Have a service accept a bounded repository model, filter before limiting and return a clear zero-result outcome.
Specify a JSP view using an accepted request model and appropriate HTML text encoding, plus a JSON response branch. Explain forwarding versus redirecting, model scope and which pieces require a compatible Jakarta or legacy Java EE runtime.
Define separate tests for controller rejections, repository failure, malformed rows, service filtering and literal titles. A real project must then verify servlet mapping, JSP/tag libraries, JDBC driver/data source and actual HTTP output. Do not infer those integration results from this local browser demonstration.
Success criterion: map each application responsibility to the right layer and trace both accepted and rejected catalog requests. Level 23 will develop Java Servlets in more detail.
Before marking complete, explain the Servlet/JSP/JDBC roles, compare a forward with a redirect and reproduce query, repository and representation outcomes in the lab. Identify which real Java runtime checks remain separate. Completion is a local study marker.