Monday, February 15, 2010

Solving Tomcat + JSF 2.0 Error: java.lang.LinkageError: loader constraint violation

What happens when you try running JSF 2.0 web framework on Tomcat 6? This error:

HTTP Status 500 -


type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class, org/apache/jsp/index_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature org.apache.jasper.servlet.JspServlet.service(JspServlet.java:275) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) root cause
java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;" the class loader (instance of org/apache/jasper/servlet/JasperLoader) of the current class, org/apache/jsp/index_jsp, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature org.apache.jsp.index_jsp._jspInit(index_jsp.java:25) org.apache.jasper.runtime.HttpJspBase.init(HttpJspBase.java:52) org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:159) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:329) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) note The full stack trace of the root cause is available in the Apache Tomcat/6.0.20 logs.

Apache Tomcat/6.0.20

The problem is simple: Tomcat ships with an old version of el-api, the Expression Language used by JSP, JSTL, and JSF.

JSF 2.0 uses the new Java EE 6 version that is EL 2.2. Unfortunately you can't just put the new EL libraries in your WEB-INF/lib because of Tomcat's restriction.

To fix this, you don't need to change your project.. but you need to patch your Tomcat installation:
  1. Delete el-api.jar from your Tomcat's lib folder.
  2.  Get the new el-api-2.2.jar from java.net and save it as el-api.jar on the Tomcat's lib folder.
You will also need to put the new el-impl.jar on your web application's WEB-INF/lib folder.

For a Maven web project, put this in your pom.xml :
                <dependency>
                    <groupId>javax.el</groupId>
                    <artifactId>el-api</artifactId>
                    <version>2.2</version>
                    <scope>provided</scope>
                </dependency>
                <dependency>
                    <groupId>org.glassfish.web</groupId>
                    <artifactId>el-impl</artifactId>
                    <version>2.2</version>
                    <scope>runtime</scope>
                </dependency>
You also need to use java.net's Maven repository:
<repositories>
    <repository>
        <id>java.net.m2</id>
        <url>http://download.java.net/maven/2</url>
        <snapshots>
           <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>
Related Articles: