Re: Data model traverse

Daniel Dekany <[email protected]>
Newsgroups gmane.comp.web.freemarker.user
Message-ID <[email protected]>
Monday, March 30, 2009, 4:37:31 PM, wkbutler wrote:
>
>
> Daniel Dekany wrote:
>> 
>>>Saturday, March 28, 2009, 12:48:36 AM, Daniel Dekany wrote:
>>>> Friday, March 27, 2009, 5:44:46 PM, wkbutler wrote:
>>>>>
>>>>> Thanks Daniel.  Maybe data_model has been overridden then, because when
>>>>> I use
>>>>> your suggestion this is the error I encounter:
>>>>>
>>>>> Caused by: freemarker.template.TemplateException: Expected extended
>>>>> hash.
>>>>> .data_model evaluated instead to freemarker.co
>>>>> re.Environment$1 on line 3, column 10 in
>>>>> appfuse/web/struts/action-test.ftl.
>>>>>         at
>>>>> freemarker.core.TemplateObject.invalidTypeException(TemplateObject.java:135)
>>>>>         at
>>>>> freemarker.core.BuiltIn$keysBI._getAsTemplateModel(BuiltIn.java:594)
>>>>>         at
>>>>> freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
>>>>>         at freemarker.core.IteratorBlock.accept(IteratorBlock.java:87)
>>>>>         at freemarker.core.Environment.visit(Environment.java:196)
>>>>>         at freemarker.core.MixedContent.accept(MixedContent.java:92)
>>>>>         at freemarker.core.Environment.visit(Environment.java:196)
>>>>>         at freemarker.core.Environment.process(Environment.java:176)
>>>>>         at freemarker.template.Template.process(Template.java:232)
>>>>>         at
>>>>> org.hibernate.tool.hbm2x.TemplateHelper.processTemplate(TemplateHelper.java:255)
>>>>
>>>> Now that's magical, in a bad way. What does ${.version} print? Because
>>>> it seems I will have to find out what Envionment$1 is... (Currently
>>>> it's a TemplateDirectiveBody, and I could achieve this error message
>>>> with a trick, but the stack trace doesn't suggest that the error was
>>>> achieved with my trick...) Can you access any data-model variables at
>>>> all in this template? I guess you can't.
>>>
>>>Anyway, a quick guess... I remember that in some older FM versions the
>>>data-model wasn't TemplateHashModelEx. So maybe it's an old FM
>>>version, and there Environment$1 was some anonymous TemplateHashModel
>>>used to wrap the data-model... So, replace freemarker.jar with a
>>>recent one, and if the problem goes away, then that was it.
>>>
>> 
>
>
> We are running struts2-core 2.0.11, which uses FM 2.3.8. Upgrading to struts
> 2.1.x would get us up to FM 2.3.13, which could be worthwhile.  The
> ${.version} tag confirmed the runtime version at 2.3.8.

.data_model?keys works (in most cases) starting from 2.3.11 only
(http://freemarker.org/docs/versions_2_3_11.html). But, at least
technically, you don't need to update Struts for updating FreeMarker,
since the 2.3-series keep backward compatibility. Just add FreeMarker
2.3.15 as a project dependency... if you are using Maven or Ivy, that
is.

> And sorry, I did not divulge this at the outset, but FM is being invoked
> here by hibernate3's hbm2java tool. 
>
> So, in fact the data model objects are accessible.

Yeah, that was expected after I realized what the problem was.

> Here is what I believe to
> be the relevant source:
>
>     protected Configuration freeMarkerEngine;
>     protected SimpleHash getContext()
>     {
>         return context;
>     }
>     public void setupContext()
>     {
>         getContext().put("version", Version.getDefault());
>         getContext().put("ctx", getContext());
>         getContext().put("templates", new Templates());
>         getContext().put("date", new SimpleDate(new Date(), 3));
>     }
>     public void processTemplate(String templateName, Writer output, String
> rootContext)
>     {
>         if(rootContext == null)
>             rootContext = "Unknown context";
>         try
>         {
>             Template template =
> freeMarkerEngine.getTemplate(templateName);
>             template.process(getContext(), output);
>         }
>         catch(IOException e)
>         ...
>     }
>
> I think the rootContext is getting passed as a fully-qualified class name.
>
> Anyhow if I use the following trace:
>
>     Version: ${.version}
>     The version variable in the data-model: ${version}
>     The templates variable in the data-model: ${templates}
>     The date variable in the data-model: ${date}
>
>     The variables in the ctx data-model are:
>       <#list ctx?keys as key>

Indeed, you are lucky here as the data-model is put into itself(!)
with name "ctx" in this application, so that's a workaround...

>         ${key?html}
>       </#list>
>
> I get...
>
>     Version: 2.3.8
>     The version variable in the data-model: 3.2.2.GA
>     The templates variable in the data-model:
> org.hibernate.tool.hbm2x.TemplateHelper$Templates@133926
>     The date variable in the data-model: Mar 30, 2009 9:53:07 AM
>
>     The variables in the ctx data-model are:
>         com.h4h.model.RateProgram
>         basepackage
>         data
>         ...rest of my data model...
>
>
> and if I iterate over the keys of ${version} and ${templates}, the keys are
> the get methods of those objects. No surprise there, I suppose. But, this
> helps a lot because now I have a path to examining and modifying the data
> model.
>
> So I understand how this is working much better.  When I get struts updated
> I will try to re-test and see if .data_model becomes available.  
>
> Otherwise, I guess we can conclude that the clever lads at hibernate have
> not done anything so exotic with FM, right?

Not to my knowledge...

> "Pretty standard, really". Thanks for all your help Daniel. Hope
> this helps someone else too.
>
> Kent

-- 
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.