[MAGNOLIA-3092] freemarker: support for loading taglibs from classpath resources (jars and folders) instead of WEB-INF/lib only Created: 18/Feb/10 Updated: 01/Mar/15 Resolved: 11/Dec/11 |
|
| Status: | Closed |
| Project: | Magnolia |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | 4.5 |
| Type: | Improvement | Priority: | Major |
| Reporter: | Manuel Molaschi | Assignee: | Fabrizio Giustina |
| Resolution: | Fixed | Votes: | 1 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Attachments: |
|
||||||||||||||||||||||||||||
| Issue Links: |
|
||||||||||||||||||||||||||||
| Template: |
|
||||||||||||||||||||||||||||
| Acceptance criteria: |
Empty
|
||||||||||||||||||||||||||||
| Task DoD: |
[ ]*
Doc/release notes changes? Comment present?
[ ]*
Downstream builds green?
[ ]*
Solution information and context easily available?
[ ]*
Tests
[ ]*
FixVersion filled and not yet released
[ ] 
Architecture Decision Record (ADR)
|
||||||||||||||||||||||||||||
| Date of First Response: | |||||||||||||||||||||||||||||
| Description |
|
it would be useful to have freemarker loading taglibs from classpath resources (jars and folders) instead of WEB-INF/lib only. If it's fine for you, i can commit it. PS: i've submitted the patch to freemarker (http://sourceforge.net/tracker/index.php?func=detail&aid=2954132&group_id=794&atid=100794#) |
| Comments |
| Comment by Philipp Bärfuss [ 04/Aug/11 ] |
|
The methods we would like to override are private and I don't like to copy bigger parts of the code. But we followed a different approach in the AbstractRenderTestCase. We fake the existence of the jars in WEB-INF/lib by mocking the servlet context. We could do the same thing in the FreemarkerHelper.addTaglibSupportData(Map<String, Object>, WebContext) |
| Comment by Philipp Bärfuss [ 04/Aug/11 ] |
|
see AbstractRenderTestCase.createFreemarkerFriendlyServletContext() the following changes had to be done:
|
| Comment by Danilo Ghirardelli [ 07/Sep/11 ] |
|
There is an updated patch for the same problem, hoping that freemarkers developer would consider it someday: Anyway, the idea of "tricking" freemarker with a wrapped context is good, but I don't exactly like it, first because the problem is within the library, and second because I'm not really sure you can "trick" freemarker with only the wrapped context for every case, but that's just a sensation... |
| Comment by Danilo Ghirardelli [ 09/Sep/11 ] |
|
I'm sorry, I attached the patch and commented the linked issue by mistake, I'll re-attach everything on this... Just to refute myself, I attached a patch to do what Philipp suggested. The attached patch wraps freemarker and tricks it to load jars from all the classpath when they are requested under WEB-INF/lib. This make possible working with freemarker in Magnolia directly under eclipse, without deploying. Just to be clear, this patch is inspired by the freemarker patch linked above, so credits goes to the original creator. |
| Comment by Fabrizio Giustina [ 11/Dec/11 ] |
|
After playing a bit with the patch I realized it doesn't completely solve the issue described in the original There are actually 2 problems with the freemarker handling of tlds: The FreemarkerServletContextWrapper implemented here only solves the first issue, but this is not enough. While working with the Magnolia community code, for example, all the taglibs are not inside a jar but expanded in the "generated-resources/xdoclet" directory. Unfortunately it looks like the second issue can't be solved without extending freemarker TagLibFactory: looking at the original code it's clear that is just throws away any path that doesn't refer to a jar (and so also most of the resouce-scanning code in FreemarkerServletContextWrapper is actually useless): private void getLocationsFromLibJars() throws ParserConfigurationException, IOException, SAXException
{
Set libs = ctx.getResourcePaths("/WEB-INF/lib");
for (Iterator iter = libs.iterator(); iter.hasNext();) {
String path = (String) iter.next();
if(path.endsWith(".jar") || path.endsWith(".zip")) {
... // check for tlds
Although according to jsp specs also tlds expanded into WEB-INF and subdirectories should be loaded automatically freemarker does't seem to support this, so we cannot either use this to trick it (the "load resources from workspaces" in the eclipse tomcat adapter works by faking WEB-INF/xxx.tld paths for any tld found in classpath and outside jars). So, although I totally agree with Philipp and I wouldn't go for replacing taglibfactory copying a large part of the code due to lack of extensibility, that looks the only way. I don't really like the solution but the issue is pretty important for any eclipse user out there and it is here unsolved for nearly 2 years... speaking about myself I realized that until now I copied the patched taglibfactory over a dozen of projects, always running into this issue. Said so, I'll try to cleanup the taglibfactory-based patch as more as possible so that it can be included, I can't see any other working solution... |
| Comment by Danilo Ghirardelli [ 11/Dec/11 ] |
|
The patch was written with freemarker 2.3.18, in which they slightly refactored their TaglibFactory. The little changes they did are not enough to solve our problem directly, but are enough to make this patch works as intended. |
| Comment by Fabrizio Giustina [ 11/Dec/11 ] |
|
wow, looks like part of the issue has been actually solved in freemarker 2.3.18 (trunk is using 2.3.16 at the moment): while it doesn't actually fix this issue it should help in solving the problem by wrapping the servlet context instead of patching everything as explained in the last comment... upgrading could be a better solution, I'll try to get through this path. |
| Comment by Fabrizio Giustina [ 11/Dec/11 ] |
|
Done! |
| Comment by Danilo Ghirardelli [ 11/Jul/12 ] |
|
Is there any chance to have this backported also in the 4.4.x branch? |
| Comment by Daniel Dekany [ 01/Mar/15 ] |
|
You don't need to patch FreeMarker anymore to have this feature. Since 2.3.22, the requested behavior can be activated with an init-param to FreemarkerServlet: <init-param> <param-name>MetaInfTldSources</param-name> <param-value>classpath</param-value> </init-param> Or, as this behavior is probably only desirable when running the application from under Eclipse without deploying it, you can set this system property in the Eclipse run configuration: -Dorg.freemarker.jsp.metaInfTldSources=classpath Or, if you want this to be the default (but beware, this behavior differs from what the JSP specification requests), you can extend FreemarkerServlet and override createDefaultMetaInfTldSources like: @Override
protected List<MetaInfTldSource> createDefaultMetaInfTldSources() {
return Collections.singletonList(
new ClasspathMetaInfTldSource(Pattern.compile(".*", Pattern.DOTALL)));
}
|