JSP, EL & JSTL
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Part I of the section covers Jakarta Pages 4.0, Jakarta Expression Language 6.0 and Jakarta Standard Tag Library 3.0 (API 3.0.2, implementation 3.0.1) on Jakarta Servlet 6.1,
running on Apache Tomcat 11.0.26 and Java 21; the versions were verified on 2026-10-08. It builds bookshelf-jsp, the servlet and JSP variant of the
Bookshelf scenario described on the section landing page, and it needs only the servlet foundations of
Servlet Fundamentals. Part II, Apache Struts, uses the same pages as the view layer of its actions.
What Part I covers
JSP is the oldest part of the stack and the part that every Java web framework of its generation still uses as a view. Part I explains how a page becomes a
servlet, every element of its syntax, the Expression Language that replaced scriptlets, the five tag libraries of JSTL, and how to write your own tags.
It then builds applications from those parts: a Model 2 application with a front controller, forms with validation and sessions, Spring MVC with JSP views, Jasper
configuration for development and production, security and testing. The status of each technology is stated on its page: scripting elements and the SQL and XML libraries of
JSTL are legacy, jsp:plugin and isThreadSafe are removed, and the EL and JSTL libraries are the current way to write a view.
Version matrix
Each Jakarta EE release fixes one version of each specification, and the package namespace changed once, between Jakarta EE 8 and 9. The table lists the releases a JSP application can still meet and the container line that implements each of them; the Jakarta EE 12 row is in progress and is not released.
| Jakarta EE | Pages | Expression Language | Tags (JSTL) | Servlet | Tomcat line |
|---|---|---|---|---|---|
9 and 9.1 |
3.0 |
4.0 |
2.0 |
5.0 |
10.0 |
10 |
3.1 |
5.0 |
3.0 |
6.0 |
10.1 |
11 (current) |
4.0 |
6.0 |
3.0 |
6.1 |
11.0 |
12 (in progress) |
4.1 |
6.1 |
3.1 |
6.2 |
none yet (Tomcat 12 is not released) |
Everything from Jakarta EE 9 on uses jakarta.* packages, and Tags 3.0 renames the tag library URIs to jakarta.tags.* (jakarta.tags.core, jakarta.tags.fmt,
jakarta.tags.functions, jakarta.tags.sql, jakarta.tags.xml). Java EE 8 and earlier (Pages 2.3, EL 3.0, JSTL 1.2, Servlet 4.0) used javax.* and the http://java.sun.com/jsp/jstl/... URIs.
What’s Changed & Migration lists every change between them.
Container support matrix
Any Jakarta EE 11 servlet container runs the examples. The three that matter in practice differ in what they are and how they provide the JSP engine; the full comparison and the installation steps are on Getting Started.
| Apache Tomcat 11.0.26 | Eclipse Jetty 12.1.14 | Eclipse GlassFish 8.0.5 | |
|---|---|---|---|
Specifications |
Servlet 6.1, Pages 4.0, EL 6.0, WebSocket 2.2 (the Jakarta EE 11 servlet-container set); Java 17 or later |
One environment per Jakarta EE release ( |
A full Jakarta EE 11 application server (Platform and Web Profile distributions) |
JSP and EL engines |
Jasper and its own EL implementation, built in |
Apache Jasper, packaged with the |
Eclipse WaSP (Pages) and Eclipse Expressly (EL) |
JSTL |
Not bundled: the API and the implementation travel in |
The WAR’s own JSTL jars were used |
Provided by the server; a WAR that carries its own copy also ran |
Older lines |
Tomcat 10.1 (Servlet 6.0, Pages 3.1) on Java 11 or later; Tomcat 9.0 stays on |
Jetty 12.0 and the |
GlassFish 7.x (Jakarta EE 10) |
Maven coordinates
The container supplies the Servlet, Pages and EL APIs, so a WAR compiles against them with provided scope. Tomcat does not ship JSTL, so the API and the
implementation are added with default scope and travel inside the WAR.
bookshelf-jsp<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.el</groupId>
<artifactId>jakarta.el-api</artifactId>
<version>6.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
The specification page of Pages lists its API as jakarta.pages:jakarta.pages-api, which does not exist on Maven Central; the artifact that does is
jakarta.servlet.jsp:jakarta.servlet.jsp-api, as above. The JSTL implementation is still 3.0.1 (2023-01-19).
Reading order
The pages build on each other; read them in this order the first time and use them as a reference afterwards.
-
Core JSP: lifecycle and translation first, then syntax, directives, implicit objects and scopes, scripting elements (to read legacy code), standard actions, composition, errors, encoding, JSP documents and configuration.
-
Expression Language: the basics, then operators, lambdas and streams, static access, records and
Optional, and configuration. -
JSTL: core, iteration, URLs, i18n, formatting, functions and the legacy SQL and XML libraries.
-
Custom tags: simple tags, classic tags, the TLD and EL functions, and tag files.
-
Building applications: Model 2 with servlets, forms and sessions, Spring MVC, Jasper, security, and testing and debugging.
What’s covered
Core JSP
-
JSP Lifecycle and Translation: translation to a servlet, compilation and the generated
_jspService -
Syntax, Comments & Escaping: elements, template text, comments and the escape conventions
-
Directives: every
pageattribute,includeandtaglib -
Implicit Objects & Scopes: the nine implicit objects,
PageContextand the four scopes -
Scripting Elements (Legacy): declarations, scriptlets and expressions (legacy)
-
Standard Actions & JavaBeans:
jsp:useBean,jsp:include,jsp:forwardand the bean conventions -
Includes, Forwards & Page Composition: building a page from other resources
-
Error Handling:
errorPage,isErrorPageand the container error pages -
Character Encoding: source, response and request encoding
-
JSP Documents (XML Syntax):
.jspx,jsp:rootand the XML view -
Configuration and Property Groups:
jsp-configand everyjsp-property-groupelement
Expression Language
-
Expression Language Basics: dollar-brace versus hash-brace, implicit objects and resolvers
-
EL Operators & Type Coercion: every operator, precedence and the coercion rules
-
EL Lambdas, Collections & Streams: lambdas, collection literals and the stream operations
-
EL Static Access, Records & Optional: static members, records and
Optional -
EL Configuration & ELProcessor: switching EL on and off, and the standalone
ELProcessor
JSTL
-
JSTL Core: the five libraries,
c:out,c:set,c:if,c:chooseandc:catch -
JSTL Iteration:
c:forEach,c:forTokensandvarStatus -
JSTL URLs, Imports & Redirects:
c:url,c:param,c:importandc:redirect -
JSTL i18n & Messages: locales, bundles and
fmt:message -
JSTL Formatting: numbers, dates and time zones
-
JSTL Functions: the sixteen
fn:functions -
JSTL SQL & XML (Legacy): the legacy
sql:andx:libraries
Custom tags
-
Custom Tags: SimpleTag:
SimpleTaghandlers -
Custom Tags: Classic Handlers:
Tag,IterationTagandBodyTaghandlers -
Tag Library Descriptors & EL Functions: the TLD and EL functions
-
Tag Files & Layouts:
.tagfiles and page layouts
Building applications
-
MVC with Servlets & JSP: Model 1, Model 2 and a front controller
-
Forms, Validation & Sessions: forms, validation and sessions
-
Spring MVC with JSP: JSP as the view technology of Spring MVC and Spring Boot
-
Security: escaping, access control and hardening
-
Jasper Configuration & Precompilation: Jasper parameters, development and production
-
Testing and Debugging JSP Applications: reading the generated servlet, testing and debugging