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? spacer ).

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:

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

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!

Comments (52)

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

  1. Christian Ullenboom says:
    February 20th, 2008 at 2:15 am

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

  2. pmularien says:
    February 20th, 2008 at 6:11 am

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

  3. newbie says:
    February 20th, 2008 at 2:47 pm

    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:
    February 20th, 2008 at 10:12 pm

    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:
    April 2nd, 2008 at 1:32 pm

    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:
    April 24th, 2008 at 6:06 am

    [...] 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:
    June 6th, 2008 at 11:31 am

    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:
    June 6th, 2008 at 12:25 pm

    Sam,

    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!

    Peter

  9. pmularien says:
    June 9th, 2008 at 7:58 am

    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:
    June 13th, 2008 at 4:54 pm

    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:
    June 13th, 2008 at 5:34 pm

    @ 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!
    Peter

  12. Alex says:
    July 10th, 2008 at 2:54 pm

    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:
    August 20th, 2008 at 9:36 am

    The JSTL 1.2 and UEL 1.0 Api and impl can be downloaded here:
    https://jstl.dev.java.net/
    https://uel.dev.java.net/

    have fun!

    Steven

  14. Rafal Rusin says:
    August 22nd, 2008 at 2:05 am

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

  15. Howard says:
    September 22nd, 2008 at 1:27 am

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

  16. Dennis says:
    November 22nd, 2008 at 7:21 am

    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:
    November 27th, 2008 at 5:13 am

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

  18. cruuzzz says:
    December 1st, 2008 at 10:48 am

    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:
    December 4th, 2008 at 11:10 am

    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:
    December 17th, 2008 at 3:50 pm

    [...] 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:
    March 13th, 2009 at 4:23 pm

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

  22. Pratima says:
    March 25th, 2009 at 10:17 am

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

  23. Kiran says:
    April 11th, 2009 at 9:18 pm

    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
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:920)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

    root cause

    java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config
    org.springframework.web.servlet.support.JstlUtils.exposeLocalizationContext(JstlUtils.java:97)
    org.springframework.web.servlet.view.JstlView.exposeHelpers(JstlView.java:133)
    org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:213)
    org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:258)
    org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1174)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:901)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

  24. Tin says:
    April 12th, 2009 at 11:26 pm

    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:
    April 12th, 2009 at 11:27 pm

    And here’s the site, https://maven-repository.dev.java.net/repository/jstl/jars/

  26. Ignacio de La Madrid says:
    May 15th, 2009 at 7:47 pm

    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:
    May 28th, 2009 at 4:37 pm

    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:
    May 28th, 2009 at 6:19 pm

    @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:
    May 30th, 2009 at 4:06 am

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

    @Tin
    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:
    June 1st, 2009 at 3:58 pm

    @ 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:
    June 14th, 2009 at 4:03 pm

    [...] 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:
    August 27th, 2009 at 7:46 am

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

  33. WeeBay says:
    September 12th, 2009 at 6:48 pm

    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:
    November 11th, 2009 at 3:15 am

    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:
    January 29th, 2010 at 1:07 am

    JSTL 1.2 Jar @ 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:
    March 30th, 2010 at 5:05 am

    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:
    July 15th, 2010 at 12:50 pm

    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:
    July 20th, 2010 at 11:50 pm

    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:
    July 27th, 2010 at 5:22 pm

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

  40. lwpro2 says:
    September 12th, 2010 at 4:14 am

    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:
    October 16th, 2010 at 2:21 pm

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

  42. Colin says:
    November 15th, 2010 at 4:53 pm

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

    javax.servlet
    jstl
    1.2

    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:
    November 15th, 2010 at 4:55 pm

    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:
    January 27th, 2011 at 11:00 pm

    Thank you so much. You saved my day.

  45. sharad says:
    March 16th, 2011 at 12:55 am

    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.

    exception

    org.apache.jasper.JasperException: This absolute uri (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:
    March 26th, 2011 at 3:51 pm

    [...] 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:
    April 22nd, 2011 at 5:30 am

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

  48. Gautham Nookala says:
    April 25th, 2011 at 9:52 am

    Thanks. The JSTL link really helped.

  49. Yatin says:
    May 7th, 2011 at 5:28 am

    @Kiran

    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:
    January 7th, 2012 at 4:56 pm

    thanks for the update, you helped a lot.

  51. Nirup says:
    January 10th, 2012 at 12:14
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.