A JSP page runs inside a Servlet container; the browser never executes JSP source. The container translates the page into a Servlet, compiles it, runs it for a request, and sends only the generated response body to the client.
Use a supported JDK and a Jakarta Servlet container such as Tomcat. JSP applications need a web root for public resources and a WEB-INF directory for protected configuration, classes, and libraries. Files below WEB-INF cannot be requested directly, which makes it the correct location for views that must be reached through a controller.
Match the API namespace to the container generation. Current Jakarta containers use jakarta.servlet packages; older Java EE containers use javax.servlet. Mixing those APIs produces deployment or class-loading failures even when the Java code compiles in the editor.
A minimal JSP can contain ordinary HTML plus Expression Language. Deploy the application to the container and request it through the application context, for example http://localhost:8080/shop/hello.jsp. Opening the file from disk bypasses the container and cannot execute JSP.
On the first request, the container may translate and compile the page, so it can be slower than later requests. A translation or compilation error appears in container logs with the generated Servlet location and the original JSP line where possible.
Production JSP is normally a view, not the request controller. A Servlet validates input, calls application services, stores view data as request attributes, and forwards to a JSP. The JSP renders those values with EL and tags. This separation keeps SQL, authorization, redirects, and business rules out of the template.
Forward when the same request should render a view and retain request attributes. Redirect when the browser must make a new request, commonly after a successful POST. A redirect loses request attributes unless data is stored elsewhere, and it changes the browser URL.
A 404 means the context path or resource mapping was not found; it is different from a JSP compilation failure, which normally returns a 500. Confirm that the application deployed, inspect the expanded artifact or WAR, check filename case, and verify whether the page is intentionally under WEB-INF.
After edits, make sure the container detects the changed file. For repeatable builds, package the application through the project build rather than copying random class files into the running server. Keep container, JDK, and Jakarta API versions recorded with the project.
<%@ page contentType="text/html;charset=UTF-8" %>
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>Hello JSP</title></head>
<body>
<h1>Hello, ${empty requestScope.name ? 'visitor' : requestScope.name}</h1>
</body>
</html>
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("name", "Asha");
request.getRequestDispatcher("/WEB-INF/views/hello.jsp")
.forward(request, response);
}
}
JSP is translated into a Servlet and executed on the server. A normal browser cannot perform that translation or run the generated Java code.
The Servlet specification protects WEB-INF from direct HTTP access. Forward to that view from a mapped controller.
Prefer EL, JSTL, and controller-prepared data. Scriptlets mix Java control logic into markup and are difficult to test and maintain.
Explore 500+ free tutorials across 20+ languages and frameworks.