This combination creates a slight issue with dependencies for JSP and JSTL. If you have ever seen this error when running
mvn jetty:run
:java.lang.ClassNotFoundException: org.apache.el.ExpressionFactoryImpl
Or these errors when running in tomcat when it was okay in jetty:
javax.servlet.jsp.JspApplicationContext
.getExpressionFactory()Ljavax/el/ExpressionFactory
or
org.apache.jasper.JasperException: Unable to read TLD "META-INF/c.tld" from JAR file
or
java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/catalina/loader/WebappClassLoader) previously initiated loading for a different type with name "javax/el/ExpressionFactory"
Over the last few years I have perservered and solved this flat wheel in different ways. However in my recent deja-vue I now have a tidy solution. (the project where this is visable is my up4 project. github source, demo)
I am utilising the jetty maven plugin, and the tomcat maven plugin to show how this works.
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.0.2.v20100331</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
</plugin>
To utilise JSP pages and JSTL EL with e.g. Spring MVC / Struts Tiles you perhaps expect these types of maven dependencies, remembering that most containers include support for Servelet API and JSPs:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
If you then try
mvn clean jetty:run
you may end up with a:java.lang.ClassNotFoundException: org.apache.el.ExpressionFactoryImpl
A response which will solve the jetty problem is to include some jstl EL dependencies:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jasper-el</artifactId>
<version>6.0.26</version>
</dependency>
mvn jetty:run
This should now work fine in Jetty (test in browser as well).
Now try the application in tomcat:
mvn clean tomcat:run
. It will moan about unable to read some the JSTL taglibs:org.apache.jasper.JasperException: Unable to read TLD "META-INF/c.tld" from JAR file
This due to the compile scope of the jsp-api dependency, changing this to provided:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jasper-el</artifactId>
<version>6.0.26</version>
</dependency>
Test first in
mvn jetty:run
, which should be okay. Then in
mvn clean tomcat:run
. It starts ok, but on the first browser test this error appears:javax.servlet.jsp.JspApplicationContext
.getExpressionFactory()Ljavax/el/ExpressionFactory
Okay, so Tomcat does not like JSTL EL dependencies as it provides them itself, so my initial respone was to have a separate profile which changed the scope of the dependency to provided for tomcat builds only. However on further reflection it turns out the spec says JSP & EL should be provided by the container. So in fact the problem lays with Jetty, and it turns out the move to eclipse.org created a licensing issue with JSP, so jetty does not include the appropiate libs. So to fix this the correct dependencies will have to be:
In your plugins section:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.0.2.v20100331</version>
<dependencies>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1-glassfish</artifactId>
<version>9.1.1.B60.25.p2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>el-api</artifactId>
<version>6.0.26</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jasper-el</artifactId>
<version>6.0.26</version>
</dependency>
</dependencies>
</plugin>
And in your normal dependencies section:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>el-api</artifactId>
<version>6.0.26</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>jasper-el</artifactId>
<version>6.0.26</version>
<scope>provided</scope>
</dependency>
mvn jetty:run
& mvn tomcat:run
Voila.
Ps. If you are providing a WAR for another jetty container, you may want to create a profile section which include the provided dependencies.
Ps2. If you prefer Sun's EL libs then replace the org.apache.tomcat dependencies with:
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>el-impl</artifactId>
<scope>runtime</scope>
<version>2.2</version>
</dependency>
I have tried your solution and it works only with jetty. With tomcat, application returns blank page.
Best regards
Great Ivar !
It's work fine for me ;-)
THANK YO SOOOOOOOOOOOOO MUCH!!
I've been trying to deploy my web aplicattion JSF 2.0 based during 10 days until i found this post.
:)
By
Thank you Ivar!
It has been really help
Thank you very much for your post.
I finnally managed to solve my problem using your dependencies.
Latest versions also work:
- jetty-maven-plugin/7.3.1.v20110307
- jsp-2.1-glassfish/2.1.v20100127
- el-api/6.0.32
- jasper-el/6.0.32
My problem was complicated because by maven misconfiguration I got gwt-dev/2.1.0 dependency to server module which was conflicting with many classes (JSP, EL, etc.) leading to many unclear errors.
Many thanks. It's really helpfull.
Thanks a bunch, I'm new to Maven and managed to get my jetty-websocket test to work by adding the right dependecy for the plugin.
Cheers!
I was never more happy. Thank you, this was a great post. Kudos for help ;)
Unless otherwise specified, all content is licensed under Creative Commons by Attribution 3.0 (CC-BY).
Externally linked images and content are not included and are licensed and copyrighted separately.
Comments
Comments below were made on a legacy Blog, before move to current Blog (February 2019)