views:

64

answers:

1

I am currently upgrading our application from Webwork to Struts2. Today I run into strange error: displayTag stopped 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?

A: 

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
Ula Krukar