Feb 19

Tutorial: How to set up Tomcat 6 to work with JSTL 1.2

Tag: development,java,jsp,jstl,spring,tomcatpmularien @ 11:37 pm

Tomcat 6 does not ship with an implementation of JSTL. I decided to write up this quick start guide, since it’s really, really hard for new folks to know how to get started with Spring MVC (which is very often combined with JSTL) on Tomcat 6.

Sadly, Sun’s JSTL site does not even point you at the actual reference implementation of JSTL 1.2 (at least there’s no very obvious link that I have been able to find – but what good would a Sun web site be if it was easy to find what you were looking for? ;) ).

The Apache Jakarta Taglibs project is the source of JSTL 1.0 and 1.1 reference implementations, but it is no longer maintained and will never implement JSTL 1.2.

Updated: Mar 1, 2011

You may now download the JSTL API and implementation JARs directly from the Sun Glassfish web site. Thanks to several alert readers for pointing this out!

Simply go to dev.java.net and download the two JAR files on the page for JSTL 1.2. Copy them into your Tomcat installation’s lib directory and you should be all set!

You can also download the JSTL JAR (API and implementation in a single JAR) directly from Maven Central.

If you are using Maven, you can pick up the JSTL dependency by including the following in your project’s POM file:


Older Information Below (2008 Vintage)

The JSTL 1.2 reference implementation has been folded into the Glassfish application server. It seems that Sun in its infinite wisdom has decided to make the reference implementation almost impossible to find. The link to “Reference Implementation” on the JSR-052 page points you to the Sun Java EE download page (argh!)

So, how do you get this installed on Tomcat?

  • Download the latest version of Glassfish V2 application server here.
  • Unzip/install to a directory
  • From the “lib” directory of the install, copy as follows:
    • appserver-jstl.jar: Place in the WEB-INF/lib directory of your web application. This is preferable because you can ensure that the correct version of JSTL lives with your application. Note you may run into classloader issues when running on application servers other than Tomcat which supply their own (conflicting) JSTL implementations. In this case, remove this JAR from your web application, and move it into {tomcat-install}/lib.
    • javaee.jar: In the {tomcat-install}/lib folder. This will make the JSTL 1.2 libraries available to all web applications.

Note that placing javaee.jar in the app server lib directory isn’t really the best way to go about this, but Tomcat will ignore the JAR if it’s included in your webapp due to the rule in section 9.3.2 of the Servlet 2.3 spec (in fact, it will ignore any JAR file completely if it contains the class javax.servlet.Servlet). For further reference, you can see the classloader code. You will see the following error when your webapp is started up if you have javaee.jar in WEB-INF/lib (assuming appropriate logging is enabled):

INFO: validateJarFile({path-to-webapp}\WEB-INF\lib\javaee.jar) – jar not loaded. See Servlet Spec 2.3, section 9.7.2.
Offending class: javax/servlet/Servlet.class

For you Spring MVC’ers trying to get started with the latest versions of Tomcat and JSTL, hopefully this helps you!

