Menu

#340 Freemarker cannot resolve Taglib URIs

2.3.22
closed-fixed
nobody
5
2015-02-28
2011-01-13
Cefn Hoile
No

I have the Stripes quickstart example working as a JSP perfectly well, but any attempt to use the Freemarker equivalent in the same container fails because Freemarker's taglib loading is unable to resolve the Stripes taglib URI.

The two guides describing how to create the same toy app with JSP and Freemarker are available here...
http://www.stripesframework.org/display/stripes/Quick+Start+Guide JSP
http://www.stripesframework.org/display/stripes/FreeMarker+with+Stripes Freemarker

However whilst the JSP example 'just works', Freemarker's JSPTagLib hash is unable to resolve the URI for the Stripes library by default. It reports...

>>>>>>>>>

Could not find webapp resource /WEB-INF/lib/stripes.tld
The problematic instruction:
----------
==> assignment: s=JspTaglibs["http://stripes.sourceforge.net/stripes.tld"] [on line 2, column 1 in calculator.ftl]
[...]
freemarker.template.TemplateModelException: Could not find webapp resource /WEB-INF/lib/stripes.tld
at freemarker.ext.jsp.TaglibFactory.loadTaglib(TaglibFactory.java:432)
[...]

<<<<<<<<<<<

I figure since the JSP example can resolve the Taglib URI perfectly well inside the same container then Freemarker is broken.

I found two workarounds for Freemarker which seem to fix the problem...

WORKAROUND 1

Extract the stripes.tld file from the stripes jar (this is where the JSP logic loads it from) and put it in WEB-INF/lib, then add this to your web.xml

<!-- CEFNHOILE Required to work around limitation in Freemarker's bespoke taglib engine (not loading tlds from classpath Jars) -->
<taglib>
<taglib-uri>http://stripes.sourceforge.net/stripes.tld</taglib-uri>
<taglib-location>/WEB-INF/lib/stripes.tld</taglib-location>
</taglib>

WORKAROUND 2

Put a copy of the stripes jar inside WEB-INF/lib

Both of these are pretty nasty, since
a) you shouldn't have to do them at all,
b) there are now two copies of the taglib declaration files or stripes.jar flying about, one read by freemarker and the other by JVM and JSP

Can Freemarker either use the established loaders for JSP taglibs, rather than rolling their own, or add the standard behaviour to their own loader (look inside jars on the classpath for .tld files)?

At the very least can someone urgently add an error message to the handler so that this request fails with something meaningful like 'Freemarker requires the tld or .jar file for your taglib in WEB-INF/lib' The web is full of people who have asked this question, got no response and presumably given up.

Discussion

  • Cefn Hoile

    Cefn Hoile - 2011-01-13

    Didn't copy paste the original error, but another error which arose whilst trying to reverse the workaround changes I'd made.

    The original error before attempting any workarounds was...

    Error on line 2, column 1 in calculator.ftl
    JspTaglibs["http://stripes.sourceforge.net/stripes.tld"] is undefined.
    It cannot be assigned to s
    The problematic instruction:
    ----------
    ==> assignment: s=JspTaglibs["http://stripes.sourceforge.net/stripes.tld"] [on line 2, column 1 in calculator.ftl]
    ----------

     
  • Dániel Dékány

    The JSP 2.2. specification requires that TLD-s are searched inside jar-s in WEB-INF/lib, but not in general in the classpath. I don't know in what setup did the OP run his application, where did he put stripes.jar if not into WEB-INF/lib (where it should be put per spec), and what servlet container specific trick made JSP find that TLD in stripes.jar. For Jetty for example you can specify a pattern of jar-s in the classpath that it will search for TLD-s, but it's totally Jetty-specific. Certainly Tomcat has its own tricks too. I don't know of any published APIs through which we could tap on the taglib resolution mechanism of the container.

    FreeMarker 2.3.22 improves the situation:

    • It has its own "extension" of the standard search procedure, configurable through the MetaInfTldSources and ClasspathTlds init-params of FreemarkerServlet. Setting MetaInfTldSources to classpath will just ignore the standard and search for META-INF/**/*.tld everywhere. Setting it to webInfPerLibJars, classpath:.*stripes.*\.jar$ is a less brutal solution.

    • It recognized Jetty-s respectable setting, and automatically appends it to MetaInfTldSources

    So I'm going to close this when 2.3.22 is out.

     
  • Dániel Dékány

    • status: open --> open-fixed
    • Group: --> 2.3.22
     
  • Dániel Dékány

    • Status: open-fixed --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB