jsptomcatjstljakarta-migration

jakarta.servlet.ServletException: java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/TagLibraryValidator


I am trying to execute JSP with JSTL, but I am not able to. I have Apache Tomcat 10, i.e. jakarta.servlet.* instead of javax.servlet.*. So whenever I execute the web app with JSTL 1.2.5 files, then I get the error:

jakarta.servlet.ServletException: java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/TagLibraryValidator
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:778)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

I tried to find a similar problem/question online that is resolved, but was not able to find it. How can I use JSTL in JSP with Tomcat 10?

My index JSP file code:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 
<html>  
  <head>  
    <title>Tag Example</title>  
  </head>  
  <body>  
    <c:out value="${'Hello Yo'}"/> 
  </body>  
</html>  

Solution

  • The Jakarta EE 9 / Servlet 5.0 compatible version of Jakarta Standard Tag Library is available as JSTL 2.0 from here.

    <dependency>
        <groupId>org.glassfish.web</groupId>
        <artifactId>jakarta.servlet.jsp.jstl</artifactId>
        <version>2.0.0</version>
    </dependency>
    

    This is the reference implementation of JSTL 2.0 which is currently also used in GlassFish 6.0 (originally from Sun, then owned by Oracle, then owned by Eclipse). Usually Apache also has its own implementation, but it is not available as JSTL 2.0 (yet?).

    For sake of completeness, and to confirm, yes the taglib URI of JSTL 2.0 still references the original java.sun.com host whereas you'd intuitively expect it also being migrated to xmlns.jcp.org or even jakarta.ee.

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    

    In case you're already on Jakarta EE 10 / Servlet 6.0 (e.g. Tomcat 10.1.x instead of Tomcat 10.0.x), then use JSTL 3.0 instead.

    <!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api -->
    <dependency>
        <groupId>jakarta.servlet.jsp.jstl</groupId>
        <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
        <version>3.0.2</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl -->
    <dependency>
        <groupId>org.glassfish.web</groupId>
        <artifactId>jakarta.servlet.jsp.jstl</artifactId>
        <version>3.0.1</version>
    </dependency>
    

    With this version, the taglib URI has been changed to from the URL form to the URN form as follows:

    <%@ taglib uri="jakarta.tags.core" prefix="c" %>
    

    See also: