Running JSTL 1.2 on Tomcat 7 using Maven

I finally decided to bite the bullet and try using cleaner JSP methods, including JSTL tags for some looping constructs. I thought I could slam out a quick “hello world” on my Tomcat 7 instance, but what I found instead was a world of hurt! I wrote this blog article so that anyone facing a similar road can avoid the speed-bumps.

Okay, I know I haven’t posted anything on my blog in over a year, but this falls under the OMG-Why-Couldn’t-I-find-a-straightforward-answer category. Whomever suffers the same headache I suffered will hopefully get led here by Google…

The Problem: Running the most basic JSP Example

Up until now, the few times I’ve needed to cobble together a JSP file for some sort of front-end functionality, I’ve used raw, low-level JSP Scriptlets. Which means typing things like

<% if (something) { %> <some-html> <% } else { %> <some-html> <% } %>

all over the place. And if I wanted to do any looping, well forget about it! It’s a nightmare. So I’ve got these few books and articles that talk about the better ways to solve these problems using cleaner xml-y solutions, and most all of them dive into using JSTL (JSP Standard Tag Library) which is a damned standard and yet isn’t included with Tomcat. It’s one of those things that each vendor is supposed to implement independently, and yet the only implementation out there appears to be Oracle’s Glassfish implementation! (There’s an Apache JSTL project, and they say on their web page that a version 1.2 implementation (which is the stated version for the Java 6 EE standard collection, alongside Servlet 3.0 and JSP 2.2) but that webpage hasn’t been updated since October 2009!!

So apparently JSTL is so basic and simple that it’s included in the elementary pages of any JSP books, but like some bastard stepchild that nobody wants, it’s support is freakishly missing. Okay, enough bellyaching about how FUBAR that is… what about just getting the thing to run?

Here are some watchas that I ran into…

  • It doesn’t work… until it does. Until I had the right library dependencies working and the right namespace down, I didn’t get any error messages or diagnostics. I just found that my sample <c:forEach> tags would get merely copied into the resulting HTML.
  • The JSP namespace changed. Some early books showed examples where the JSP namespace was written out as xmlns:c="http://java.sun.com/jstl/core" when in fact it later got renamed to xmlns:c="http://java.sun.com/jsp/jstl/core"! Again, no error messages to help me out here. It just didn’t work until it did.
  • Dependency hell, JSTL 2.1 can include the wrong JSP API versions. More on this in the next section.

The good news is you should just be able to grab the Oracle Glassfish implementation JAR, toss that into Tomcat’s lib directory, and stop worrying. But if you use Maven for your dependency management, then life gets crazy again.

JSTL and Maven Dependencies

For the longest time I avoided learning Maven because it just seemed like “just one more thing” and besides, Eclipse seemed to handle all the packaging, etc. just fine. But once I started playing around with XML and SOAP and Web Services and Dependency Injection and Spring and all that really cool stuff, I knew I had to bite the bullet. And I’m glad I did.

Normally if I want to start using some feature (like JSTL) I’ll just do a search in my Eclipse pom dependencies pane, add the dependency and start using the thing. (It’s fantastic!) But unfortunately, Maven dependencies seem to have gotten tripped up when it comes to JSTL 1.2, the bastard stepchild of a dependency. And especially for Tomcat (6 or 7 apparently) which is the “We’re the de-facto standard Servlet 3.0/JSP 2.2 container… except for the JSTL Bastard Stepchild!” server.

When I tried to do a simple dependency inclusion…

&lt;dependency&gt;
  &lt;groupId&gt;javax.servlet&lt;/groupId&gt;
  &lt;artifactId&gt;jstl&lt;/artifactId&gt;
  &lt;version&gt;1.2&lt;/version&gt;
&lt;/dependency&gt;

I got the API, but no runtime libraries. (As I said in the earlier section, this doesn’t result in a compile or runtime error. The JSTL tags simply don’t run and get passed through the outgoing HTML!) So then, after looking for an Apache implementation (I wanted to keep my implementation flavors consistent, and Apache wrote the Servlet 3.0/JSP 2.2 for Tomcat) I decided to include the Glassfish implementation…

&lt;dependency&gt;
  &lt;groupId&gt;org.glassfish.web&lt;/groupId&gt;
  &lt;artifactId&gt;jstl-impl&lt;/artifactId&gt;
  &lt;version&gt;1.2&lt;/version&gt;
&lt;/dependency&gt;

and THEN I finally got a runtime exception. But this

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

At least this time I got an error message, strange as it was! (And all throughout this experience I didn’t find much of use on the Internet, which is why I’m writing this blog entry.) So at least I got the general idea that there was a revision/dependency problem between the classes. This is why I really hoped to find a JSTL library by Apache—because if you stick with one “flavor” you’re less likely to run into this.

I went into the Dependency Hierarchy tab of my Eclipse POM editor, and I could see that the Glassfish Maven module I’d included also decided to include the Servlet 2.5 and JSP 2.1 libraries. So I was causing a Servlet 3.0/2.5 and JSP 2.1/2.2 clash in my class loader. I clicked on those individual components, right-clicked, asked to remove the dependency, and ended up with this:

&lt;dependency&gt;
  &lt;groupId&gt;org.glassfish.web&lt;/groupId&gt;
  &lt;artifactId&gt;jstl-impl&lt;/artifactId&gt;
  &lt;version&gt;1.2&lt;/version&gt;
  &lt;exclusions&gt;
    &lt;exclusion&gt;
      &lt;artifactId&gt;servlet-api&lt;/artifactId&gt;
      &lt;groupId&gt;javax.servlet&lt;/groupId&gt;
    &lt;/exclusion&gt;
    &lt;exclusion&gt;
      &lt;artifactId&gt;jsp-api&lt;/artifactId&gt;
      &lt;groupId&gt;javax.servlet.jsp&lt;/groupId&gt;
    &lt;/exclusion&gt;
  &lt;/exclusions&gt;
&lt;/dependency&gt;

(Note: I actually removed the “jstl-api” dependency I’d mentioned earlier in this post because it gets included as a dependency of the Glassfish “jstl-impl” and I like to keep things trim and minimal.)

Now to reclaim the hours it took me to get this far! I almost think I should have stuck with the old JSP-style scriptlets all over the place!

Author: Murray Todd Williams

I live in Austin, Texas. I'm enthusiastic about food, wine, programming (especially Scala), tennis and politics. I've worked for Accenture for over 12 years where I'm a Product Manager for suite of analytical business applications.

25 thoughts on “Running JSTL 1.2 on Tomcat 7 using Maven”

  1. This was *exactly* what I was looking for–not only the steps to make it work, but actually telling me *why* it didn’t work. I finally got it all to run. Thank you so much!

  2. Thanks for the note. Yeah, it doesn’t happen often, but every now and then there’s a complete “hole” in the Googlable universe on a relatively large topic like this. I have no illusions of my little blog being read actively, but as long as the search engines will index it, every now and then I like to know I’ve helped someone out.

    An update on the entire overall topic—and this I find rather strange—is that it seems that JSP and JSTL are dead. I am practicing in hyperbole here, but the fact of the matter is that any modern J2EE developer has moved on to either JSF or Google’s GWT. JSP may be okay for a quick “knock this small thing out” solution, but I guess the implication is that you shouldn’t really waste your time on it.

    Now having said that, if you talk with corporate IT departments (and I work with some IT groups in the Fortune 50) you will find that there is plenty of active JSP development going on, and that there are few boots-on-the-ground people doing JSF. Then again, one of these companies I’ve worked with just last year moved from Java 1.4 to Java 5 (or more specifically from IBM WebSphere 5 to 6) so you can see what’s going on.

    Anyway, food for thought.

  3. I would like to add that I couldn’t get this to work with Tomcat 7.0.22. I spent an inordinate amount of time on it and then for the heck of it, downloaded 7.0.27 and it worked right out of the box with the war I had been testing with all along.

  4. Just wanted to say hi and thanks. I had an old application that was running fine under Resin that I had to move to Tomcat and then I stumbled upon this idiocy… I was including just javax.servlet.jstl/1.2 as dependency because I thought it included the reference implementation also. In many places it talks about jstl-api.jar and jstl-impl.jar so I thought a jstl.jar that includes org.apache classes would include the reference implementation… WRONG!

    Instead of no message or anything, I was getting the infamous “The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application” but it seems the problem was the same…

    Oh well, thanks for the heads up, it worked :).

  5. Thank you a lot. This really saved my day, since I was almost going nuts not understanding why it told me there’s no taglib for the given namespace.

    The error message could indeed be better explained.

    Thanks!

  6. What was supposed to be an easy to find fix took me hours to find it until I found your article. Thank you.

  7. Phew, Google did it’s work! This saved me from smashing my PC through the window!
    Nice work posting this here!

  8. Mr. Williams

    I am very thank full to you. I was googling for last 3 hours to solve this problem.
    Finally I got what I was expecting.

  9. Thanks a million for posting that critical snippet. I lost my sleep two days in a row to find out why it worked for me initially but then started breaking as I set up the environment for another developer. For a while, I thought I would not be able to reproduce the successful setup.

    Once again many, many thanks :)))).

  10. Thanks for the note. Just in case my “tip” here was outdated (I wrote it well over a year ago!) I decided to take a look at this. (Reading your blog reference made me feel relieved in my “Maven Dependency Madness” when it came to this topic.) I also tried this out to see if I could get things to work out right.

    One thing: your set of dependencies is for Tomcat 6 which is Servlet 2.5 + JSP 2.1 which is equivalent to the J2EE 5 technologies. I had chosen the Tomcat 7 stack, which is Servlet 3.0 + JSP 2.2. This is actually relevant because your suggested jasper-el module imports a dependency chain of the servlet 2.5 and jsp 2.1 modules which would conflict with Tomcat 7.

    Also, your lineup here still doesn’t include an “jstl-impl” component—I was hoping that the jasper-el library you mentioned would do this—so you’re still stuck importing some implementation, and it still looks like Glassfish is the only standard version as Apache’s JSTL implementation is still dead and long defunct. (Their web page now officially states the Jakarta JSTL work is dead.)

    So for the sake of people reading the blog, I’ve still got to recommend my same dependency lineup.

  11. Thank You so much. I spent few hours on this. This post really saved hours of my time.

  12. Hi Murray,

    Thanks for the post. Unfortunately it did not work for me (somehow). I still cannot find the reason for this. Even if I add Glassfish implementation with exclusions, still entire page tags are just being copied to my view (as it happened to you initially). No complains, no errors, nothing! I am using Servlet 3.1.0 (also tried Servlet 3.0.1), Tomcat 7.0.55 (also tried 7.0.27), JSTL 1.2 as you did.
    Do you have any clue?

    Thanks!

  13. I’m not likely to be much help. But here’s where I would start looking: first look at your built WAR file (jar-unpack it or look in the appropriate target/something/WEB-INF/lib subdirectory) to make sure your see a jstl-impl.jar or jstl-impl-1.2.jar. If you don’t, then you haven’t solved your maven dependency issue yet and you need to go back to your POM file.

    If you do have the library included but still don’t see anything, then the problem may very well be the namespace you are using in your JSP’s header—where you define what tags map to.

    Best of luck.

    Murray

  14. Thanks for the pointers in the article.
    I would add one more thing which helped resolved my issue- the web.xml should be declared to conform to Servelet 2.5 specification.

  15. Hi Murray,

    Actually you are wrong about jstl 1.2 maven artifact: it contains not only API, but implementation also.
    See http://stackoverflow.com/tags/jstl/info. You can also check yourself that jar contains org.apache.taglibs.standard package with runtime classes.

    That is why for Tomcat 6 and JDK 6 pom.xml like below is working solution:

    javax.servlet
    servlet-api
    2.5
    provided

    javax.servlet.jsp
    jsp-api
    2.1
    provided

    javax.servlet
    jstl
    1.2

    I didn’t check the situation with Tomcat 7, but JSTL 1.2.1 should be used with it to be compatible with Java 7. And here is a different situation because API and implementation are in different jars and your solution should be working.

  16. I made an error in my previous post. I mentioned java versions as shorthand for supported servlet and jsp specs. I mixed the numbers, correct versions are:
    Tomcat 6 – Java 5 or more – Servlet 2.5 – JSP 2.1 – JSTL 1.2
    Tomcat 7 – Java 6 or more – Servlet 3.0 – JSP 2.2 – JSTL 1.2.1

    http://tomcat.apache.org/whichversion.html

Leave a Reply

Your email address will not be published. Required fields are marked *