开发者

Struts2 + Freemarker + DisplayTag: how to make it work

开发者 https://www.devze.com 2023-01-07 07:09 出处:网络
I am currently upgrading our application from Webwork to Struts2. Today I run into strange error: displayTag s开发者_如何学运维topped working after the upgrade.

I am currently upgrading our application from Webwork to Struts2. Today I run into strange error: displayTag s开发者_如何学运维topped working after the upgrade.

This is a snipped from my FTL file:

<#assign display=JspTaglibs["http://displaytag.sf.net"]>

<@s.set name="entries" value="historyEntries" scope="page"/>

<@display.table class="data" name="pageScope.entries" sort="list" 
      pagesize=30 id="entry" defaultsort=5 defaultorder="descending">
  <@display.column property="folderName" title="Folder" sortable=true/>
</@display.table>

The error I get is:

freemarker.template.TemplateModelException:   
javax.servlet.jsp.JspException: Exception:   
[.LookupUtil] Error looking up property "folderName" 
in object type "freemarker.template.SimpleSequence". 
Cause: Unknown property 'folderName'

Standard struts tags are working correctly, I have JspSupportServlet added in my configuration. Any idead why this isn't working?


I found a way to solve this (not sure if it the only way or if it is the best, worked for me though).

The root of the problem was that freemarker.template.SimpleSequence does not out-of-the-box implement any standard Collections API, it is not a Collection, Enumerable etc.

In order to solve this I created custom FreemarkerManager and provided custom BeansWrapper:

@Override
protected BeansWrapper getObjectWrapper() {
    BeansWrapper wrapper = super.getObjectWrapper();
    class CustomBeansWrapper extends BeansWrapper {
        private BeansWrapper internalWrapper;

        public Xp2BeansWrapper(BeansWrapper wrapper) {
            this.internalWrapper = wrapper;
        }

        //delegate methods


        public TemplateModel wrap(Object object) throws TemplateModelException {
            TemplateModel model = internalWrapper.wrap(object);
            if (model instanceof SimpleSequence) {
                class SimpleSequenceWithIterator extends SimpleSequence {
                    private SimpleSequence internalSequence;
                    public SimpleSequenceWithIterator(SimpleSequence sequence) {
                        this.internalSequence = sequence;
                    }

                    //delegate methods

                    //IteratorUtils from Apache Commons is used internally 
                    //by DisplayTag library, it can use public iterator() method
                    public Iterator iterator() throws TemplateModelException {
                        return toList().iterator();
                    }

                }
                return new SimpleSequenceWithIterator((SimpleSequence) model);
            }
            return model;
        }


    }
    return new CustomBeansWrapper(wrapper);

}

Now I just needed to change one setting in struts.properties:

struts.freemarker.manager.classname=xyz.CustomFreemarkerManager


You can also certify if your deployment copy all dependecies to WEB-INF/lib. TaglibFactory searches every TLD under /META-INF/ inside jar there.

Take a look at https://stackoverflow.com/a/37092269/1113510

0

精彩评论

暂无评论...
验证码 换一张
取 消