¿Cómo instalar JSTL? Falla con "No se puede resolver el uri absoluto" o "No se puede encontrar taglib" o NoClassDefFoundError o ClassCastException
No sé qué hice incorrectamente, pero no puedo incluir JSTL. Lo he hecho jstl-1.2.jar
, pero desafortunadamente recibo una excepción:
org.apache.jasper.JasperException: la uri absoluta: http://java.sun.com/jstl/core no se puede resolver ni en web.xml ni en los archivos jar implementados con esta aplicación.
Tengo esto en pom.xml
:
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
Estoy intentando usarlo de la siguiente manera:
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
En su caso específico,
org.apache.jasper.JasperException: la uri absoluta: http://java.sun.com/jstl/core no se puede resolver ni en web.xml ni en los archivos jar implementados con esta aplicación.
ese URI es para JSTL 1.0, pero en realidad estás usando JSTL 1.2, que usa URI con una /jsp
ruta adicional. Este cambio de URI se debe a que JSTL, que inventó las expresiones EL, se integró desde la versión 1.1 como parte de JSP 2.0 (¡lanzado en 2001!) para compartir/reutilizar la lógica EL también en JSP simple. Consulte también Diferencia entre JSP EL, JSF EL y Unified EL .
Por lo tanto, corrija el URI de taglib según la documentación de JSTL 1.2 :
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Además, debe asegurarse absolutamente de no incluir varios archivos JSTL JAR con versiones diferentes juntos en la ruta de clase del tiempo de ejecución o versiones que no coincidan con la versión esperada por el tiempo de ejecución de destino (el servidor) o simplemente con la API sin implicación. De lo contrario, corre el riesgo de ver otros errores como los siguientes:
org.apache.jasper.JasperException: no se puede encontrar el descriptor de la biblioteca de etiquetas para "http://java.sun.com/jsp/jstl/core"
org.apache.jasper.JasperException: no se puede encontrar taglib [c] para URI: [jakarta.tags.core]
java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/TagLibraryValidator
java.lang.NoClassDefFoundError: jakarta/servlet/jsp/tagext/TagLibraryValidator
java.lang.ClassCastException: la clase org.apache.taglibs.standard.tlv.JstlCoreTLV no se puede convertir a la clase jakarta.servlet.jsp.tagext.TagLibraryValidator
Este es un error bastante común entre los usuarios de Tomcat. El problema con Tomcat es que no ofrece JSTL listo para usar y, por lo tanto, debe instalarlo manualmente. Esto no es necesario en los servidores normales de Yakarta EE. Consulte también ¿Qué es exactamente Java EE? y ¿ Cómo configurar correctamente las bibliotecas Jakarta EE en Maven pom.xml para Tomcat?
En su caso específico, su pom.xml básicamente le dice que tiene jstl-1.2.jar y standard-1.1.2.jar juntos. Esto está mal. Básicamente estás mezclando JSTL 1.2 API+impl de Oracle (GlassFish) con JSTL 1.1 impl de Apache. Debe eliminar las implementaciones JSTL duplicadas y limitarse a una sola implementación JSTL y la versión de API debe coincidir con la versión impl y la versión de API debe ser compatible con el tiempo de ejecución de destino.
Instalación de JSTL en Tomcat 10.1.x
En caso de que ya esté en Tomcat 10.1.x (la segunda versión Jakartificada, con jakarta.*
paquete en lugar de javax.*
paquete, pero la primera versión con las jakarta.tags.*
URN del espacio de nombres actualizadas en lugar de http://java.sun.com/jsp/jstl/*
las URL del espacio de nombres), use JSTL 3.0 a través de estas dependencias usando el alcance predeterminado de Maven de compile
(¡porque Tomcat no lo proporciona listo para usar!):
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>3.0.1</version>
</dependency>
Tenga en cuenta que la dependencia de API se debe a que esta versión no se incluye transitivamente a través de la dependencia impl, por lo que debe declararla explícitamente.
Los usuarios que no son Maven pueden lograr lo mismo colocando los siguientes dos archivos físicos en la /WEB-INF/lib
carpeta del proyecto de la aplicación web (¡ no coloques ningún archivo estándar*.jar ni ningún archivo .tld suelto allí! Elimínalos si es necesario).
- jakarta.servlet.jsp.jstl-api-3.0.0.jar (esta es la API JSTL 3.0)
- jakarta.servlet.jsp.jstl-3.0.1.jar (este es el impl JSTL 3.0.1 de EE4J)
Como se dijo, los URI del espacio de nombres se han cambiado para convertirse en URN en lugar de URL. El núcleo de JSTL está disponible desde la versión 3.0 de JSTL a través de un URI de espacio de nombres más fácil de recordar en formato URN:
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
Consulte también la documentación de JSTL 3.0 .
En caso de que realmente desee utilizar la implementación JSTL de Apache en lugar de EE4J, debe saber que no tienen una versión 3.0 y mucho menos una 2.0. La última versión publicada actualmente de la implementación JSTL de Apache es 1.2.3 y ya no se mantiene activamente desde febrero de 2015 . La implementación JSTL de EE4J (anteriormente Oracle/Sun) es actualmente (julio de 2023) su única opción.
Instalación de JSTL en Tomcat 10.0.x
En caso de que esté en Tomcat 10.0.x (la primera versión Jakartificada, con jakarta.*
paquete en lugar de javax.*
paquete), use JSTL 2.0 a través de esta única dependencia usando el alcance predeterminado de Maven compile
(¡porque Tomcat no lo proporciona de fábrica!):
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>2.0.0</version>
</dependency>
Tenga en cuenta que la dependencia de la API ya está incluida de forma transitiva a través de esta dependencia implícita, por lo que no es necesario declararla explícitamente.
Los usuarios que no son Maven pueden lograr lo mismo colocando los siguientes dos archivos físicos en la /WEB-INF/lib
carpeta del proyecto de la aplicación web (¡ no coloques ningún archivo estándar*.jar ni ningún archivo .tld suelto allí! Elimínalos si es necesario).
- jakarta.servlet.jsp.jstl-api-2.0.0.jar (esta es la API JSTL 2.0)
- jakarta.servlet.jsp.jstl-2.0.0.jar (este es el impl JSTL 2.0 de EE4J)
Instalación de JSTL en Tomcat 9-
En caso de que aún no esté en Tomcat 10, pero aún tenga Tomcat 9 o anterior, use JSTL 1.2 a través de esta única dependencia (esto es compatible con Tomcat 9/8/7/6/5 pero no anterior) usando el alcance predeterminado de Maven. de compile
(¡porque Tomcat no lo proporciona listo para usar!):
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
<version>1.2.6</version>
</dependency>
Tenga en cuenta que la dependencia de la API ya está incluida de forma transitiva a través de esta dependencia implícita, por lo que no es necesario declararla explícitamente.
Los usuarios que no son Maven pueden lograr lo mismo colocando los siguientes dos archivos físicos en la /WEB-INF/lib
carpeta del proyecto de la aplicación web (¡ no coloques ningún archivo estándar*.jar ni ningún archivo .tld suelto allí! Elimínalos si es necesario).
- jakarta.servlet.jsp.jstl-api-1.2.7.jar (esta es la API JSTL 1.2)
- jakarta.servlet.jsp.jstl-1.2.6.jar (este es el impl JSTL 1.2 de EE4J)
Instalación de JSTL en un servidor JEE normal
En caso de que esté utilizando un servidor Jakarta EE normal como WildFly, Payara, TomEE, GlassFish, WebSphere, OpenLiberty, WebLogic, etc. en lugar de un contenedor de servlet básico como Tomcat, Jetty, Undertow, etc., entonces no necesita instalar JSTL explícitamente. Los servidores normales de Yakarta EE ya proporcionan JSTL listo para usar. En otras palabras, no necesita agregar JSTL pom.xml
ni soltar ningún archivo JAR/TLD en la aplicación web. Sólo la provided
coordenada EE de Yakarta con alcance es suficiente:
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version><!-- 10.0.0, 9.1.0, 9.0.0, 8.0.0, etc depending on your server --></version>
<scope>provided</scope>
</dependency>
Asegúrese de que la versión web.xml sea correcta
Además, también debe asegurarse de que su web.xml
declaración se ajuste al menos a Servlet 2.4 y, por lo tanto, no a Servlet 2.3 o anterior. De lo contrario, las expresiones EL dentro de las etiquetas JSTL no funcionarían. Elija la versión más alta que coincida con su contenedor de destino y asegúrese de que no tenga ninguna <!DOCTYPE>
en ningún lugar web.xml
, ya que de lo contrario aún activaría el modo Servlet 2.3. Aquí hay un ejemplo compatible con Servlet 6.0 (Tomcat 10.1.x):
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<!-- Config here. -->
</web-app>
Y aquí hay un ejemplo compatible con Servlet 5.0 (Tomcat 10.0.x):
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<!-- Config here. -->
</web-app>
Y aquí hay un ejemplo compatible con Servlet 4.0 (Tomcat 9):
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- Config here. -->
</web-app>
Ver también:
- Documentación de taglib principal de JSTL (para los URI de taglib correctos)
- Expresiones EL no evaluadas en JSP
- Cómo configurar pom.xml para Tomcat 10+ o Tomcat 9-
@BalusC tiene toda la razón, pero si aún encuentra esta excepción, significa que algo ha hecho mal. La información más importante que encontrará se encuentra en la página Información de etiqueta SO JSTL .
Básicamente, este es un resumen de lo que debe hacer para abordar esta excepción.
Verifique la versión del servlet en web.xml:
<web-app version="2.5">
Compruebe si la versión JSTL es compatible con esta versión de servlet: la versión 2.5 del servlet usa JSTL 1.2 o la versión 2.4 del servlet usa JSTL 1.1
Su contenedor de servlets debe tener la biblioteca adecuada o debe incluirla manualmente en su aplicación. Por ejemplo: JSTL 1.2 requiere jstl-1.2.jar
Qué hacer con Tomcat 5 o 6:
Debe incluir los archivos jar apropiados en su directorio WEB-INF/lib (funcionará solo para su aplicación) o en tomcat/lib (funcionará globalmente para todas las aplicaciones).
Lo último es un taglib en tus archivos jsp. Para JSTL 1.2, el correcto es este:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Encontré otra razón para este tipo de error: en mi caso, alguien configuró la propiedad conf/catalina.properties
de configuración para evitar mensajes de advertencia de registro, omitiendo así el análisis necesario de Tomcat. Cambiar esto nuevamente al valor predeterminado de Tomcat y agregar una lista apropiada de archivos jar para omitir (sin incluir jstl-1.2 o spring-webmvc) resolvió el problema.tomcat.util.scan.StandardJarScanFilter.jarsToSkip
*
jstl-1.2.jar --> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
jstl-1.1.jar --> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
También verifique los archivos jar de dependencia que ha agregado javax.servlet.jar
o javax.servlet.jsp.jstl-1.2.1.jar
no en su carpeta WEB-INF/lib. En mi caso estos dos resolvieron el problema.
Agregue el jstl-1.2.jar
a la tomcat/lib
carpeta.
Con esto, tu error de dependencia se solucionará nuevamente.