53 Responses to “Tutorial: How to set up Tomcat 6 to work with JSTL 1.2”

  1. Christian Ullenboom says:

    A litte sidenote: With Glassfish v3 the Jars are under /modules and named e.x. jstl-api-1.2.jar.

  2. pmularien says:

    Thanks, I’ve updated the content to specify v2, until v3 stabilizes a bit more.

  3. newbie says:

    So the only way is to install them in the tomcat lib directory? In other words, I can’t have them in just my application’s lib directory, i.e., /WEB-INF/lib ?

  4. pmularien says:

    Indeed you can – I must have missed that [highly preferable] option when I reviewed this entry prior to posting. I’ve revised it listing both the WEB-INF/lib and Tomcat lib directories as choices. Thanks for the feedback!

  5. Frederic Filiatrault says:

    Hi pmularien,

    After loosing about 2 hours saying: “WTF happened with Tomcat?@##@)@(%*#)@( *”, I found your website.

    Pray the Lord! You described exactly what I have found but was not sure. How come Tomcat, which is a fair web container IMHO can intentionally omit JSTL jars?!?

    Anyway, many thanks for your page on this!

  6. It’s Only Software » How to Reference and Use JSTL in your Web Application says:

    [...] Of these, JBOSS and Glassfish ship with JSTL implementations out of the box. Tomcat does not ship with a JSTL implementation. I have previously blogged about this here. [...]

  7. Sam Weinger says:

    Am I the only one who is unable to get this to work without placing javaee.jar in {tomcat-install}/lib? Otherwise the webapp class loader is unable to find classes that implement the tags.

  8. pmularien says:


    I have seen that behavior too, since I posted this article. I’ve been meaning to dig into it a little more, and your comment has pushed it up on the priority list. Look for an update soon!


  9. pmularien says:

    So, it seems that Tomcat will not recognize j2ee.jar if it’s included only in your webapp. This is because Tomcat is coded to ignore any JAR file containing classes from javax.servlet, which j2ee.jar does (along with a whole host of other stuff). It looks like, unless you want to create a j2ee.jar with the javax.servlet stuff elided. I’ll update the article to reflect this. At minimum, it seems you need j2ee.jar in (tomcat-install)/lib, and appserv-jstl.jar can reside with your webapp.

  10. Dylan MacDonald says:

    God how I wish this worked. The version of glassfish you cite does not have the files you mention. Well, it does but they are archived as appserv-jstl.jar.pack.gz and javaee.jar.pack.gz. Easy to unarchive .gz files, but I could not for the life of me find what .pack files are and how to unarchive them. I swear I hate development sometimes. Everything has to be so damn difficult.

  11. pmularien says:

    @ Dylan -

    Make sure you run the step of the Glassfish “install” process that includes executing the ‘setup.xml’ ant script. This is the step that will unpack those files. Alternatively, I believe the Sun distribution of Glassfish will unpack when you run the installer.

    Good luck!

  12. Alex says:

    If you want to just add the appsrv-jstl.jar and javaee.jar to WEB-INF/lib here is what you need to do: javaee.jar has all the JEE stack in it, so you need to manually extract just the javax.servlet.jsp.jstl package. This is what is needed to run the tags. The trimmed version of javaee.jar will go in to WEB-INF/lib just fine. The same can be done with GF v3 new jars. Hope this helps.

  13. Steven says:

    The JSTL 1.2 and UEL 1.0 Api and impl can be downloaded here:

    have fun!


  14. Rafal Rusin says:

    Except that implementations contain 0 files on dev.java.net

  15. Howard says:

    Here’s a direct link to JSTL 1.2. jars – https://maven-repository.dev.java.net/repository/jstl/jars/

  16. Dennis says:

    Thank you for this article! What a pain in the neck. Is there no JSTL 1.2 implementation in the Maven Repo yet? Stinks having to d/l and modify the Glassfish javaee.jar.

  17. Joakim Andersson » Blog Archive » How to set up Tomcat 6 to work with JSTL 1.2 says:

    [...] » Tutorial: How to set up Tomcat 6 to work with JSTL 1.2 – It’s Only Software.   [...]

  18. cruuzzz says:

    I was starting with spring mvc and tried its step-by-step sample on tomcat 6.
    I run into mentioned issues with jstl, this article really helped me out…

    @ howard works just fine for me thanks alot

  19. Guntis Ozols says:

    Please add to the tutorial that after jar copying is done, recompilation of jsp has to be forced

  20. Setting Up Tomcat 6 with JSF « Distributing Java says:

    [...] found this very useful post, which advied me to install glassfish and pull a couple jars from its lib folder. I did this, and [...]

  21. ahmed says:

    thank you. what a great post. when u don’t work with tomcat often, this really helps

  22. Pratima says:

    thanks a ton for posting this..really helps beginners like me

  23. Kiran says:

    pmularien :
    I did everything you said needs to be done. But, I still keep getting run time error as follows. What could be the other area I should be looking into , please ?

    org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config

    root cause

    java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config

  24. Tin says:

    I believe this is now on the Maven site for easy download as a single jar. You should be able to just include this in your application’s lib folder. I have not had a chance to test this out yet. Still trying to find out what is new with JSTL 1.2 and if I should even upgrade.

  25. Tin says:
  26. Ignacio de La Madrid says:

    Thank you very much! It has been a very though time trying to solve this problem. If you let me, I’d say this was a mo..fu.. conundrum! But you guys have helped me, THANKS! Especially to the owner of the blog. I know we can take a great tutorial from here called : “The wizard of Sun” lol. No, I’m just joking; I have found my answer because of you.

  27. Panos says:

    I think Tomcat 6 does come with JSTL 1.2 support. The examples that come with Tomcat contain a few JSP pages that use JSTL. Besides in the examples/WEB-INF/lib directory you will find the two jstl.jar and standard.jar files.

  28. sherb says:

    @Panos… I too have seen jstl.jar and standard.jar in the examples folder (Tomcat 6.0.18 distro, to be exact). However, if you call org.apache.taglibs.standard.Version.getVersion on standard.jar you’ll get something back like “standard-taglib 1.1.D16″, which is the old JSTL 1.1.

  29. Maximilian Eberl says:

    @ Peter Mularien
    You saved my weekend! May You live 120 years!! Rich and happy!! And allways good music and good wine!!!

    Thank You too, this lib works perfectly

    @ sherb
    In JSTL the package names are no longer org.apache…, but javax.servlet….

    Peace and good food to all of You!

  30. sherb says:

    @ Maximilian… Not all the packages have moved under JSTL 1.2. Unjar “jstl-1.2.jar” and take a look at the contents: The Version class is still along the org.apache package path, and will respond with “standard-taglib 1.2.0″ when queried.

  31. Javatech » A Conventionally Annotated Configuration – Spring, Hibernate, Eclipse says:

    [...] Only *Glassfish* ships with the reference implementation of JSTL 1.2?!?  Oh brother.  Thanks to Peter Mularien for writing a nice post informing me of [...]

  32. SrinivasReddy says:

    Hi pmularien,
    this helped alot in solving problem in Spring example as DispatcherServlet…..

  33. WeeBay says:

    Thanks for a great article.

    I’m having a problem with the expression language. I’m running Tomcat 6.0.14 with he two .jar files placed appropriately. My web.xml references servlet 2.5 and I have the JSTL 1.2 taglib directives at the top of each JSP page. Struts is my framework and I’m using the Struts-el taglibs as well.

    My problem is that only some of the EL expressions will render – specifically those that are coded as the value of an attribute of a Struts-el tag. If the EL expression is the value of an attribute of a JSTL tag or is coded as plain old template text (which you are supposed to be able to do under JSTK 1.2), then what gets rendered is the literal value of the expression, e.g. ${foo}. Strangely enough if I back off the taglib directives to JSTL 1.0, everything works fine (except coding an EL expression as template text).

    I have not tried adding any jsp_property_group elements to the web.xml or coding isElIgnored anywhere. How all these various elements – web.xml, JSP, JSTL, EL – fit together is confusing at best.

    Any thoughts?

  34. Seifer says:

    Update: Sun’s web site has link to jstl 1.2 implementation
    I’ve googled ‘jstl sun’
    then follow: ‘JSTL Projects’ > ‘Download JSTL’ will bring you a page with 2 links to jar files.

    You may want to update your post. =)

    I was having trouble setting up jstl but not anymore.

  35. Rodrigo Bartels says:

    JSTL 1.2 Jar @ http://download.java.net/maven/glassfish/org/glassfish/web/jstl-impl/1.2/jstl-impl-1.2.jar

    Just copy to /tomcat/lib folder and works!

  36. Matias says:

    thanks a million for the great article. Saved me heaps of time. One minor suggestion, in the article you name the file as “appserver-jstl.jar” when it should be “appserv-jstl.jar”

  37. Viktor says:

    Thank you Peter for article. It is good to know about missing jstl libs in tomcat.

    Here is updated link https://jstl.dev.java.net/download.html nowadays.

  38. BillC says:

    Thank you to Peter and those that posted update comments… it was the combination of all the above that got me past the JSTL part of the Spring documentation for web apps. Thanks!

  39. Failed to load or instantiate TagLibraryValidator class: org.apache.taglibs.standard.tlv.JstlCoreTLV « Sri's At Work Blog says:

    [...] If it still doesnt work then follow the steps mentioned at this site [...]

  40. lwpro2 says:

    its actually quite a simple case.
    for tomcat 6, jstl.jar and standard.jar needed to be dropped into the lib directory to use JSTL.

  41. shashank says:

    thanks man.. i really appreciate your posting it here so that guys like me can find it out.. thanks again

  42. Colin says:

    If you’re using Tomcat 6 & Maven, this is all you need to add to your pom:


    That worked for me.

    Thanks for putting this page together and for your other page on how to import the taglib correctly. Very helpful.

  43. Colin says:

    OK, the xml was eaten in my last post. Add this dependency to your pom:

    groupId: javax.servlet
    artifactId: jstl
    version: 1.2

  44. gant says:

    Thank you so much. You saved my day.

  45. sharad says:

    I am getting this eroor while i have put jstl.jar on proper place as mentioned in different docs.plz suggest me proper solution

    type Exception report

    message Internal Server Error

    description The server encountered an internal error (Internal Server Error) that prevented it from fulfilling this request.


    org.apache.jasper.JasperException: This absolute uri (http://java.sun.com/jsp/jstl/core) cannot be resolved in either web.xml or the jar files deployed with this application
    at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:105)
    at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:430)
    at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:154)
    at org.apache.jasper.compiler.TagLibraryInfoImpl.(TagLibraryInfoImpl.java:159)
    at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:354)
    at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:381)
    at org.apache.jasper.compiler.Parser.parseElements(Parser.java:795)
    at org.apache.jasper.compiler.Parser.parse(Parser.java:122)
    at org.apache.jasper.compiler.ParserController.parse(ParserController.java:199)
    at org.apache.jasper.compiler.ParserController.parse(ParserController.java:153)
    at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:227)
    at org.apache.jasper.compiler.Compiler.compile(Compiler.java:369)
    at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:473)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:190)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2417)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
    at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:577)
    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
    at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
    at org.apache.catalina.connector.http.HttpProcessor.process(HttpProcessor.java:1040)
    at org.apache.catalina.connector.http.HttpProcessor.run(HttpProcessor.java:1151)
    at java.lang.Thread.run(Thread.java:636)

  46. Playing With Jetty « Bit Motif says:

    [...] Setting a Web Application Context Tip: Enabling JSP support in Jetty.7.0.0 How to Reference and Use JSTL in your Web Application Tutorial: How to set up Tomcat 6 to work with JSTL 1.2 [...]

  47. Oliver Siegmar says:

    Please note, that the official maven repository does currently *NOT* contain a valid JSTL 1.2 version. See http://jira.codehaus.org/browse/MEV-677

  48. Gautham Nookala says:

    Thanks. The JSTL link really helped.

  49. Yatin says:


    Dude, sorry this is a bit late, but i was getting exactly the same message you were getting. I was only copying one of the jar files across and not the api jar. If you copy both files across, problem should be resolved.

  50. fazi says:

    thanks for the update, you helped a lot.

  51. Nirup says:

    tons of thanks ….this article helped me out, where i was getting the same error for a week.

  52. Roshan says:

    God bless you…

  53. Bad says:

    Thanks a lot. You saved me.I just downloaded JSTL 1.2 jar and dumped it in Tomcat/lib folder

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>